diff -Nru meson-0.53.2/contributing.md meson-0.61.2/contributing.md --- meson-0.53.2/contributing.md 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/contributing.md 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,8 @@ +## Contributing to the Meson build system + +Thank you for your interest in participating to the development! +A large fraction of Meson is contributed by people outside +the core team and we are *excited* to see what you do. + +**Contribution instructions can be found on the website** + @ https://mesonbuild.com/Contributing.html diff -Nru meson-0.53.2/cross/arm64cl.txt meson-0.61.2/cross/arm64cl.txt --- meson-0.53.2/cross/arm64cl.txt 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/cross/arm64cl.txt 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,17 @@ +[binaries] +c = 'cl' +cpp = 'cl' +ar = 'lib' +windres = 'rc' + +[built-in options] +c_args = ['-DWINAPI_FAMILY=WINAPI_FAMILY_APP'] +c_link_args = ['-APPCONTAINER', 'WindowsApp.lib'] +cpp_args = ['-DWINAPI_FAMILY=WINAPI_FAMILY_APP'] +cpp_link_args = ['-APPCONTAINER', 'WindowsApp.lib'] + +[host_machine] +system = 'windows' +cpu_family = 'aarch64' +cpu = 'armv8' +endian = 'little' diff -Nru meson-0.53.2/cross/armcc.txt meson-0.61.2/cross/armcc.txt --- meson-0.53.2/cross/armcc.txt 2018-08-25 08:05:43.000000000 +0000 +++ meson-0.61.2/cross/armcc.txt 2021-04-01 21:12:21.000000000 +0000 @@ -7,7 +7,7 @@ ar = 'armar' strip = 'armar' -[properties] +[built-in options] # The '--cpu' option with the appropriate target type should be mentioned # to cross compile c/c++ code with armcc,. c_args = ['--cpu=Cortex-M0plus'] diff -Nru meson-0.53.2/cross/armclang-linux.txt meson-0.61.2/cross/armclang-linux.txt --- meson-0.53.2/cross/armclang-linux.txt 2020-01-07 19:29:59.000000000 +0000 +++ meson-0.61.2/cross/armclang-linux.txt 2021-04-01 21:12:21.000000000 +0000 @@ -12,7 +12,7 @@ # Armcc is only available in toolchain version 5. # Armclang is only available in toolchain version 6. # Start shell with /opt/arm/developmentstudio-2019.0/bin/suite_exec zsh -# Now the compilers will work. +# Now the compilers will work. [binaries] # we could set exe_wrapper = qemu-arm-static but to test the case @@ -24,8 +24,7 @@ #strip = '/usr/arm-linux-gnueabihf/bin/strip' #pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' -[properties] - +[built-in options] c_args = ['--target=aarch64-arm-none-eabi'] [host_machine] diff -Nru meson-0.53.2/cross/armclang.txt meson-0.61.2/cross/armclang.txt --- meson-0.53.2/cross/armclang.txt 2018-08-25 08:05:43.000000000 +0000 +++ meson-0.61.2/cross/armclang.txt 2021-04-01 21:12:21.000000000 +0000 @@ -7,7 +7,7 @@ ar = 'armar' strip = 'armar' -[properties] +[built-in options] # The '--target', '-mcpu' options with the appropriate values should be mentioned # to cross compile c/c++ code with armclang. c_args = ['--target=arm-arm-none-eabi', '-mcpu=cortex-m0plus'] diff -Nru meson-0.53.2/cross/c2000.txt meson-0.61.2/cross/c2000.txt --- meson-0.53.2/cross/c2000.txt 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/cross/c2000.txt 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,28 @@ +# This file assumes that path to the Texas Instruments C20000 toolchain is added +# to the environment(PATH) variable, so that Meson can find +# cl2000 and ar2000 while building. +[binaries] +c = 'cl2000' +ar = 'ar2000' +strip = 'cl2000' + +[host_machine] +system = 'bare metal' +cpu_family = 'c2000' +cpu = 'c28x' +endian = 'little' + +[built-in options] +c_args = [ + '-v28', + '-ml', + '-mt'] +c_link_args = [ + '-z', + '--rom_model', + '\f28004x_flash.cmd'] +cpp_args = [] +cpp_link_args = [] + +[properties] +needs_exe_wrapper = true diff -Nru meson-0.53.2/cross/ccomp-armv7a.txt meson-0.61.2/cross/ccomp-armv7a.txt --- meson-0.53.2/cross/ccomp-armv7a.txt 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/cross/ccomp-armv7a.txt 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,13 @@ +[binaries] +c = 'ccomp' +ar = 'ccomp' +strip = 'strip' + +[built-in options] +c_args = ['-target', 'armv7a-eabi', '-fall'] + +[host_machine] +system = 'bare metal' # Update with your system name - bare metal/OS. +cpu_family = 'arm' +cpu = 'Cortex-A9' +endian = 'little' diff -Nru meson-0.53.2/cross/ccrx.txt meson-0.61.2/cross/ccrx.txt --- meson-0.53.2/cross/ccrx.txt 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/cross/ccrx.txt 2021-04-01 21:12:21.000000000 +0000 @@ -7,7 +7,7 @@ ar = 'rlink' strip = 'rlink' -[properties] +[built-in options] # The '--cpu' option with the appropriate target type should be mentioned # to cross compile c/c++ code with ccrx,. c_args = ['-cpu=rx600'] diff -Nru meson-0.53.2/cross/iphone.txt meson-0.61.2/cross/iphone.txt --- meson-0.53.2/cross/iphone.txt 2017-05-24 16:55:14.000000000 +0000 +++ meson-0.61.2/cross/iphone.txt 2021-11-02 19:58:07.000000000 +0000 @@ -5,23 +5,26 @@ [binaries] c = 'clang' cpp = 'clang++' +objc = 'clang' +objcpp = 'clang++' ar = 'ar' strip = 'strip' +[built-in options] +c_args = ['-arch', 'arm64', '-miphoneos-version-min=11.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +cpp_args = ['-arch', 'arm64', '-miphoneos-version-min=11.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +c_link_args = ['-arch', 'arm64', '-miphoneos-version-min=11.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +cpp_link_args = ['-arch', 'arm64', '-miphoneos-version-min=11.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +objc_args = ['-arch', 'arm64', '-miphoneos-version-min=11.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +objcpp_args = ['-arch', 'arm64', '-miphoneos-version-min=11.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] + [properties] root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer' - -c_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] -cpp_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] -c_link_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] -cpp_link_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] - has_function_printf = true has_function_hfkerhisadf = false [host_machine] system = 'darwin' -cpu_family = 'arm' -cpu = 'armv7' +cpu_family = 'aarch64' +cpu = 'aarch64' endian = 'little' - diff -Nru meson-0.53.2/cross/linux-mingw-w64-32bit.json meson-0.61.2/cross/linux-mingw-w64-32bit.json --- meson-0.53.2/cross/linux-mingw-w64-32bit.json 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/cross/linux-mingw-w64-32bit.json 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "file": "linux-mingw-w64-32bit.txt", + "tests": ["common", "cmake"], + "env": { + "WINEPATH": "/usr/lib/gcc/i686-w64-mingw32/9.2-posix;/usr/i686-w64-mingw32/bin;/usr/i686-w64-mingw32/lib" + } +} diff -Nru meson-0.53.2/cross/linux-mingw-w64-32bit.txt meson-0.61.2/cross/linux-mingw-w64-32bit.txt --- meson-0.53.2/cross/linux-mingw-w64-32bit.txt 2020-01-23 22:34:28.000000000 +0000 +++ meson-0.61.2/cross/linux-mingw-w64-32bit.txt 2021-04-01 21:13:00.000000000 +0000 @@ -1,12 +1,14 @@ [binaries] c = '/usr/bin/i686-w64-mingw32-gcc' cpp = '/usr/bin/i686-w64-mingw32-g++' +objc = '/usr/bin/i686-w64-mingw32-gcc' ar = '/usr/bin/i686-w64-mingw32-ar' strip = '/usr/bin/i686-w64-mingw32-strip' pkgconfig = '/usr/bin/i686-w64-mingw32-pkg-config' windres = '/usr/bin/i686-w64-mingw32-windres' exe_wrapper = 'wine' ld = '/usr/bin/i686-w64-mingw32-ld' +cmake = '/usr/bin/cmake' [properties] # Directory that contains 'bin', 'lib', etc @@ -19,3 +21,11 @@ cpu_family = 'x86' cpu = 'i686' endian = 'little' + +[cmake] + +CMAKE_BUILD_WITH_INSTALL_RPATH = 'ON' +CMAKE_FIND_ROOT_PATH_MODE_PROGRAM = 'NEVER' +CMAKE_FIND_ROOT_PATH_MODE_LIBRARY = 'ONLY' +CMAKE_FIND_ROOT_PATH_MODE_INCLUDE = 'ONLY' +CMAKE_FIND_ROOT_PATH_MODE_PACKAGE = 'ONLY' diff -Nru meson-0.53.2/cross/linux-mingw-w64-64bit.json meson-0.61.2/cross/linux-mingw-w64-64bit.json --- meson-0.53.2/cross/linux-mingw-w64-64bit.json 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/cross/linux-mingw-w64-64bit.json 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "file": "linux-mingw-w64-64bit.txt", + "tests": ["common", "cmake"], + "env": { + "WINEPATH": "/usr/lib/gcc/x86_64-w64-mingw32/9.2-posix;/usr/x86_64-w64-mingw32/bin;/usr/x86_64-w64-mingw32/lib" + } +} diff -Nru meson-0.53.2/cross/linux-mingw-w64-64bit.txt meson-0.61.2/cross/linux-mingw-w64-64bit.txt --- meson-0.53.2/cross/linux-mingw-w64-64bit.txt 2018-08-25 08:05:43.000000000 +0000 +++ meson-0.61.2/cross/linux-mingw-w64-64bit.txt 2021-04-01 21:13:00.000000000 +0000 @@ -1,11 +1,13 @@ [binaries] c = '/usr/bin/x86_64-w64-mingw32-gcc' cpp = '/usr/bin/x86_64-w64-mingw32-g++' +objc = '/usr/bin/x86_64-w64-mingw32-gcc' ar = '/usr/bin/x86_64-w64-mingw32-ar' strip = '/usr/bin/x86_64-w64-mingw32-strip' pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config' windres = '/usr/bin/x86_64-w64-mingw32-windres' exe_wrapper = 'wine64' +cmake = '/usr/bin/cmake' [properties] # Directory that contains 'bin', 'lib', etc @@ -18,3 +20,11 @@ cpu_family = 'x86_64' cpu = 'x86_64' endian = 'little' + +[cmake] + +CMAKE_BUILD_WITH_INSTALL_RPATH = 'ON' +CMAKE_FIND_ROOT_PATH_MODE_PROGRAM = 'NEVER' +CMAKE_FIND_ROOT_PATH_MODE_LIBRARY = 'ONLY' +CMAKE_FIND_ROOT_PATH_MODE_INCLUDE = 'ONLY' +CMAKE_FIND_ROOT_PATH_MODE_PACKAGE = 'ONLY' diff -Nru meson-0.53.2/cross/none.txt meson-0.61.2/cross/none.txt --- meson-0.53.2/cross/none.txt 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/cross/none.txt 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,18 @@ +# native file used to make the build machine compiler unusable + +[host_machine] +system = 'none' +cpu_family = 'none' +cpu = 'none' +endian = 'little' + +[properties] + +[binaries] +c = ['false'] +cpp = ['false'] +objc = ['false'] +objcpp = ['false'] +ar = ['false'] +pkgconfig = ['false'] +cmake = ['false'] diff -Nru meson-0.53.2/cross/ownstdlib.txt meson-0.61.2/cross/ownstdlib.txt --- meson-0.53.2/cross/ownstdlib.txt 2016-05-28 14:39:38.000000000 +0000 +++ meson-0.61.2/cross/ownstdlib.txt 2021-04-01 21:12:21.000000000 +0000 @@ -10,4 +10,4 @@ [properties] -c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, dependency name +c_stdlib = 'mylibc' # Subproject name diff -Nru meson-0.53.2/cross/tvos.txt meson-0.61.2/cross/tvos.txt --- meson-0.53.2/cross/tvos.txt 2019-06-16 18:54:18.000000000 +0000 +++ meson-0.61.2/cross/tvos.txt 2021-11-02 19:58:07.000000000 +0000 @@ -8,14 +8,15 @@ ar = 'ar' strip = 'strip' -[properties] -root = '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer' - +[built-in options] c_args = ['-arch', 'arm64', '-mtvos-version-min=12.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] cpp_args = ['-arch', 'arm64', '-mtvos-version-min=12.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] c_link_args = ['-arch', 'arm64', '-mtvos-version-min=12.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] cpp_link_args = ['-arch', 'arm64', '-mtvos-version-min=12.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] +[properties] +root = '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer' + has_function_printf = true has_function_hfkerhisadf = false @@ -24,4 +25,3 @@ cpu_family = 'arm' cpu = 'arm64' endian = 'little' - diff -Nru meson-0.53.2/cross/ubuntu-armhf.json meson-0.61.2/cross/ubuntu-armhf.json --- meson-0.53.2/cross/ubuntu-armhf.json 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/cross/ubuntu-armhf.json 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "file": "ubuntu-armhf.txt", + "tests": ["common"], + "env": {} +} diff -Nru meson-0.53.2/cross/ubuntu-armhf.txt meson-0.61.2/cross/ubuntu-armhf.txt --- meson-0.53.2/cross/ubuntu-armhf.txt 2020-01-23 22:34:28.000000000 +0000 +++ meson-0.61.2/cross/ubuntu-armhf.txt 2021-04-01 21:12:21.000000000 +0000 @@ -9,15 +9,19 @@ pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' ld = '/usr/bin/arm-linux/gnueabihf-ld' -[properties] -root = '/usr/arm-linux-gnueabihf' +[built-in options] # Used in unit test '140 get define' c_args = ['-DMESON_TEST_ISSUE_1665=1'] cpp_args = '-DMESON_TEST_ISSUE_1665=1' +[properties] +root = '/usr/arm-linux-gnueabihf' + has_function_printf = true has_function_hfkerhisadf = false +skip_sanity_check = true + [host_machine] system = 'linux' cpu_family = 'arm' diff -Nru meson-0.53.2/cross/wasm.txt meson-0.61.2/cross/wasm.txt --- meson-0.53.2/cross/wasm.txt 2019-08-28 17:15:38.000000000 +0000 +++ meson-0.61.2/cross/wasm.txt 2021-11-02 19:58:07.000000000 +0000 @@ -1,13 +1,12 @@ [binaries] -c = '/home/jpakkane/emsdk/fastcomp/emscripten/emcc' -cpp = '/home/jpakkane/emsdk/fastcomp/emscripten/em++' -ar = '/home/jpakkane/emsdk/fastcomp/emscripten/emar' +c = '/home/jpakkane/src/emsdk/upstream/emscripten/emcc' +cpp = '/home/jpakkane/src/emsdk/upstream/emscripten/em++' +ar = '/home/jpakkane/src/emsdk/upstream/emscripten/emar' -[properties] - -c_args = ['-s', 'WASM=1', '-s', 'EXPORT_ALL=1'] +[built-in options] +c_args = [] c_link_args = ['-s','EXPORT_ALL=1'] -cpp_args = ['-s', 'WASM=1', '-s', 'EXPORT_ALL=1'] +cpp_args = [] cpp_link_args = ['-s', 'EXPORT_ALL=1'] [host_machine] @@ -16,4 +15,3 @@ cpu_family = 'wasm32' cpu = 'wasm32' endian = 'little' - diff -Nru meson-0.53.2/cross/xc16.txt meson-0.61.2/cross/xc16.txt --- meson-0.53.2/cross/xc16.txt 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/cross/xc16.txt 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,26 @@ +# This file assumes that path to the Microchip xc16 toolchain is added +# to the environment(PATH) variable, so that Meson can find +# xc16-gcc and xc16-ar while building. +[binaries] +c = 'xc16-gcc' +ar = 'xc16-ar' +strip = 'xc16-gcc' + +[host_machine] +system = 'bare metal' +cpu_family = 'dspic' +cpu = '33ep64mc203' +endian = 'little' + +[properties] +needs_exe_wrapper = true + +[built-in options] +c_args = [ + '-c', + '-mcpu=33EP64MC203', + '-omf=elf'] +c_link_args = [ + '-mcpu=33EP64MC203', + '-omf=elf', + '-Wl,--script=p33EP64MC203.gld,'] diff -Nru meson-0.53.2/data/.coveragerc.in meson-0.61.2/data/.coveragerc.in --- meson-0.53.2/data/.coveragerc.in 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/data/.coveragerc.in 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,25 @@ +[run] +branch = True +parallel = True +concurrency = multiprocessing +data_file = @ROOT@/.coverage/coverage +source = @ROOT@/mesonbuild/ + +[report] +exclude_lines = + if T.TYPE_CHECKING: + +[paths] +mesonbuild = + mesonbuild/ + __w/meson/meson/mesonbuild/ + @ROOT@/mesonbuild/ + +[html] +directory = @ROOT@/.coverage/html + +[xml] +output = @ROOT@/.coverage/coverage.xml + +[json] +output = @ROOT@/.coverage/coverage.json diff -Nru meson-0.53.2/data/macros.meson meson-0.61.2/data/macros.meson --- meson-0.53.2/data/macros.meson 2019-05-02 18:59:50.000000000 +0000 +++ meson-0.61.2/data/macros.meson 2020-08-15 16:27:05.000000000 +0000 @@ -2,12 +2,6 @@ %__meson_wrap_mode nodownload %__meson_auto_features enabled -%_smp_mesonflags %([ -z "$MESON_BUILD_NCPUS" ] \\\ - && MESON_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"; \\\ - ncpus_max=%{?_smp_ncpus_max}; \\\ - if [ -n "$ncpus_max" ] && [ "$ncpus_max" -gt 0 ] && [ "$MESON_BUILD_NCPUS" -gt "$ncpus_max" ]; then MESON_BUILD_NCPUS="$ncpus_max"; fi; \\\ - if [ "$MESON_BUILD_NCPUS" -gt 1 ]; then echo "--num-processes $MESON_BUILD_NCPUS"; fi) - %meson \ %set_build_flags \ %{shrink:%{__meson} \ @@ -28,17 +22,24 @@ --wrap-mode=%{__meson_wrap_mode} \ --auto-features=%{__meson_auto_features} \ %{_vpath_srcdir} %{_vpath_builddir} \ - %{nil}} + %{nil}} %meson_build \ - %ninja_build -C %{_vpath_builddir} + %{shrink:%{__meson} compile \ + -C %{_vpath_builddir} \ + -j %{_smp_build_ncpus} \ + --verbose \ + %{nil}} %meson_install \ - %ninja_install -C %{_vpath_builddir} + %{shrink:DESTDIR=%{buildroot} %{__meson} install \ + -C %{_vpath_builddir} \ + --no-rebuild \ + %{nil}} %meson_test \ - %{shrink: %{__meson} test \ + %{shrink:%{__meson} test \ -C %{_vpath_builddir} \ - %{?_smp_mesonflags} \ + --num-processes %{_smp_build_ncpus} \ --print-errorlogs \ - %{nil}} + %{nil}} diff -Nru meson-0.53.2/data/schema.xsd meson-0.61.2/data/schema.xsd --- meson-0.53.2/data/schema.xsd 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/data/schema.xsd 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru meson-0.53.2/data/shell-completions/zsh/_meson meson-0.61.2/data/shell-completions/zsh/_meson --- meson-0.53.2/data/shell-completions/zsh/_meson 2019-03-10 17:10:57.000000000 +0000 +++ meson-0.61.2/data/shell-completions/zsh/_meson 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,4 @@ -#compdef meson mesonconf=meson-configure mesontest=meson-test mesonintrospect=meson-introspect +#compdef meson # vim:ts=2 sw=2 @@ -32,13 +32,55 @@ local __meson_backends="(ninja xcode ${(j. .)${:-vs{,2010,2015,2017}}})" local __meson_build_types="(plain debug debugoptimized minsize release)" local __meson_wrap_modes="(WrapMode.{default,nofallback,nodownload,forcefallback})" +local __meson_dist_formats=("xztar" "gztar" "zip") +local __meson_cd='-C[change into this directory before running]:target dir:_directories' +local -a __meson_common=( + '--prefix=[installation prefix]: :_directories' + '--bindir=[executable directory]: :_directories' + '--datadir=[data file directory]: :_directories' + '--includedir=[header file directory]: :_directories' + '--infodir=[info page directory]: :_directories' + '--libdir=[library directory]: :_directories' + '--libexecdir=[library executable directory]: :_directories' + '--localedir=[locale data directory]: :_directories' + '--localstatedir=[local state data directory]: :_directories' + '--mandir=[manual page directory]: :_directories' + '--sbindir=[system executable directory]: :_directories' + '--sharedstatedir=[arch-independent data directory]: :_directories' + '--sysconfdir=[system configuration directory]: :_directories' + '--auto-features=[default value for auto features]:auto features types:(auto disabled enabled)' + '--backend=[backend to use]:Meson backend:'"$__meson_backends" + '--buildtype=[build type to use]:Meson build type:'"$__meson_build_types" + '--debug[turn on building with debug]' + '--default-library=[default library type]:default library type:(shared static both)' + '--errorlogs[prints the logs from failing tests]' + '--install-umask=[default umask for permissions of all installed files]' + '--layout=[build directory layout]:build directory layout:(flat mirror)' + '--optimization=[optimization level for compiled targets]:optimization:(0 g 1 2 3 s)' + '--stdsplit=[split stdout and stderr in test logs]' + '--strip[strip targets on install]' + '--unity=[unity builds on/off]:whether to do unity builds:(on off subprojects)' + '--warnlevel=[compiler warning level]:compiler warning level:warning level:(1 2 3)' + '--werror[treat warnings as errors]' + '--wrap-mode=[special wrap mode]:wrap mode:'"$__meson_wrap_modes" + '--force-fallback-for=[force fallback for listed subprojects]' + '--pkg-config-path=[extra paths for HOST pkg-config to search]:paths:_dir_list -s ,' + '--build.pkg-config-path=[extra paths for BUILD pkg-config to search]:paths:_dir_list -s ,' + '--cmake-prefix-path=[extra prefixes for HOST cmake to search]:paths:_dir_list -s ,' + '--build.cmake-prefix-path=[extra prefix for BUILD cmake to search]:paths:_dir_list -s ,' +) local -a meson_commands=( -'setup:set up a build directory' 'configure:configure a project' -'test:run tests' +'dist:generate release archive' +'init:create a new project' +'install:install one more more targets' 'introspect:query project properties' +'setup:set up a build directory' +'test:run tests' 'wrap:manage source dependencies' +'subprojects:manage subprojects' +'compile:Build the project' ) (( $+functions[__meson_is_build_dir] )) || __meson_is_build_dir() { @@ -68,6 +110,21 @@ fi } +(( $+functions[__meson_wrap_names] )) || __meson_wrap_names() { + local rwraps + rwraps="$(_call_program meson meson wrap list)" + local -a wraps=(${(@f)rwraps}) + _describe -t wraps "Meson wraps" wraps +} + +(( $+functions[__meson_installed_wraps] )) || __meson_installed_wraps() { + local rwraps + if rwraps="$(ls subprojects/ | grep '\.wrap$' | cut -d . -f 1)"; then + local -a wraps=(${(@f)rwraps}) + _describe -t wraps "Meson wraps" wraps + fi +} + (( $+functions[_meson_commands] )) || _meson_commands() { _describe -t commands "Meson subcommands" meson_commands } @@ -89,48 +146,30 @@ _arguments \ '*-D-[set the value of a build option]:build option:__meson_build_options' \ - '--prefix=[installation prefix]: :_directories' \ - '--libdir=[library directory]: :_directories' \ - '--libexecdir=[library executable directory]: :_directories' \ - '--bindir=[executable directory]: :_directories' \ - '--sbindir=[system executable directory]: :_directories' \ - '--includedir=[header file directory]: :_directories' \ - '--datadir=[data file directory]: :_directories' \ - '--mandir=[manual page directory]: :_directories' \ - '--infodir=[info page directory]: :_directories' \ - '--localedir=[locale data directory]: :_directories' \ - '--sysconfdir=[system configuration directory]: :_directories' \ - '--localstatedir=[local state data directory]: :_directories' \ - '--sharedstatedir=[arch-independent data directory]: :_directories' \ - '--backend=[backend to use]:Meson backend:'"$__meson_backends" \ - '--buildtype=[build type to use]:Meson build type:'"$__meson_build_types" \ - '--strip[strip targets on install]' \ - '--unity=[unity builds on/off]:whether to do unity builds:(on off subprojects)' \ - '--werror[treat warnings as errors]' \ - '--layout=[build directory layout]:build directory layout:(flat mirror)' \ - '--default-library=[default library type]:default library type:(shared static)' \ - '--warnlevel=[compiler warning level]:compiler warning level:warning level:(1 2 3)' \ - '--stdsplit=[split stdout and stderr in test logs]' \ - '--errorlogs=[prints the logs from failing tests]' \ '--cross-file=[cross-compilation environment description]:cross file:_files' \ - '--wrap-mode=[special wrap mode]:wrap mode:'"$__meson_wrap_modes" \ + '--native-file=[build machine compilation environment description]:native file:_files' \ + '--clearcache[clear cached state]' \ + '--fatal-meson-warnings=[exit when any meson warnings are encountered]' \ + '(-v --version)'{'-v','--version'}'[print the meson version and exit]' \ + '--reconfigure=[re-run build configuration]' \ + '--wipe=[delete saved state and restart using saved command line options]' \ ":$firstd directory:_directories" \ "::$secondd directory:_directories" \ - # + "${(@)__meson_common}" } (( $+functions[_meson-configure] )) || _meson-configure() { local curcontext="$curcontext" # TODO: implement 'mesonconf @file' local -a specs=( - '--clearcache[clear cached state]' '*-D-[set the value of a build option]:build option:__meson_build_options' '::build directory:_directories' ) _arguments \ '(: -)'{'--help','-h'}'[show a help message and quit]' \ - "${(@)specs}" + "${(@)specs}" \ + "${(@)__meson_common}" } (( $+functions[_meson-test] )) || _meson-test() { @@ -138,22 +177,23 @@ # TODO: complete test suites local -a specs=( - '(--quiet -q)'{'--quiet','-q'}'[produce less output to the terminal]' - '(--verbose -v)'{'--verbose','-v'}'[do not redirect stdout and stderr]' - '(--timeout-multiplier -t)'{'--timeout-multiplier','-t'}'[a multiplier for test timeouts]:Python floating-point number: ' - '-C[directory to cd into]: :_directories' '--repeat[number of times to run the tests]:number of times to repeat: ' '--no-rebuild[do not rebuild before running tests]' '--gdb[run tests under gdb]' + '--gdb-path=[program to run for gdb (can be wrapper or compaitble program)]:program:_path_commands' '--list[list available tests]' '(--wrapper --wrap)'{'--wrapper=','--wrap='}'[wrapper to run tests with]:wrapper program:_path_commands' - '(--no-suite)--suite[only run tests from this suite]:test suite: ' + "$__meson_cd" '(--suite)--no-suite[do not run tests from this suite]:test suite: ' + '(--no-suite)--suite[only run tests from this suite]:test suite: ' '--no-stdsplit[do not split stderr and stdout in logs]' '--print-errorlogs[print logs for failing tests]' '--benchmark[run benchmarks instead of tests]' '--logbase[base name for log file]:filename: ' '--num-processes[how many threads to use]:number of processes: ' + '(--verbose -v)'{'--verbose','-v'}'[do not redirect stdout and stderr]' + '(--quiet -q)'{'--quiet','-q'}'[produce less output to the terminal]' + '(--timeout-multiplier -t)'{'--timeout-multiplier','-t'}'[a multiplier for test timeouts]:Python floating-point number: ' '--setup[which test setup to use]:test setup: ' '--test-args[arguments to pass to the tests]: : ' '*:Meson tests:__meson_test_names' @@ -164,17 +204,32 @@ "${(@)specs}" } +(( $+functions[_meson-install] )) || _meson-install() { + local curcontext="$curcontext" + local -a specs=( + "$__meson_cd" + '--no-rebuild[Do not rebuild before installing]' + '--only-changed[Do not overwrite files that are older than the copied file]' + '--quiet[Do not print every file that was installed]' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + (( $+functions[_meson-introspect] )) || _meson-introspect() { local curcontext="$curcontext" local -a specs=( - '--targets[list top level targets]' - '--installed[list all installed files and directories]' - '--buildsystem-files[list files that belong to the build system]' - '--buildoptions[list all build options]' - '--tests[list all unit tests]' + '--ast[dump the ASK of the meson file]' '--benchmarks[list all benchmarks]' + '--buildoptions[list all build options]' + '--buildsystem-files[list files that belong to the build system]' '--dependencies[list external dependencies]' + '--installed[list all installed files and directories]' '--projectinfo[show project information]' + '--targets[list top level targets]' + '--tests[list all unit tests]' + '--backend=[backend to use]:Meson backend:'"$__meson_backends" '::build directory:_directories' ) _arguments \ @@ -182,8 +237,167 @@ "${(@)specs}" } +(( $+functions[_meson-init] )) || _meson-init() { + local curcontext="$curcontext" + local -a specs=( + "$__meson_cd" + '(-n --name)'{'-n','--name'}'=[the name of the project (defaults to directory name)]' + '(-e --executable)'{'-e','--executable'}'=[the name of the executable target to create (defaults to project name)]' + '(-d --deps)'{'-d','--deps'}'=[comma separated list of dependencies]' + '(-l --language)'{'-l','--language'}'=[comma separated list of languages (autodetected based on sources if unset)]:languages:_values , (c cpp cs cuda d fortran java objc objcpp rust)' + '(-b --build)'{'-b','--build'}'[build the project immediately after generation]' + '--builddir=[directory for building]:directory:_directories' + '(-f --force)'{'-f','--force'}'[overwrite any existing files and directories]' + '(-t --type)'{'-t','--type'}'=[project type, defaults to executable]:type:(executable library)' + '(-v --version)'{'-v','--version'}'[print the meson version and exit]' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + (( $+functions[_meson-wrap] )) || _meson-wrap() { - # TODO + local -a commands=( + 'list:list all available wraps' + 'search:search the db by name' + 'install:install the specified project' + 'update:Update a project to its newest available version' + 'info:Show info about a wrap' + 'status:Show the status of your subprojects' + ) + + if (( CURRENT == 2 )); then + _describe -t commands "Meson wrap subcommands" commands + else + local curcontext="$curcontext" + cmd="${${commands[(r)$words[2]:*]%%:*}}" + if (( $#cmd )); then + if [[ $cmd == status ]]; then + _message "no options" + elif [[ $cmd == "list" ]]; then + _arguments '*:meson wraps' + elif [[ $cmd == "search" ]]; then + _arguments '*:meson wraps' + elif [[ $cmd == "install" ]]; then + _arguments '*:meson wraps:__meson_wrap_names' + elif [[ $cmd == "update" ]]; then + _arguments '*:meson wraps:__meson_installed_wraps' + elif [[ $cmd == "info" ]]; then + _arguments '*:meson wraps:__meson_wrap_name' + elif [[ $cmd == "status" ]]; then + _arguments '*:' + elif [[ $cmd == "promote" ]]; then + # TODO: how do you figure out what wraps are provided by subprojects if + # they haven't been fetched yet? + _arguments '*:' + fi + else + _message "unknown meson wrap command: $words[2]" + fi + fi + +} + +(( $+functions[_meson-dist] )) || _meson-dist() { + local curcontext="$curcontext" + local -a specs=( + '--formats=[comma separated list of archive types to create]:archive formats:_values -s , format '"$__meson_dist_formats" + '--include-subprojects[Include source code of subprojects that have been used for the build]' + '--no-tests[Do not build and test generated packages]' + "$__meson_cd" + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects-update] )) || _meson-subprojects-update() { + local curcontext="$curcontext" + local -a specs=( + "--rebase[rebase your branch on top of wrap's revision (git only)]" + '--sourcedir=[path to source directory]:_directories' + '*:subprojects:__meson_installed_wraps' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects-checkout] )) || _meson-subprojects-checkout() { + local curcontext="$curcontext" + local -a specs=( + '-b[create a new branch]' + '--sourcedir=[path to source directory]:_directories' + # FIXME: this doesn't work exactly right, but I can't figure it out + ':branch name' + '*:subprojects:__meson_installed_wraps' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects-download] )) || _meson-subprojects-download() { + local curcontext="$curcontext" + local -a specs=( + '--sourcedir=[path to source directory]:_directories' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects-foreach] )) || _meson-subprojects-foreach() { + local curcontext="$curcontext" + local -a specs=( + '--sourcedir=[path to source directory]:_directories' + '*:command:_command_names -e' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects] )) || _meson-subprojects() { + local -a commands=( + 'update:update all subprojects from wrap files' + 'checkout:checkout a branch (git only)' + 'download:ensure subprojects are fetched, even if not in use. Already downloaded subprojects are not modified.' + 'foreach:execute a command in each subproject directory' + ) + + if (( CURRENT == 2 )); then + _describe -t commands "Meson subproject subcommands" commands + else + local curcontext="$curcontext" + cmd="${${commands[(r)$words[2]:*]%%:*}}" + if (( $#cmd )); then + if [[ $cmd == status ]]; then + _message "no options" + else + _meson-subprojects-$cmd + fi + else + _message "unknown meson subproject command: $words[2]" + fi + fi + +} + +(( $+functions[_meson-compile] )) || _meson-compile() { + local curcontext="$curcontext" + local -a specs=( + "$__meson_cd" + '--clean[Clean the build directory]' + '(-j --jobs)'{'-j','--jobs'}'=[the number fo work jobs to run (if supported)]:_guard "[0-9]#" "number of jobs"' + '(-l --load-averate)'{'-l','--load-average'}'=[the system load average to try to maintain (if supported)]:_guard "[0-9]#" "load average"' + '(-v --verbose)'{'-v','--verbose'}'[Show more output]' + '--ninja-args=[Arguments to pass to ninja (only when using ninja)]' + '--vs-args=[Arguments to pass to vs (only when using msbuild)]' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" } if [[ $service != meson ]]; then @@ -208,4 +422,3 @@ esac return ret - diff -Nru meson-0.53.2/data/syntax-highlighting/vim/ftdetect/meson.vim meson-0.61.2/data/syntax-highlighting/vim/ftdetect/meson.vim --- meson-0.53.2/data/syntax-highlighting/vim/ftdetect/meson.vim 2020-01-23 22:29:05.000000000 +0000 +++ meson-0.61.2/data/syntax-highlighting/vim/ftdetect/meson.vim 2020-08-15 16:27:05.000000000 +0000 @@ -1,2 +1,3 @@ au BufNewFile,BufRead meson.build set filetype=meson au BufNewFile,BufRead meson_options.txt set filetype=meson +au BufNewFile,BufRead *.wrap set filetype=dosini diff -Nru meson-0.53.2/data/syntax-highlighting/vim/ftplugin/meson.vim meson-0.61.2/data/syntax-highlighting/vim/ftplugin/meson.vim --- meson-0.53.2/data/syntax-highlighting/vim/ftplugin/meson.vim 2019-12-04 18:45:50.000000000 +0000 +++ meson-0.61.2/data/syntax-highlighting/vim/ftplugin/meson.vim 2021-11-02 19:58:07.000000000 +0000 @@ -1,6 +1,7 @@ " Vim filetype plugin file " Language: meson " License: VIM License +" Maintainer: Liam Beguin " Original Author: Laurent Pinchart " Last Change: 2018 Nov 27 @@ -11,9 +12,28 @@ setlocal commentstring=#\ %s setlocal comments=:# +setlocal formatoptions+=croql formatoptions-=t -setlocal shiftwidth=2 -setlocal softtabstop=2 +let b:undo_ftplugin = "setl com< cms< fo<" + +if get(g:, "meson_recommended_style", 1) + setlocal expandtab + setlocal shiftwidth=2 + setlocal softtabstop=2 + let b:undo_ftplugin .= " | setl et< sts< sw<" +endif + +if exists("loaded_matchit") && !exists("b:match_words") + let b:match_words = '\:\:\:\,' . + \ '\:\:\:\' + let b:undo_ftplugin .= " | unlet! b:match_words" +endif + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Meson Build Files (meson.build)\tmeson.build\n" . + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin .= " | unlet! b:browsefilter" +endif let &cpo = s:keepcpo unlet s:keepcpo diff -Nru meson-0.53.2/data/syntax-highlighting/vim/indent/meson.vim meson-0.61.2/data/syntax-highlighting/vim/indent/meson.vim --- meson-0.53.2/data/syntax-highlighting/vim/indent/meson.vim 2019-12-04 18:45:50.000000000 +0000 +++ meson-0.61.2/data/syntax-highlighting/vim/indent/meson.vim 2021-11-02 19:58:07.000000000 +0000 @@ -2,6 +2,7 @@ " Language: Meson " License: VIM License " Maintainer: Nirbheek Chauhan +" Liam Beguin " Original Authors: David Bustos " Bram Moolenaar " Last Change: 2015 Feb 23 @@ -19,12 +20,14 @@ setlocal indentexpr=GetMesonIndent(v:lnum) setlocal indentkeys+==elif,=else,=endforeach,=endif,0) +let b:undo_indent = "setl ai< inde< indk< lisp<" + " Only define the function once. if exists("*GetMesonIndent") finish endif let s:keepcpo= &cpo -setlocal cpo&vim +set cpo&vim " Come here when loading the script the first time. diff -Nru meson-0.53.2/data/syntax-highlighting/vim/syntax/meson.vim meson-0.61.2/data/syntax-highlighting/vim/syntax/meson.vim --- meson-0.53.2/data/syntax-highlighting/vim/syntax/meson.vim 2019-12-29 22:47:27.000000000 +0000 +++ meson-0.61.2/data/syntax-highlighting/vim/syntax/meson.vim 2021-12-26 16:24:25.000000000 +0000 @@ -2,7 +2,8 @@ " Language: Meson " License: VIM License " Maintainer: Nirbheek Chauhan -" Last Change: 2016 Dec 7 +" Liam Beguin +" Last Change: 2021 Aug 16 " Credits: Zvezdan Petkovic " Neil Schemenauer " Dmitry Vasiliev @@ -17,11 +18,7 @@ " let meson_space_error_highlight = 1 " -" For version 5.x: Clear all syntax items. -" For version 6.x: Quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +if exists("b:current_syntax") finish endif @@ -32,8 +29,9 @@ " http://mesonbuild.com/Syntax.html syn keyword mesonConditional elif else if endif -syn keyword mesonRepeat foreach endforeach -syn keyword mesonOperator and not or +syn keyword mesonRepeat foreach endforeach +syn keyword mesonOperator and not or in +syn keyword mesonStatement continue break syn match mesonComment "#.*$" contains=mesonTodo,@Spell syn keyword mesonTodo FIXME NOTE NOTES TODO XXX contained @@ -58,9 +56,11 @@ " Meson only supports integer numbers " http://mesonbuild.com/Syntax.html#numbers syn match mesonNumber "\<\d\+\>" +syn match mesonNumber "\<0x\x\+\>" +syn match mesonNumber "\<0o\o\+\>" " booleans -syn keyword mesonConstant false true +syn keyword mesonBoolean false true " Built-in functions syn keyword mesonBuiltin @@ -99,6 +99,8 @@ \ install_headers \ install_man \ install_subdir + \ install_symlink + \ install_emptydir \ is_disabler \ is_variable \ jar @@ -120,8 +122,10 @@ \ summary \ target_machine \ test + \ unset_variable \ vcs_tag \ warning + \ range if exists("meson_space_error_highlight") " trailing whitespace @@ -131,31 +135,20 @@ syn match mesonSpaceError display "\t\+ " endif -if version >= 508 || !exists("did_meson_syn_inits") - if version <= 508 - let did_meson_syn_inits = 1 - command -nargs=+ HiLink hi link - else - command -nargs=+ HiLink hi def link - endif - - " The default highlight links. Can be overridden later. - HiLink mesonStatement Statement - HiLink mesonConditional Conditional - HiLink mesonRepeat Repeat - HiLink mesonOperator Operator - HiLink mesonComment Comment - HiLink mesonTodo Todo - HiLink mesonString String - HiLink mesonEscape Special - HiLink mesonNumber Number - HiLink mesonBuiltin Function - HiLink mesonConstant Number - if exists("meson_space_error_highlight") - HiLink mesonSpaceError Error - endif - - delcommand HiLink +" The default highlight links. Can be overridden later. +hi def link mesonStatement Statement +hi def link mesonConditional Conditional +hi def link mesonRepeat Repeat +hi def link mesonOperator Operator +hi def link mesonComment Comment +hi def link mesonTodo Todo +hi def link mesonString String +hi def link mesonEscape Special +hi def link mesonNumber Number +hi def link mesonBuiltin Function +hi def link mesonBoolean Boolean +if exists("meson_space_error_higlight") + hi def link mesonSpaceError Error endif let b:current_syntax = "meson" diff -Nru meson-0.53.2/data/test.schema.json meson-0.61.2/data/test.schema.json --- meson-0.53.2/data/test.schema.json 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/data/test.schema.json 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,179 @@ +{ + "type": "object", + "additionalProperties": false, + "properties": { + "env": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "installed": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "file": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "file", + "python_file", + "dir", + "exe", + "shared_lib", + "python_lib", + "pdb", + "implib", + "py_implib", + "implibempty", + "expr" + ] + }, + "platform": { + "type": "string", + "enum": [ + "msvc", + "gcc", + "cygwin", + "!cygwin" + ] + }, + "version": { + "type": "string" + }, + "language": { + "type": "string" + } + }, + "required": [ + "file", + "type" + ] + } + }, + "matrix": { + "type": "object", + "properties": { + "options": { + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "val": { + "type": ["string", "boolean", "null", "array"], + "items": { + "type": "string" + } + }, + "compilers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "skip_on_env": { + "type": "array", + "items": { + "type": "string" + } + }, + "skip_on_jobname": { + "type": "array", + "items": { + "type": "string" + } + }, + "skip_on_os": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "val" + ] + } + }, + "exclude": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": ["string", "boolean", "array"], + "items": { + "type": "string" + } + } + } + } + } + } + }, + "do_not_set_opts": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "libdir", + "prefix" + ] + } + }, + "tools": { + "type": "object" + }, + "stdout": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "line": { + "type": "string" + }, + "match": { + "type": "string", + "enum": [ + "literal", + "re" + ] + }, + "count": { + "type": "integer" + }, + "comment": { + "type": "string" + } + }, + "required": [ + "line" + ] + } + }, + "skip_on_env": { + "type": "array", + "items": { + "type": "string" + } + }, + "skip_on_jobname": { + "type": "array", + "items": { + "type": "string" + } + }, + "skip_on_os": { + "type": "array", + "items": { + "type": "string" + } + } + } +} diff -Nru meson-0.53.2/debian/changelog meson-0.61.2/debian/changelog --- meson-0.53.2/debian/changelog 2020-03-03 07:59:51.000000000 +0000 +++ meson-0.61.2/debian/changelog 2022-06-28 01:54:37.000000000 +0000 @@ -1,547 +1,5 @@ -meson (0.53.2-2ubuntu2) focal; urgency=medium +meson (0.61.2-1~ppa~focal) focal; urgency=medium - * Skip test cross on s390x, because arm toolchain is not available there. + * Initial release. - -- Gianfranco Costamagna Tue, 03 Mar 2020 08:59:51 +0100 - -meson (0.53.2-2ubuntu1) focal; urgency=medium - - * Merge from Debian unstable. Remaining changes: - - add debian/patches/6703.patch - - Allow stderr for new test - - depend on rustc and valac, so autopkgtests can pick them up - - -- Gianfranco Costamagna Mon, 02 Mar 2020 12:05:06 +0100 - -meson (0.53.2-2) unstable; urgency=medium - - * Fix autopkgtest dependencies. Closes: #952610 - - -- Jussi Pakkanen Sat, 29 Feb 2020 00:20:11 +0200 - -meson (0.53.2-1ubuntu4) focal; urgency=medium - - * Also allow stderr - - -- Gianfranco Costamagna Mon, 02 Mar 2020 11:58:04 +0100 - -meson (0.53.2-1ubuntu3) focal; urgency=medium - - * debian/patches/6703.patch - - use upstream proposed approach instead of use_python3_tests.patch - * Tweak debian tests/control to fix another test failure (Closes: #952610) - - patch taken from bug report - - -- Gianfranco Costamagna Mon, 02 Mar 2020 07:24:25 +0100 - -meson (0.53.2-1ubuntu1) focal; urgency=medium - - [ Stefano Rivera ] - * debian/patches/use_python3_tests.patch: - - Update use_python3_tests.patch to catch one more python binary use. - - [ Rico Tzschichholz ] - * debian/tests/control: - - Explicit depends on rustc and valac, so autopkgtests can pick it up - - -- Rico Tzschichholz Wed, 26 Feb 2020 12:42:13 +0100 - -meson (0.53.2-1) unstable; urgency=medium - - * New upstream release. Closes: #950020, #951487 - - -- Jussi Pakkanen Tue, 25 Feb 2020 18:02:37 +0200 - -meson (0.53.1-1) unstable; urgency=medium - - * New upstream release. Closes: #948611. - * Add cross build autopkgtest from Helmut Grohne. Closes: #948608 - - -- Jussi Pakkanen Fri, 24 Jan 2020 00:35:16 +0200 - -meson (0.53.0-1) unstable; urgency=medium - - * New upstream release. - * Disable tests that check home directory because it does - not seem to work under pbuilder. - - -- Jussi Pakkanen Tue, 07 Jan 2020 22:13:25 +0200 - -meson (0.52.1-1) unstable; urgency=medium - - * New upstream release. Closes: #945277. - * Packaging fixes from Lasse Kantola. Closes: #870314. - - -- Jussi Pakkanen Fri, 29 Nov 2019 15:52:29 +0200 - -meson (0.52.0-2) unstable; urgency=medium - - * Update wxwidgets build dependency. Closes: #943437. - * Disable FPGA tests temporarily to work around Yosys upstream - bug #1467. - - -- Jussi Pakkanen Tue, 29 Oct 2019 23:48:25 +0200 - -meson (0.52.0-1) unstable; urgency=medium - - * New upstream release. - * Removed python2 build dep to prepare for Python 2 removal. - Added boost-python explicitly to build-deps. - - -- Jussi Pakkanen Sun, 06 Oct 2019 20:05:53 +0300 - -meson (0.51.2-1) unstable; urgency=medium - - * New upstream release. - * Updated standards and compat versions. - - -- Jussi Pakkanen Mon, 26 Aug 2019 19:39:22 +0300 - -meson (0.51.1-1) unstable; urgency=medium - - * New upstream release. - * Fix debcrossgen on i386. - - -- Jussi Pakkanen Tue, 09 Jul 2019 19:40:49 +0300 - -meson (0.51.0-1) experimental; urgency=medium - - * New upstream release. - * Add build-dep to CMake needed by new tests. - - -- Jussi Pakkanen Sun, 16 Jun 2019 22:04:22 +0300 - -meson (0.50.1-1) experimental; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Wed, 17 Apr 2019 01:12:02 +0300 - -meson (0.50.0-1) experimental; urgency=medium - - * New upstream release. - * Install zsh completion files. Closes: #920154. - * Add python2-dev to build deps as needed by new tests. - - -- Jussi Pakkanen Sun, 10 Mar 2019 19:27:10 +0200 - -meson (0.49.2-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Mon, 04 Feb 2019 21:20:09 +0200 - -meson (0.49.1-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Wed, 23 Jan 2019 18:49:53 +0200 - -meson (0.49.0-2) unstable; urgency=medium - - * Debcrossgen CPU fix from Helmut Grohne. Closes: #919065. - * Add system compiler flags to cross files. Closes: #919117. - - -- Jussi Pakkanen Sun, 13 Jan 2019 00:59:08 +0200 - -meson (0.49.0-1) unstable; urgency=medium - - * New upstream release. Closes: #894774, #914543, #913263. - - -- Jussi Pakkanen Sun, 09 Dec 2018 19:56:53 +0200 - -meson (0.48.2-1) unstable; urgency=medium - - * New upstream release. Closes: #911879, #911697. - * Backport split-merge patch from trunk. Closes: #913320. - - -- Jussi Pakkanen Fri, 15 Nov 2018 21:30:25 +0200 - -meson (0.48.1-1) unstable; urgency=medium - - * New upstream release. Closes: #909851, #910443. - - -- Jussi Pakkanen Wed, 17 Oct 2018 18:57:16 +0300 - -meson (0.48.0-2) unstable; urgency=medium - - * Add dependency to python3-pkg-resources temporarily. Closes: #909440. - - -- Jussi Pakkanen Mon, 24 Sep 2018 18:51:11 +0300 - -meson (0.48.0-1) unstable; urgency=medium - - * New upstream release. Closes: #907324. - - -- Jussi Pakkanen Sat, 22 Sep 2018 23:13:11 +0300 - -meson (0.47.2-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Sat, 25 Aug 2018 11:15:05 +0300 - -meson (0.47.1-2) unstable; urgency=medium - - * Fix debcrossgen install properly. Closes: #903279. - * Re-enable Valgrind tests. - - -- Jussi Pakkanen Fri, 3 Aug 2018 22:56:19 +0300 - -meson (0.47.1-1) unstable; urgency=medium - - * New upstream release. Closes: #903414. - * Install depfixer again, it got lost accidentally. Closes: #903279. - * Disable all Valgrind tests because of #903404. - - -- Jussi Pakkanen Wed, 11 Jul 2018 00:05:14 +0300 - -meson (0.47.0-1) unstable; urgency=medium - - * New upstream release. - * Switch to using standard Python install because trying to keep the - library private is just too damn hard and annoying. - * Updated Google test dependencies. Closes: #897174. - * Added build deps to test new functionality. - - -- Jussi Pakkanen Mon, 02 Jul 2018 20:54:05 +0300 - -meson (0.46.1-1) unstable; urgency=medium - - * New upstream release. Closes: #896876. - * Use an UTF-8 locale because ASCII breaks tests. - - -- Jussi Pakkanen Wed, 16 May 2018 19:28:58 +0300 - -meson (0.46.0-1) unstable; urgency=medium - - * New upstream release. Closes: #892515. - * Updated debcrossgen. - * Old command names now only print errors. Closes: #886882. - * Marked pytho3 dependency with :any as recommended by multiarch hinter. - - -- Jussi Pakkanen Sun, 22 Apr 2018 19:42:22 +0300 - -meson (0.45.1-2) unstable; urgency=medium - - * Added cross fix to enable RISC-V bootstrap. Closes: #894505. - * Added patch to fix autopkgtests. Closes: #894594. - * Fixed Java detection logic and dependency. Closes: #894200. - * Fixed cross dependencies. Closes: #894199. - * Updated debcrossgen tool. Closes: #893502. - - -- Jussi Pakkanen Mon, 02 Apr 2018 12:54:53 +0300 - -meson (0.45.1-1) unstable; urgency=medium - - * New upstream release. Closes: #892956. - - -- Jussi Pakkanen Thu, 22 Mar 2018 00:04:38 +0200 - -meson (0.45.0-1) unstable; urgency=medium - - * New upstream release. - * Updated debhelper requirement. - * New build deps for FPGA tests. - - -- Jussi Pakkanen Sun, 04 Mar 2018 20:27:57 +0200 - -meson (0.44.1-1) unstable; urgency=medium - - * New upstream version. Closes: #884627. - - -- Jussi Pakkanen Wed, 21 Feb 2018 00:02:07 +0200 - -meson (0.44.0-3) unstable; urgency=medium - - * Forward autopkgtest stderr to stdout because the test executor - interprets any text in stderr as a test failure. - - -- Jussi Pakkanen Sat, 23 Dec 2017 15:42:17 +0200 - -meson (0.44.0-2) unstable; urgency=medium - - * Add meson package as a dependency of all autopkgtests. - * Add build deps to enable a few optional tests. - - -- Jussi Pakkanen Sun, 17 Dec 2017 13:49:31 +0200 - -meson (0.44.0-1) unstable; urgency=medium - - * New upstream release. - * Do not run D library tests, because GDC has problems - with them. Closes: #879976. - * Fixed dependency declarations so a nocheck build - no longer requires Rust. Closes: #879704. - * Converted thorough autopkgtest to run the full test - suite including all dependency tests. - - -- Jussi Pakkanen Sun, 10 Dec 2017 15:41:49 +0200 - -meson (0.43.0-1) unstable; urgency=medium - - * New upstream release. - * Updated debcrossgen script. Closes: #875703. - - -- Jussi Pakkanen Sun, 08 Oct 2017 22:36:43 +0300 - -meson (0.42.1-1) unstable; urgency=medium - - * New upstream version. - * Marked the package multi-arch foreign - * Ship non-public helper script to generate cross files - from architecture info to aid in cross builds. Closes: #859177. - - -- Jussi Pakkanen Tue, 12 Sep 2017 19:37:59 +0300 - -meson (0.42.0-2) unstable; urgency=medium - - * Fix autopkgtests to use the meson command rather than mesonconf, - mesonintrospect et al, because the latter write a warning to - stderr which causes autopkg to mark the test as failed. - - -- Jussi Pakkanen Thu, 24 Aug 2017 01:08:48 +0300 - -meson (0.42.0-1) unstable; urgency=medium - - * New upstream release. - * Disabled openmpi test because the generated binaries do not run - in pbuilder for an unknown reason. - - -- Jussi Pakkanen Tue, 15 Aug 2017 00:45:25 +0300 - -meson (0.41.2-2) unstable; urgency=medium - - * Cherry picked asm tagging patch to fix Ubuntu CI breakage. - - -- Jussi Pakkanen Tue, 25 Jul 2017 18:59:58 +0300 - -meson (0.41.2-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Wed, 19 Jul 2017 12:41:18 +0300 - -meson (0.41.1-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Mon, 19 Jun 2017 23:48:01 +0300 - -meson (0.41.0-1) unstable; urgency=medium - - * New upstream release. - * Added build dep to sdl2 and llvm for new tests. - * Added a new, more exhaustive Debian test. - - -- Jussi Pakkanen Mon, 12 Jun 2017 21:49:13 +0300 - -meson (0.40.1-1) unstable; urgency=medium - - * New upstream release. - * Backport helper fix from Martin Pitt. Closes: #861055. - - -- Jussi Pakkanen Fri, 28 Apr 2017 21:13:15 +0300 - -meson (0.40.0-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Sun, 23 Apr 2017 02:01:34 +0300 - -meson (0.39.1-1) unstable; urgency=medium - - * New upstream release - - -- Jussi Pakkanen Wed, 15 Mar 2017 22:58:47 +0200 - -meson (0.39.0-1) unstable; urgency=medium - - * New upstream release - * Added build-dep to Valgrind which some tests use if available - - -- Jussi Pakkanen Sun, 05 Mar 2017 23:10:04 +0200 - -meson (0.38.1-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Tue, 07 Feb 2017 22:03:30 +0200 - -meson (0.38.0-1) unstable; urgency=medium - - * New upstream release. - * Versioned Ninja dependency. Closes: #850078. - * Install mesontest properly. Closes: #851601. - * Build-dep on arm cross compiler to run cross build tests. - - -- Jussi Pakkanen Sun, 29 Jan 2017 21:17:38 +0200 - -meson (0.37.1-1) unstable; urgency=medium - - * New upstream bugfix release. - - -- Jussi Pakkanen Tue, 20 Dec 2016 22:09:22 +0200 - -meson (0.37.0-1) unstable; urgency=medium - - * New upstream release. - * Added build dep to libgtk-3-dev needed by new tests. - - -- Jussi Pakkanen Sun, 18 Dec 2016 21:17:38 +0200 - -meson (0.36.0-1) unstable; urgency=medium - - * New upstream release. Closes: #841846. - * Added build dep to itstool, which is needed by new tests. - - -- Jussi Pakkanen Mon, 14 Nov 2016 20:12:41 +0200 - -meson (0.35.1-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Mon, 17 Oct 2016 21:02:42 +0300 - -meson (0.35.0-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Mon, 03 Oct 2016 22:53:31 +0300 - -meson (0.34.0-1) unstable; urgency=medium - - * New upstream release. - * Added build dep to D compiler to run new tests. - - -- Jussi Pakkanen Mon, 05 Sep 2016 22:33:07 +0300 - -meson (0.33.0-1) unstable; urgency=medium - - * New upstream release - - -- Jussi Pakkanen Sat, 30 Jul 2016 22:36:07 +0300 - -meson (0.32.0-1) unstable; urgency=medium - - * New upstream release. - * Removed meson-gui package because upstream removed it. - - -- Jussi Pakkanen Sun, 05 Jun 2016 20:51:37 +0300 - -meson (0.31.0-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Wed, 13 Apr 2016 19:39:02 +0300 - -meson (0.30.0-1) unstable; urgency=medium - - * New upstream release. Closes: #815253. - * New build deps to test building of Python3 extension modules. - * Add Lintian override for build-depping on python-dev - even though the package is arch-all. - - -- Jussi Pakkanen Sat, 12 Mar 2016 19:04:33 +0200 - -meson (0.29.0-1) unstable; urgency=medium - - * New upstream release. - * Upstream moved to distutils so rewrote packaging. - - -- Jussi Pakkanen Sun, 24 Jan 2016 18:57:59 +0200 - -meson (0.28.0-2) unstable; urgency=medium - - * Change Rust dependency so the package builds - on Debian and Ubuntu without changes. - - -- Jussi Pakkanen Wed, 06 Jan 2016 15:23:56 +0200 - -meson (0.28.0-1) unstable; urgency=medium - - * New upstream release. - * Only build-dep on Rust on platforms that provide it. - - -- Jussi Pakkanen Tue, 29 Dec 2015 00:01:46 +0200 - -meson (0.27.0-1) unstable; urgency=medium - - * New upstream release. - * Build-dep on rustc to run Rust tests. - - -- Jussi Pakkanen Wed, 25 Nov 2015 19:58:44 +0200 - -meson (0.26.0-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Sat, 12 Sep 2015 22:31:28 +0300 - -meson (0.25.0-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Sun, 12 Jul 2015 20:52:27 +0300 - -meson (0.24.0-1) unstable; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Sat, 23 May 2015 21:31:15 +0300 - -meson (0.23.0-2) unstable; urgency=medium - - * Reupload to unstable. - - -- Jussi Pakkanen Sun, 26 Apr 2015 13:43:52 +0300 - -meson (0.23.0-1) experimental; urgency=medium - - * New upstream release. - - -- Jussi Pakkanen Tue, 31 Mar 2015 01:02:33 +0300 - -meson (0.22.0-1) experimental; urgency=medium - - * New upstream release - * Use QT_SELECT instead of build-depending on - qt5-default to fix Lintian error - - -- Jussi Pakkanen Mon, 19 Jan 2015 21:49:17 +0200 - -meson (0.21.0-1) unstable; urgency=medium - - * New upstream release. - * Added autopkgtest for Clang - - -- Jussi Pakkanen Fri, 24 Oct 2014 05:01:08 +0300 - -meson (0.20.0-1) unstable; urgency=medium - - * New upstream version - * Added build-deps to Mono, Flex and Bison as - required by new unit tests - - -- Jussi Pakkanen Sat, 13 Sep 2014 00:46:56 +0300 - -meson (0.19.0-1) unstable; urgency=medium - - * New upstream release. - * Meson now supports Fortran compilation, - so build-depend on gfortran to test that it's working. - - -- Jussi Pakkanen Mon, 11 Aug 2014 00:24:16 +0300 - -meson (0.18.0-1) unstable; urgency=medium - - * New upstream release. - * Made compilation and test output more verbose. - - -- Jussi Pakkanen Mon, 14 Jul 2014 18:26:28 +0300 - -meson (0.17.0-1) unstable; urgency=medium - - * Initial release. Closes: #712605, #712610 - - -- Jussi Pakkanen Wed, 04 Jun 2014 22:33:44 +0300 + -- tomx3 Tue, 28 Jun 2022 03:54:37 +0200 diff -Nru meson-0.53.2/debian/compat meson-0.61.2/debian/compat --- meson-0.53.2/debian/compat 2019-08-26 17:40:34.000000000 +0000 +++ meson-0.61.2/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -12 diff -Nru meson-0.53.2/debian/control meson-0.61.2/debian/control --- meson-0.53.2/debian/control 2020-03-02 11:02:28.000000000 +0000 +++ meson-0.61.2/debian/control 2022-06-28 01:54:37.000000000 +0000 @@ -1,17 +1,19 @@ + Source: meson -Maintainer: Jussi Pakkanen +Maintainer: tomx3 Section: devel Priority: optional -Standards-Version: 4.5.0 +Standards-Version: 4.6.0 Homepage: https://mesonbuild.com X-Python3-Version: >= 3.7 Rules-Requires-Root: no -Build-Depends: debhelper (>= 12), +Build-Depends: debhelper-compat (= 12), python3:any (>= 3.5), dh-exec, dh-python, python3-setuptools, ninja-build (>= 1.6), + bash-completion, # The following are needed for the unit test suite zlib1g-dev , pkg-config , @@ -20,6 +22,7 @@ libboost-test-dev , libboost-log-dev , libboost-python-dev , + libboost-regex-dev , gobjc , gobjc++ , gnustep-make , @@ -62,9 +65,10 @@ valgrind [amd64 i386] , llvm-dev , libsdl2-dev , -# OpenMPI packages do not install currently (2018/04/23) +# OpenMPI tests do not run under pbuilder and the packages are currently +# (2020-09-10) broken and uninstallable so disable this. openmpi-bin , - libopenmpi-dev , +# libopenmpi-dev , # Running OpenMPI executables requires openssh. Yes, really. openssh-client , libvulkan-dev , @@ -85,6 +89,7 @@ doxygen , nasm , cmake , + clang-format , Package: meson Architecture: all @@ -93,7 +98,10 @@ ${misc:Depends}, ${python3:Depends}, ninja-build(>=1.6), -# python3-pkg-resources, + python3-pkg-resources, + python3-distutils +Recommends: + dpkg-dev, Description: high-productivity build system Meson is a build system designed to increase programmer productivity. It does this by providing a fast, simple and easy to diff -Nru meson-0.53.2/debian/copyright meson-0.61.2/debian/copyright --- meson-0.53.2/debian/copyright 2018-05-16 18:06:55.000000000 +0000 +++ meson-0.61.2/debian/copyright 2021-11-25 18:40:41.000000000 +0000 @@ -1,10 +1,10 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: meson Upstream-Contact: jpakkane@gmail.com -Source: https://github.com/jpakkane/meson +Source: https://github.com/mesonbuild/meson Files: * -Copyright: 2012-2015 The Meson development team +Copyright: 2012-2021 The Meson development team License: Apache-2.0 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff -Nru meson-0.53.2/debian/debcrossgen meson-0.61.2/debian/debcrossgen --- meson-0.53.2/debian/debcrossgen 2019-07-01 18:33:01.000000000 +0000 +++ meson-0.61.2/debian/debcrossgen 2021-02-14 12:58:40.000000000 +0000 @@ -80,7 +80,8 @@ cmd = ['dpkg-architecture'] else: cmd = ['dpkg-architecture', '-a' + options.arch] - output = subprocess.check_output(cmd, universal_newlines=True) + output = subprocess.check_output(cmd, universal_newlines=True, + stderr=subprocess.DEVNULL) data = {} for line in output.split('\n'): line = line.strip() @@ -109,6 +110,10 @@ ofile.write("pkgconfig = '%s'\n" % locate_path("%s-pkg-config" % host_arch)) except ValueError: pass # pkg-config is optional + try: + ofile.write("cups-config = '%s'\n" % locate_path("cups-config")) + except ValueError: + pass # cups-config is optional ofile.write('\n[properties]\n') write_args_from_envvars(ofile) ofile.write('\n[host_machine]\n') diff -Nru meson-0.53.2/debian/install meson-0.61.2/debian/install --- meson-0.53.2/debian/install 2019-11-23 20:10:34.000000000 +0000 +++ meson-0.61.2/debian/install 2021-02-14 12:58:40.000000000 +0000 @@ -1,4 +1,4 @@ #!/usr/bin/dh-exec -__main__.py => /usr/bin/meson +meson.py => /usr/bin/meson debian/debcrossgen /usr/share/meson -data/shell-completions/zsh/_meson /usr/share/zsh/vendor-completions \ No newline at end of file +data/shell-completions/zsh/_meson /usr/share/zsh/vendor-completions diff -Nru meson-0.53.2/debian/meson.bash-completion meson-0.61.2/debian/meson.bash-completion --- meson-0.53.2/debian/meson.bash-completion 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/debian/meson.bash-completion 2021-02-14 12:58:40.000000000 +0000 @@ -0,0 +1 @@ +data/shell-completions/bash/meson diff -Nru meson-0.53.2/debian/patches/1-disable-openmpi.patch meson-0.61.2/debian/patches/1-disable-openmpi.patch --- meson-0.53.2/debian/patches/1-disable-openmpi.patch 2020-01-07 19:00:50.000000000 +0000 +++ meson-0.61.2/debian/patches/1-disable-openmpi.patch 2021-02-14 12:58:40.000000000 +0000 @@ -1,12 +1,13 @@ diff --git a/test cases/frameworks/17 mpi/meson.build b/test cases/frameworks/17 mpi/meson.build -index 2102b817..cd250b58 100644 +index 75b463cc..7bf4e7ae 100644 --- a/test cases/frameworks/17 mpi/meson.build +++ b/test cases/frameworks/17 mpi/meson.build -@@ -1,5 +1,7 @@ - project('mpi', 'c', 'cpp', default_options: ['b_asneeded=false']) +@@ -2,6 +2,8 @@ project('mpi', 'c', 'cpp', default_options: ['b_asneeded=false']) + + method = get_option('method') +error('MESON_SKIP_TEST openmpi binaries do not work when run in pbuilder for some reason.') + cc = meson.get_compiler('c') - mpic = dependency('mpi', language : 'c', required : false) + mpic = dependency('mpi', language : 'c', required : false, method : method) if not mpic.found() diff -Nru meson-0.53.2/debian/patches/2-disable-rootdir-test.patch meson-0.61.2/debian/patches/2-disable-rootdir-test.patch --- meson-0.53.2/debian/patches/2-disable-rootdir-test.patch 2020-01-07 19:00:50.000000000 +0000 +++ meson-0.61.2/debian/patches/2-disable-rootdir-test.patch 2021-04-27 06:54:09.000000000 +0000 @@ -1,18 +1,27 @@ -diff --git a/test cases/common/227 fs module/meson.build b/test cases/common/227 fs module/meson.build -index 8795ee00..e34572ef 100644 ---- a/test cases/common/227 fs module/meson.build -+++ b/test cases/common/227 fs module/meson.build -@@ -30,8 +30,11 @@ assert(fs.is_dir('subprojects'), 'Dir not detected correctly.') +diff --git a/test cases/common/221 fs module/meson.build b/test cases/common/221 fs module/meson.build +index a7327682..c5f90bbb 100644 +--- a/test cases/common/220 fs module/meson.build ++++ b/test cases/common/220 fs module/meson.build +@@ -30,12 +30,16 @@ assert(fs.is_dir('subprojects'), 'Dir not detected correctly.') assert(not fs.is_dir('meson.build'), 'File detected as a dir.') assert(not fs.is_dir('nonexisting'), 'Bad path detected as a dir.') --assert(fs.is_dir('~'), 'expanduser not working') --assert(not fs.is_file('~'), 'expanduser not working') -+# These don't work under pbuilder for some reason. +-assert(fs.is_dir('~'), 'home directory not detected') +-assert(not fs.is_file('~'), 'home directory detected as file') +- +-# -- expanduser +-assert(fs.expanduser('~') != '~','expanduser failed') +-assert(fs.expanduser('~/foo').endswith('foo'), 'expanduser with tail failed') ++# These do not work with pbuilder for some reason. +# I have not been able to replicate this manually, -+# even with 'pbuilder login' -+#assert(fs.is_dir('~'), 'expanduser not working') -+#assert(not fs.is_file('~'), 'expanduser not working') ++# even with 'pbuilder login'. ++# ++#assert(fs.is_dir('~'), 'home directory not detected') ++#assert(not fs.is_file('~'), 'home directory detected as file') ++# ++## -- expanduser ++#assert(fs.expanduser('~') != '~','expanduser failed') ++#assert(fs.expanduser('~/foo').endswith('foo'), 'expanduser with tail failed') - original = 'foo.txt' - new = fs.replace_suffix(original, '.ini') + # -- as_posix + assert(fs.as_posix('/') == '/', 'as_posix idempotent') diff -Nru meson-0.53.2/debian/patches/6703.patch meson-0.61.2/debian/patches/6703.patch --- meson-0.53.2/debian/patches/6703.patch 2020-03-02 06:44:52.000000000 +0000 +++ meson-0.61.2/debian/patches/6703.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -Origin: https://github.com/mesonbuild/meson/pull/6703 ---- meson-0.53.2.orig/run_unittests.py -+++ meson-0.53.2/run_unittests.py -@@ -6650,9 +6650,9 @@ class NativeFileTests(BasePlatformTests) - '--native-file', config, '--native-file', config2, - '-Dcase=find_program']) - -- def _simple_test(self, case, binary): -+ def _simple_test(self, case, binary, entry=None): - wrapper = self.helper_create_binary_wrapper(binary, version='12345') -- config = self.helper_create_native_file({'binaries': {binary: wrapper}}) -+ config = self.helper_create_native_file({'binaries': {entry or binary: wrapper}}) - self.init(self.testcase, extra_args=['--native-file', config, '-Dcase={}'.format(case)]) - - def test_find_program(self): -@@ -6675,16 +6675,21 @@ class NativeFileTests(BasePlatformTests) - # python module breaks. This is fine on other OSes because they - # don't need the extra indirection. - raise unittest.SkipTest('bat indirection breaks internal sanity checks.') -- if os.path.exists('/etc/debian_version'): -- rc = subprocess.call(['pkg-config', '--cflags', 'python2'], -- stdout=subprocess.DEVNULL, -- stderr=subprocess.DEVNULL) -- if rc != 0: -- # Python 2 will be removed in Debian Bullseye, thus we must -- # remove the build dependency on python2-dev. Keep the tests -- # but only run them if dev packages are available. -+ elif is_osx(): -+ binary = 'python' -+ else: -+ binary = 'python2' -+ -+ # We not have python2, check for it -+ for v in ['2', '2.7', '-2.7']: -+ rc = subprocess.call(['pkg-config', '--cflags', 'python{}'.format(v)], -+ stdout=subprocess.DEVNULL, -+ stderr=subprocess.DEVNULL) -+ if rc == 0: -+ break -+ else: - raise unittest.SkipTest('Not running Python 2 tests because dev packages not installed.') -- self._simple_test('python', 'python') -+ self._simple_test('python', binary, entry='python') - - @unittest.skipIf(is_windows(), 'Setting up multiple compilers on windows is hard') - @skip_if_env_set('CC') diff -Nru meson-0.53.2/debian/patches/series meson-0.61.2/debian/patches/series --- meson-0.53.2/debian/patches/series 2020-03-02 06:30:20.000000000 +0000 +++ meson-0.61.2/debian/patches/series 2021-02-14 12:58:40.000000000 +0000 @@ -1,3 +1,2 @@ 1-disable-openmpi.patch 2-disable-rootdir-test.patch -6703.patch diff -Nru meson-0.53.2/debian/rules meson-0.61.2/debian/rules --- meson-0.53.2/debian/rules 2019-11-23 20:11:19.000000000 +0000 +++ meson-0.61.2/debian/rules 2021-02-14 12:58:40.000000000 +0000 @@ -12,7 +12,7 @@ export PYBUILD_NAME=meson %: - dh $@ --with python3 --buildsystem=pybuild + dh $@ --with python3 --buildsystem=pybuild --with bash-completion ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) override_dh_auto_test: diff -Nru meson-0.53.2/debian/tests/control meson-0.61.2/debian/tests/control --- meson-0.53.2/debian/tests/control 2020-03-03 07:59:49.000000000 +0000 +++ meson-0.61.2/debian/tests/control 2021-07-05 19:16:03.000000000 +0000 @@ -4,9 +4,13 @@ Tests: clangmeson Depends: meson, clang +# At the time of writing the packaging machinery does not put @builddeps@ into +# autopkg deps. The tests are only automatically run when packages explicitly +# listed as Depends are uploaded. List a few major ones to make sure those +# tests are run and thus block broken uploads. Tests: exhaustive -Depends: meson, @builddeps@, rustc, valac +Depends: meson, @builddeps@, valac, rustc, ldc [!s390x !ppc64el] Tests: crossbuild Depends: meson, g++, g++-arm-linux-gnueabihf -Restrictions: allow-stderr, skip-not-installable +Restrictions: skip-not-installable diff -Nru meson-0.53.2/debian/watch meson-0.61.2/debian/watch --- meson-0.53.2/debian/watch 2018-04-23 00:26:52.000000000 +0000 +++ meson-0.61.2/debian/watch 2021-04-27 11:23:59.000000000 +0000 @@ -1,4 +1,4 @@ -version = 3 +version = 4 opts=pgpsigurlmangle=s/$/.asc/ https://github.com/mesonbuild/meson/releases \ (?:.*/)meson.(\d[\d\.]*)\.tar\.gz diff -Nru meson-0.53.2/ghwt.py meson-0.61.2/ghwt.py --- meson-0.53.2/ghwt.py 2019-12-29 22:47:27.000000000 +0000 +++ meson-0.61.2/ghwt.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -# ghwt - GitHub WrapTool -# -# An emergency wraptool(1) replacement downloader that downloads -# directly from GitHub in case wrapdb.mesonbuild.com is down. - -import urllib.request, json, sys, os, shutil, subprocess -import configparser, hashlib - -req_timeout = 600.0 -private_repos = {'meson', 'wrapweb', 'meson-ci'} - -def gh_get(url): - r = urllib.request.urlopen(url, timeout=req_timeout) - jd = json.loads(r.read().decode('utf-8')) - return jd - -def list_projects(): - jd = gh_get('https://api.github.com/orgs/mesonbuild/repos') - entries = [entry['name'] for entry in jd] - entries = [e for e in entries if e not in private_repos] - entries.sort() - for i in entries: - print(i) - return 0 - -def unpack(sproj, branch, outdir): - subprocess.check_call(['git', 'clone', '-b', branch, 'https://github.com/mesonbuild/{}.git'.format(sproj), outdir]) - usfile = os.path.join(outdir, 'upstream.wrap') - assert(os.path.isfile(usfile)) - config = configparser.ConfigParser() - config.read(usfile) - us_url = config['wrap-file']['source_url'] - us = urllib.request.urlopen(us_url, timeout=req_timeout).read() - h = hashlib.sha256() - h.update(us) - dig = h.hexdigest() - should = config['wrap-file']['source_hash'] - if dig != should: - print('Incorrect hash on download.') - print(' expected:', dig) - print(' obtained:', should) - return 1 - spdir = os.path.dirname(outdir) - ofilename = os.path.join(spdir, config['wrap-file']['source_filename']) - with open(ofilename, 'wb') as ofile: - ofile.write(us) - if 'lead_directory_missing' in config['wrap-file']: - os.mkdir(outdir) - shutil.unpack_archive(ofilename, outdir) - else: - shutil.unpack_archive(ofilename, spdir) - extdir = os.path.join(spdir, config['wrap-file']['directory']) - assert(os.path.isdir(extdir)) - shutil.move(os.path.join(outdir, '.git'), extdir) - subprocess.check_call(['git', 'reset', '--hard'], cwd=extdir) - shutil.rmtree(outdir) - shutil.move(extdir, outdir) - shutil.rmtree(os.path.join(outdir, '.git')) - os.unlink(ofilename) - -def install(sproj): - sproj_dir = os.path.join('subprojects', sproj) - if not os.path.isdir('subprojects'): - print('Run this in your source root and make sure there is a subprojects directory in it.') - return 1 - if os.path.isdir(sproj_dir): - print('Subproject is already there. To update, nuke the dir and reinstall.') - return 1 - blist = gh_get('https://api.github.com/repos/mesonbuild/{}/branches'.format(sproj)) - blist = [b['name'] for b in blist] - blist = [b for b in blist if b != 'master'] - blist.sort() - branch = blist[-1] - print('Using branch', branch) - return unpack(sproj, branch, sproj_dir) - -def run(args): - if not args or args[0] == '-h' or args[0] == '--help': - print(sys.argv[0], 'list/install', 'package_name') - return 1 - command = args[0] - args = args[1:] - if command == 'list': - list_projects() - return 0 - elif command == 'install': - if len(args) != 1: - print('Install requires exactly one argument.') - return 1 - return install(args[0]) - else: - print('Unknown command') - return 1 - -if __name__ == '__main__': - print('This is an emergency wrap downloader. Use only when wrapdb is down.') - sys.exit(run(sys.argv[1:])) diff -Nru meson-0.53.2/__main__.py meson-0.61.2/__main__.py --- meson-0.53.2/__main__.py 2018-10-31 09:31:20.000000000 +0000 +++ meson-0.61.2/__main__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -from mesonbuild import mesonmain -import sys - -sys.exit(mesonmain.main()) diff -Nru meson-0.53.2/man/meson.1 meson-0.61.2/man/meson.1 --- meson-0.53.2/man/meson.1 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/man/meson.1 2022-02-14 19:03:13.000000000 +0000 @@ -1,4 +1,4 @@ -.TH MESON "1" "February 2020" "meson 0.53.2" "User Commands" +.TH MESON "1" "February 2022" "meson 0.61.2" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION diff -Nru meson-0.53.2/MANIFEST.in meson-0.61.2/MANIFEST.in --- meson-0.53.2/MANIFEST.in 2019-09-16 21:20:45.000000000 +0000 +++ meson-0.61.2/MANIFEST.in 2021-11-02 19:58:07.000000000 +0000 @@ -4,10 +4,11 @@ graft data graft graphics graft man -graft syntax-highlighting graft tools -include authors.txt -include contributing.txt +graft packaging +graft unittests + +include contributing.md include COPYING include README.md include run_cross_test.py @@ -15,7 +16,6 @@ include run_unittests.py include run_meson_command_tests.py include run_project_tests.py -include mesonrewriter.py include ghwt.py include __main__.py include meson.py diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/4 standalone binaries/readme.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/4 standalone binaries/readme.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/4 standalone binaries/readme.txt" 2016-08-10 20:57:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/4 standalone binaries/readme.txt" 2021-11-02 19:58:07.000000000 +0000 @@ -9,4 +9,3 @@ On Linux you must build the package on the oldest distribution you plan to support (Debian stable/oldstable and old CentOS are the common choice here). - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/meson.build" 2016-07-11 18:35:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('own libc', 'c') - -# Not related to this test, but could not find a better place for this test. -assert(meson.get_cross_property('nonexisting', 'defaultvalue') == 'defaultvalue', - 'Cross prop getting is broken.') - -# A simple project that uses its own libc. - -# Note that we don't need to specify anything, the flags to use -# stdlib come from the cross file. - -exe = executable('selfcontained', 'prog.c') - -test('standalone test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ - -#include - -int main(void) { - const char *message = "Hello without stdlib.\n"; - return simple_print(message, simple_strlen(message)); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/subprojects/mylibc/libc.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/subprojects/mylibc/libc.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/subprojects/mylibc/libc.c" 2016-05-28 14:39:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/subprojects/mylibc/libc.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -/* Do not use this as the basis of your own libc. - * The code is probably unoptimal or wonky, as I - * had no prior experience with this, but instead - * just fiddled with the code until it worked. - */ - -#include - -#define STDOUT 1 -#define SYS_WRITE 4 - -int simple_print(const char *msg, const long bufsize) { - int count; - long total_written = 0; - while(total_written < bufsize) { - asm( - "int $0x80\n\t" - : "=a"(count) - : "0"(SYS_WRITE), "b"(STDOUT), "c"(msg+total_written), "d"(bufsize-total_written) - :); - if(count == 0) { - return 1; - } - total_written += count; - } - return 0; -} - -int simple_strlen(const char *str) { - int len = 0; - while(str[len] != '\0') { - len++; - } - return len; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/subprojects/mylibc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/subprojects/mylibc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/subprojects/mylibc/meson.build" 2016-05-28 14:39:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/subprojects/mylibc/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('own libc', 'c') - -# A very simple libc implementation - -# Do not specify -nostdlib & co. They come from cross specifications. - -libc = static_library('c', 'libc.c', 'stubstart.s') - -mylibc_dep = declare_dependency(link_with : libc, - include_directories : include_directories('.') -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/subprojects/mylibc/stdio.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/subprojects/mylibc/stdio.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/subprojects/mylibc/stdio.h" 2016-05-28 14:39:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/subprojects/mylibc/stdio.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#pragma once - -int simple_print(const char *msg, const long bufsize); - -int simple_strlen(const char *str); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s" 2016-05-28 14:39:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -.globl _start - -_start: - - call main - movl %eax, %ebx - movl $1, %eax - int $0x80 diff -Nru meson-0.53.2/mesonbuild/arglist.py meson-0.61.2/mesonbuild/arglist.py --- meson-0.53.2/mesonbuild/arglist.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/arglist.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,334 @@ +# Copyright 2012-2020 The Meson development team +# Copyright © 2020 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from functools import lru_cache +import collections +import enum +import os +import re +import typing as T + +from . import mesonlib + +if T.TYPE_CHECKING: + from .linkers import StaticLinker + from .compilers import Compiler + +UNIXY_COMPILER_INTERNAL_LIBS = ['m', 'c', 'pthread', 'dl', 'rt'] # type: T.List[str] +# execinfo is a compiler lib on FreeBSD and NetBSD +if mesonlib.is_freebsd() or mesonlib.is_netbsd(): + UNIXY_COMPILER_INTERNAL_LIBS.append('execinfo') + + +class Dedup(enum.Enum): + + """What kind of deduplication can be done to compiler args. + + OVERRIDDEN - Whether an argument can be 'overridden' by a later argument. + For example, -DFOO defines FOO and -UFOO undefines FOO. In this case, + we can safely remove the previous occurrence and add a new one. The + same is true for include paths and library paths with -I and -L. + UNIQUE - Arguments that once specified cannot be undone, such as `-c` or + `-pipe`. New instances of these can be completely skipped. + NO_DEDUP - Whether it matters where or how many times on the command-line + a particular argument is present. This can matter for symbol + resolution in static or shared libraries, so we cannot de-dup or + reorder them. + """ + + NO_DEDUP = 0 + UNIQUE = 1 + OVERRIDDEN = 2 + + +class CompilerArgs(collections.abc.MutableSequence): + ''' + List-like class that manages a list of compiler arguments. Should be used + while constructing compiler arguments from various sources. Can be + operated with ordinary lists, so this does not need to be used + everywhere. + + All arguments must be inserted and stored in GCC-style (-lfoo, -Idir, etc) + and can converted to the native type of each compiler by using the + .to_native() method to which you must pass an instance of the compiler or + the compiler class. + + New arguments added to this class (either with .append(), .extend(), or +=) + are added in a way that ensures that they override previous arguments. + For example: + + >>> a = ['-Lfoo', '-lbar'] + >>> a += ['-Lpho', '-lbaz'] + >>> print(a) + ['-Lpho', '-Lfoo', '-lbar', '-lbaz'] + + Arguments will also be de-duped if they can be de-duped safely. + + Note that because of all this, this class is not commutative and does not + preserve the order of arguments if it is safe to not. For example: + >>> ['-Ifoo', '-Ibar'] + ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifez', '-Ibaz', '-Ifoo', '-Ibar', '-Werror'] + >>> ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifoo', '-Ibar'] + ['-Ifoo', '-Ibar', '-Ifez', '-Ibaz', '-Werror'] + + ''' + # Arg prefixes that override by prepending instead of appending + prepend_prefixes = () # type: T.Tuple[str, ...] + + # Arg prefixes and args that must be de-duped by returning 2 + dedup2_prefixes = () # type: T.Tuple[str, ...] + dedup2_suffixes = () # type: T.Tuple[str, ...] + dedup2_args = () # type: T.Tuple[str, ...] + + # Arg prefixes and args that must be de-duped by returning 1 + # + # NOTE: not thorough. A list of potential corner cases can be found in + # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 + dedup1_prefixes = () # type: T.Tuple[str, ...] + dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') # type: T.Tuple[str, ...] + # Match a .so of the form path/to/libfoo.so.0.1.0 + # Only UNIX shared libraries require this. Others have a fixed extension. + dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') + dedup1_args = () # type: T.Tuple[str, ...] + # In generate_link() we add external libs without de-dup, but we must + # *always* de-dup these because they're special arguments to the linker + # TODO: these should probably move too + always_dedup_args = tuple('-l' + lib for lib in UNIXY_COMPILER_INTERNAL_LIBS) # type : T.Tuple[str, ...] + + def __init__(self, compiler: T.Union['Compiler', 'StaticLinker'], + iterable: T.Optional[T.Iterable[str]] = None): + self.compiler = compiler + self._container = list(iterable) if iterable is not None else [] # type: T.List[str] + self.pre = collections.deque() # type: T.Deque[str] + self.post = collections.deque() # type: T.Deque[str] + + # Flush the saved pre and post list into the _container list + # + # This correctly deduplicates the entries after _can_dedup definition + # Note: This function is designed to work without delete operations, as deletions are worsening the performance a lot. + def flush_pre_post(self) -> None: + new = list() # type: T.List[str] + pre_flush_set = set() # type: T.Set[str] + post_flush = collections.deque() # type: T.Deque[str] + post_flush_set = set() # type: T.Set[str] + + #The two lists are here walked from the front to the back, in order to not need removals for deduplication + for a in self.pre: + dedup = self._can_dedup(a) + if a not in pre_flush_set: + new.append(a) + if dedup is Dedup.OVERRIDDEN: + pre_flush_set.add(a) + for a in reversed(self.post): + dedup = self._can_dedup(a) + if a not in post_flush_set: + post_flush.appendleft(a) + if dedup is Dedup.OVERRIDDEN: + post_flush_set.add(a) + + #pre and post will overwrite every element that is in the container + #only copy over args that are in _container but not in the post flush or pre flush set + if pre_flush_set or post_flush_set: + for a in self._container: + if a not in post_flush_set and a not in pre_flush_set: + new.append(a) + else: + new.extend(self._container) + new.extend(post_flush) + + self._container = new + self.pre.clear() + self.post.clear() + + def __iter__(self) -> T.Iterator[str]: + self.flush_pre_post() + return iter(self._container) + + @T.overload # noqa: F811 + def __getitem__(self, index: int) -> str: # noqa: F811 + pass + + @T.overload # noqa: F811 + def __getitem__(self, index: slice) -> T.MutableSequence[str]: # noqa: F811 + pass + + def __getitem__(self, index: T.Union[int, slice]) -> T.Union[str, T.MutableSequence[str]]: # noqa: F811 + self.flush_pre_post() + return self._container[index] + + @T.overload # noqa: F811 + def __setitem__(self, index: int, value: str) -> None: # noqa: F811 + pass + + @T.overload # noqa: F811 + def __setitem__(self, index: slice, value: T.Iterable[str]) -> None: # noqa: F811 + pass + + def __setitem__(self, index: T.Union[int, slice], value: T.Union[str, T.Iterable[str]]) -> None: # noqa: F811 + self.flush_pre_post() + self._container[index] = value # type: ignore # TODO: fix 'Invalid index type' and 'Incompatible types in assignment' errors + + def __delitem__(self, index: T.Union[int, slice]) -> None: + self.flush_pre_post() + del self._container[index] + + def __len__(self) -> int: + return len(self._container) + len(self.pre) + len(self.post) + + def insert(self, index: int, value: str) -> None: + self.flush_pre_post() + self._container.insert(index, value) + + def copy(self) -> 'CompilerArgs': + self.flush_pre_post() + return type(self)(self.compiler, self._container.copy()) + + @classmethod + @lru_cache(maxsize=None) + def _can_dedup(cls, arg: str) -> Dedup: + """Returns whether the argument can be safely de-duped. + + In addition to these, we handle library arguments specially. + With GNU ld, we surround library arguments with -Wl,--start/end-gr -> Dedupoup + to recursively search for symbols in the libraries. This is not needed + with other linkers. + """ + + # A standalone argument must never be deduplicated because it is + # defined by what comes _after_ it. Thus dedupping this: + # -D FOO -D BAR + # would yield either + # -D FOO BAR + # or + # FOO -D BAR + # both of which are invalid. + if arg in cls.dedup2_prefixes: + return Dedup.NO_DEDUP + if arg in cls.dedup2_args or \ + arg.startswith(cls.dedup2_prefixes) or \ + arg.endswith(cls.dedup2_suffixes): + return Dedup.OVERRIDDEN + if arg in cls.dedup1_args or \ + arg.startswith(cls.dedup1_prefixes) or \ + arg.endswith(cls.dedup1_suffixes) or \ + re.search(cls.dedup1_regex, arg): + return Dedup.UNIQUE + return Dedup.NO_DEDUP + + @classmethod + @lru_cache(maxsize=None) + def _should_prepend(cls, arg: str) -> bool: + return arg.startswith(cls.prepend_prefixes) + + def to_native(self, copy: bool = False) -> T.List[str]: + # Check if we need to add --start/end-group for circular dependencies + # between static libraries, and for recursively searching for symbols + # needed by static libraries that are provided by object files or + # shared libraries. + self.flush_pre_post() + if copy: + new = self.copy() + else: + new = self + return self.compiler.unix_args_to_native(new._container) + + def append_direct(self, arg: str) -> None: + ''' + Append the specified argument without any reordering or de-dup except + for absolute paths to libraries, etc, which can always be de-duped + safely. + ''' + self.flush_pre_post() + if os.path.isabs(arg): + self.append(arg) + else: + self._container.append(arg) + + def extend_direct(self, iterable: T.Iterable[str]) -> None: + ''' + Extend using the elements in the specified iterable without any + reordering or de-dup except for absolute paths where the order of + include search directories is not relevant + ''' + self.flush_pre_post() + for elem in iterable: + self.append_direct(elem) + + def extend_preserving_lflags(self, iterable: T.Iterable[str]) -> None: + normal_flags = [] + lflags = [] + for i in iterable: + if i not in self.always_dedup_args and (i.startswith('-l') or i.startswith('-L')): + lflags.append(i) + else: + normal_flags.append(i) + self.extend(normal_flags) + self.extend_direct(lflags) + + def __add__(self, args: T.Iterable[str]) -> 'CompilerArgs': + self.flush_pre_post() + new = self.copy() + new += args + return new + + def __iadd__(self, args: T.Iterable[str]) -> 'CompilerArgs': + ''' + Add two CompilerArgs while taking into account overriding of arguments + and while preserving the order of arguments as much as possible + ''' + tmp_pre = collections.deque() # type: T.Deque[str] + if not isinstance(args, collections.abc.Iterable): + raise TypeError(f'can only concatenate Iterable[str] (not "{args}") to CompilerArgs') + for arg in args: + # If the argument can be de-duped, do it either by removing the + # previous occurrence of it and adding a new one, or not adding the + # new occurrence. + dedup = self._can_dedup(arg) + if dedup is Dedup.UNIQUE: + # Argument already exists and adding a new instance is useless + if arg in self._container or arg in self.pre or arg in self.post: + continue + if self._should_prepend(arg): + tmp_pre.appendleft(arg) + else: + self.post.append(arg) + self.pre.extendleft(tmp_pre) + #pre and post is going to be merged later before a iter call + return self + + def __radd__(self, args: T.Iterable[str]) -> 'CompilerArgs': + self.flush_pre_post() + new = type(self)(self.compiler, args) + new += self + return new + + def __eq__(self, other: object) -> T.Union[bool]: + self.flush_pre_post() + # Only allow equality checks against other CompilerArgs and lists instances + if isinstance(other, CompilerArgs): + return self.compiler == other.compiler and self._container == other._container + elif isinstance(other, list): + return self._container == other + return NotImplemented + + def append(self, arg: str) -> None: + self.__iadd__([arg]) + + def extend(self, args: T.Iterable[str]) -> None: + self.__iadd__(args) + + def __repr__(self) -> str: + self.flush_pre_post() + return f'CompilerArgs({self.compiler!r}, {self._container!r})' diff -Nru meson-0.53.2/mesonbuild/ast/__init__.py meson-0.61.2/mesonbuild/ast/__init__.py --- meson-0.53.2/mesonbuild/ast/__init__.py 2019-03-06 20:48:10.000000000 +0000 +++ meson-0.61.2/mesonbuild/ast/__init__.py 2020-08-15 16:27:05.000000000 +0000 @@ -20,6 +20,7 @@ 'AstInterpreter', 'AstIDGenerator', 'AstIndentationGenerator', + 'AstJSONPrinter', 'AstVisitor', 'AstPrinter', 'IntrospectionInterpreter', @@ -30,4 +31,4 @@ from .introspection import IntrospectionInterpreter, build_target_functions from .visitor import AstVisitor from .postprocess import AstConditionLevel, AstIDGenerator, AstIndentationGenerator -from .printer import AstPrinter +from .printer import AstPrinter, AstJSONPrinter diff -Nru meson-0.53.2/mesonbuild/ast/interpreter.py meson-0.61.2/mesonbuild/ast/interpreter.py --- meson-0.53.2/mesonbuild/ast/interpreter.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/ast/interpreter.py 2021-12-26 16:24:25.000000000 +0000 @@ -16,56 +16,86 @@ # or an interpreter-based tool. from .visitor import AstVisitor -from .. import interpreterbase, mparser, mesonlib +from .. import mparser, mesonlib from .. import environment -from ..interpreterbase import InvalidArguments, BreakRequest, ContinueRequest +from ..interpreterbase import ( + MesonInterpreterObject, + InterpreterBase, + InvalidArguments, + BreakRequest, + ContinueRequest, + default_resolve_key, + TYPE_nvar, + TYPE_nkwargs, +) + +from ..interpreter import ( + Interpreter, + StringHolder, + BooleanHolder, + IntegerHolder, + ArrayHolder, + DictHolder, +) + from ..mparser import ( + AndNode, ArgumentNode, ArithmeticNode, ArrayNode, AssignmentNode, BaseNode, + ComparisonNode, ElementaryNode, EmptyNode, + ForeachClauseNode, IdNode, + IfClauseNode, + IndexNode, MethodNode, + NotNode, + OrNode, PlusAssignmentNode, TernaryNode, + UMinusNode, ) import os, sys import typing as T -class DontCareObject(interpreterbase.InterpreterObject): +class DontCareObject(MesonInterpreterObject): pass -class MockExecutable(interpreterbase.InterpreterObject): +class MockExecutable(MesonInterpreterObject): pass -class MockStaticLibrary(interpreterbase.InterpreterObject): +class MockStaticLibrary(MesonInterpreterObject): pass -class MockSharedLibrary(interpreterbase.InterpreterObject): +class MockSharedLibrary(MesonInterpreterObject): pass -class MockCustomTarget(interpreterbase.InterpreterObject): +class MockCustomTarget(MesonInterpreterObject): pass -class MockRunTarget(interpreterbase.InterpreterObject): +class MockRunTarget(MesonInterpreterObject): pass ADD_SOURCE = 0 REMOVE_SOURCE = 1 -class AstInterpreter(interpreterbase.InterpreterBase): - def __init__(self, source_root: str, subdir: str, visitors: T.Optional[T.List[AstVisitor]] = None): - super().__init__(source_root, subdir) +_T = T.TypeVar('_T') +_V = T.TypeVar('_V') + +class AstInterpreter(InterpreterBase): + def __init__(self, source_root: str, subdir: str, subproject: str, visitors: T.Optional[T.List[AstVisitor]] = None): + super().__init__(source_root, subdir, subproject) self.visitors = visitors if visitors is not None else [] - self.visited_subdirs = {} - self.assignments = {} - self.assign_vals = {} - self.reverse_assignment = {} + self.processed_buildfiles = set() # type: T.Set[str] + self.assignments = {} # type: T.Dict[str, BaseNode] + self.assign_vals = {} # type: T.Dict[str, T.Any] + self.reverse_assignment = {} # type: T.Dict[str, BaseNode] self.funcs.update({'project': self.func_do_nothing, 'test': self.func_do_nothing, 'benchmark': self.func_do_nothing, @@ -73,6 +103,8 @@ 'install_man': self.func_do_nothing, 'install_data': self.func_do_nothing, 'install_subdir': self.func_do_nothing, + 'install_symlink': self.func_do_nothing, + 'install_emptydir': self.func_do_nothing, 'configuration_data': self.func_do_nothing, 'configure_file': self.func_do_nothing, 'find_program': self.func_do_nothing, @@ -106,6 +138,7 @@ 'subdir': self.func_subdir, 'set_variable': self.func_do_nothing, 'get_variable': self.func_do_nothing, + 'unset_variable': self.func_do_nothing, 'is_disabler': self.func_do_nothing, 'is_variable': self.func_do_nothing, 'disabler': self.func_do_nothing, @@ -120,20 +153,27 @@ 'subdir_done': self.func_do_nothing, 'alias_target': self.func_do_nothing, 'summary': self.func_do_nothing, + 'range': self.func_do_nothing, }) - def func_do_nothing(self, node, args, kwargs): + def _unholder_args(self, args: _T, kwargs: _V) -> T.Tuple[_T, _V]: + return args, kwargs + + def _holderify(self, res: _T) -> _T: + return res + + def func_do_nothing(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> bool: return True - def load_root_meson_file(self): + def load_root_meson_file(self) -> None: super().load_root_meson_file() for i in self.visitors: self.ast.accept(i) - def func_subdir(self, node, args, kwargs): + def func_subdir(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: args = self.flatten_args(args) if len(args) != 1 or not isinstance(args[0], str): - sys.stderr.write('Unable to evaluate subdir({}) in AstInterpreter --> Skipping\n'.format(args)) + sys.stderr.write(f'Unable to evaluate subdir({args}) in AstInterpreter --> Skipping\n') return prev_subdir = self.subdir @@ -142,21 +182,22 @@ buildfilename = os.path.join(subdir, environment.build_filename) absname = os.path.join(self.source_root, buildfilename) symlinkless_dir = os.path.realpath(absdir) - if symlinkless_dir in self.visited_subdirs: + build_file = os.path.join(symlinkless_dir, 'meson.build') + if build_file in self.processed_buildfiles: sys.stderr.write('Trying to enter {} which has already been visited --> Skipping\n'.format(args[0])) return - self.visited_subdirs[symlinkless_dir] = True + self.processed_buildfiles.add(build_file) if not os.path.isfile(absname): - sys.stderr.write('Unable to find build file {} --> Skipping\n'.format(buildfilename)) + sys.stderr.write(f'Unable to find build file {buildfilename} --> Skipping\n') return - with open(absname, encoding='utf8') as f: + with open(absname, encoding='utf-8') as f: code = f.read() - assert(isinstance(code, str)) + assert isinstance(code, str) try: - codeblock = mparser.Parser(code, subdir).parse() + codeblock = mparser.Parser(code, absname).parse() except mesonlib.MesonException as me: - me.file = buildfilename + me.file = absname raise me self.subdir = subdir @@ -165,64 +206,95 @@ self.evaluate_codeblock(codeblock) self.subdir = prev_subdir - def method_call(self, node): + def method_call(self, node: BaseNode) -> bool: return True - def evaluate_arithmeticstatement(self, cur): + def evaluate_fstring(self, node: mparser.FormatStringNode) -> str: + assert isinstance(node, mparser.FormatStringNode) + return node.value + + def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> TYPE_nvar: + return self.reduce_arguments(cur.args)[0] + + def evaluate_arithmeticstatement(self, cur: ArithmeticNode) -> int: self.evaluate_statement(cur.left) self.evaluate_statement(cur.right) return 0 - def evaluate_uminusstatement(self, cur): + def evaluate_uminusstatement(self, cur: UMinusNode) -> int: self.evaluate_statement(cur.value) return 0 - def evaluate_ternary(self, node): - assert(isinstance(node, TernaryNode)) + def evaluate_ternary(self, node: TernaryNode) -> None: + assert isinstance(node, TernaryNode) self.evaluate_statement(node.condition) self.evaluate_statement(node.trueblock) self.evaluate_statement(node.falseblock) - def evaluate_plusassign(self, node): - assert(isinstance(node, PlusAssignmentNode)) - if node.var_name not in self.assignments: - self.assignments[node.var_name] = [] - self.assign_vals[node.var_name] = [] - self.assignments[node.var_name] += [node.value] # Save a reference to the value node - if hasattr(node.value, 'ast_id'): + def evaluate_dictstatement(self, node: mparser.DictNode) -> TYPE_nkwargs: + def resolve_key(node: mparser.BaseNode) -> str: + if isinstance(node, mparser.StringNode): + return node.value + return '__AST_UNKNOWN__' + arguments, kwargs = self.reduce_arguments(node.args, key_resolver=resolve_key) + assert not arguments + self.argument_depth += 1 + for key, value in kwargs.items(): + if isinstance(key, BaseNode): + self.evaluate_statement(key) + self.argument_depth -= 1 + return {} + + def evaluate_plusassign(self, node: PlusAssignmentNode) -> None: + assert isinstance(node, PlusAssignmentNode) + # Cheat by doing a reassignment + self.assignments[node.var_name] = node.value # Save a reference to the value node + if node.value.ast_id: self.reverse_assignment[node.value.ast_id] = node - self.assign_vals[node.var_name] += [self.evaluate_statement(node.value)] + self.assign_vals[node.var_name] = self.evaluate_statement(node.value) - def evaluate_indexing(self, node): + def evaluate_indexing(self, node: IndexNode) -> int: return 0 - def unknown_function_called(self, func_name): + def unknown_function_called(self, func_name: str) -> None: pass - def reduce_arguments(self, args): + def reduce_arguments( + self, + args: mparser.ArgumentNode, + key_resolver: T.Callable[[mparser.BaseNode], str] = default_resolve_key, + duplicate_key_error: T.Optional[str] = None, + ) -> T.Tuple[T.List[TYPE_nvar], TYPE_nkwargs]: if isinstance(args, ArgumentNode): + kwargs = {} # type: T.Dict[str, TYPE_nvar] + for key, val in args.kwargs.items(): + kwargs[key_resolver(key)] = val if args.incorrect_order(): raise InvalidArguments('All keyword arguments must be after positional arguments.') - return self.flatten_args(args.arguments), args.kwargs + return self.flatten_args(args.arguments), kwargs else: return self.flatten_args(args), {} - def evaluate_comparison(self, node): + def evaluate_comparison(self, node: ComparisonNode) -> bool: self.evaluate_statement(node.left) self.evaluate_statement(node.right) return False - def evaluate_andstatement(self, cur): + def evaluate_andstatement(self, cur: AndNode) -> bool: self.evaluate_statement(cur.left) self.evaluate_statement(cur.right) return False - def evaluate_orstatement(self, cur): + def evaluate_orstatement(self, cur: OrNode) -> bool: self.evaluate_statement(cur.left) self.evaluate_statement(cur.right) return False - def evaluate_foreach(self, node): + def evaluate_notstatement(self, cur: NotNode) -> bool: + self.evaluate_statement(cur.value) + return False + + def evaluate_foreach(self, node: ForeachClauseNode) -> None: try: self.evaluate_codeblock(node.block) except ContinueRequest: @@ -230,30 +302,31 @@ except BreakRequest: pass - def evaluate_if(self, node): + def evaluate_if(self, node: IfClauseNode) -> None: for i in node.ifs: self.evaluate_codeblock(i.block) if not isinstance(node.elseblock, EmptyNode): self.evaluate_codeblock(node.elseblock) - def get_variable(self, varname): + def get_variable(self, varname: str) -> int: return 0 - def assignment(self, node): - assert(isinstance(node, AssignmentNode)) - self.assignments[node.var_name] = [node.value] # Save a reference to the value node - if hasattr(node.value, 'ast_id'): + def assignment(self, node: AssignmentNode) -> None: + assert isinstance(node, AssignmentNode) + self.assignments[node.var_name] = node.value # Save a reference to the value node + if node.value.ast_id: self.reverse_assignment[node.value.ast_id] = node - self.assign_vals[node.var_name] = [self.evaluate_statement(node.value)] # Evaluate the value just in case + self.assign_vals[node.var_name] = self.evaluate_statement(node.value) # Evaluate the value just in case def resolve_node(self, node: BaseNode, include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.Optional[T.Any]: def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T.Any: if loop_detect is None: loop_detect = [] if isinstance(n, IdNode): + assert isinstance(n.value, str) if n.value in loop_detect or n.value not in self.assignments: return [] - return quick_resolve(self.assignments[n.value][0], loop_detect = loop_detect + [n.value]) + return quick_resolve(self.assignments[n.value], loop_detect = loop_detect + [n.value]) elif isinstance(n, ElementaryNode): return n.value else: @@ -266,7 +339,7 @@ if not isinstance(node, BaseNode): return None - assert(hasattr(node, 'ast_id')) + assert node.ast_id if node.ast_id in id_loop_detect: return None # Loop detected id_loop_detect += [node.ast_id] @@ -278,6 +351,11 @@ elif isinstance(node, ElementaryNode): result = node.value + elif isinstance(node, NotNode): + result = self.resolve_node(node.value, include_unknown_args, id_loop_detect) + if isinstance(result, bool): + result = not result + elif isinstance(node, ArrayNode): result = [x for x in node.args.arguments] @@ -296,18 +374,19 @@ elif isinstance(node, MethodNode): src = quick_resolve(node.source_object) - margs = self.flatten_args(node.args, include_unknown_args, id_loop_detect) + margs = self.flatten_args(node.args.arguments, include_unknown_args, id_loop_detect) + mkwargs = {} # type: T.Dict[str, TYPE_nvar] try: if isinstance(src, str): - result = self.string_method_call(src, node.name, margs) + result = StringHolder(src, T.cast(Interpreter, self)).method_call(node.name, margs, mkwargs) elif isinstance(src, bool): - result = self.bool_method_call(src, node.name, margs) + result = BooleanHolder(src, T.cast(Interpreter, self)).method_call(node.name, margs, mkwargs) elif isinstance(src, int): - result = self.int_method_call(src, node.name, margs) + result = IntegerHolder(src, T.cast(Interpreter, self)).method_call(node.name, margs, mkwargs) elif isinstance(src, list): - result = self.array_method_call(src, node.name, margs) + result = ArrayHolder(src, T.cast(Interpreter, self)).method_call(node.name, margs, mkwargs) elif isinstance(src, dict): - result = self.dict_method_call(src, node.name, margs) + result = DictHolder(src, T.cast(Interpreter, self)).method_call(node.name, margs, mkwargs) except mesonlib.MesonException: return None @@ -315,7 +394,7 @@ if isinstance(result, BaseNode): result = self.resolve_node(result, include_unknown_args, id_loop_detect) elif isinstance(result, list): - new_res = [] + new_res = [] # type: T.List[TYPE_nvar] for i in result: if isinstance(i, BaseNode): resolved = self.resolve_node(i, include_unknown_args, id_loop_detect) @@ -327,12 +406,14 @@ return result - def flatten_args(self, args: T.Any, include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.List[T.Any]: + def flatten_args(self, args_raw: T.Union[TYPE_nvar, T.Sequence[TYPE_nvar]], include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.List[TYPE_nvar]: # Make sure we are always dealing with lists - if not isinstance(args, list): - args = [args] + if isinstance(args_raw, list): + args = args_raw + else: + args = [args_raw] - flattend_args = [] + flattend_args = [] # type: T.List[TYPE_nvar] # Resolve the contents of args for i in args: @@ -346,7 +427,7 @@ flattend_args += [i] return flattend_args - def flatten_kwargs(self, kwargs: object, include_unknown_args: bool = False): + def flatten_kwargs(self, kwargs: T.Dict[str, TYPE_nvar], include_unknown_args: bool = False) -> T.Dict[str, TYPE_nvar]: flattend_kwargs = {} for key, val in kwargs.items(): if isinstance(val, BaseNode): diff -Nru meson-0.53.2/mesonbuild/ast/introspection.py meson-0.61.2/mesonbuild/ast/introspection.py --- meson-0.53.2/mesonbuild/ast/introspection.py 2019-12-29 22:47:27.000000000 +0000 +++ meson-0.61.2/mesonbuild/ast/introspection.py 2021-11-02 19:58:07.000000000 +0000 @@ -15,30 +15,46 @@ # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool -from . import AstInterpreter +from .interpreter import AstInterpreter +from .visitor import AstVisitor from .. import compilers, environment, mesonlib, optinterpreter from .. import coredata as cdata -from ..mesonlib import MachineChoice -from ..interpreterbase import InvalidArguments -from ..build import Executable, Jar, SharedLibrary, SharedModule, StaticLibrary +from ..mesonlib import MachineChoice, OptionKey +from ..interpreterbase import InvalidArguments, TYPE_nvar +from ..build import BuildTarget, Executable, Jar, SharedLibrary, SharedModule, StaticLibrary from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode +from ..compilers import detect_compiler_for +import typing as T import os +import argparse build_target_functions = ['executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries'] -class IntrospectionHelper: +class IntrospectionHelper(argparse.Namespace): # mimic an argparse namespace - def __init__(self, cross_file): - self.cross_file = cross_file - self.native_file = None - self.cmd_line_options = {} + def __init__(self, cross_file: str): + super().__init__() + self.cross_file = cross_file # type: str + self.native_file = None # type: str + self.cmd_line_options = {} # type: T.Dict[str, str] + + def __eq__(self, other: object) -> bool: + return NotImplemented class IntrospectionInterpreter(AstInterpreter): # Interpreter to detect the options without a build directory # Most of the code is stolen from interpreter.Interpreter - def __init__(self, source_root, subdir, backend, visitors=None, cross_file=None, subproject='', subproject_dir='subprojects', env=None): + def __init__(self, + source_root: str, + subdir: str, + backend: str, + visitors: T.Optional[T.List[AstVisitor]] = None, + cross_file: T.Optional[str] = None, + subproject: str = '', + subproject_dir: str = 'subprojects', + env: T.Optional[environment.Environment] = None): visitors = visitors if visitors is not None else [] - super().__init__(source_root, subdir, visitors=visitors) + super().__init__(source_root, subdir, subproject, visitors=visitors) options = IntrospectionHelper(cross_file) self.cross_file = cross_file @@ -46,16 +62,15 @@ self.environment = environment.Environment(source_root, None, options) else: self.environment = env - self.subproject = subproject self.subproject_dir = subproject_dir self.coredata = self.environment.get_coredata() self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') self.backend = backend - self.default_options = {'backend': self.backend} - self.project_data = {} - self.targets = [] - self.dependencies = [] - self.project_node = None + self.default_options = {OptionKey('backend'): self.backend} + self.project_data = {} # type: T.Dict[str, T.Any] + self.targets = [] # type: T.List[T.Dict[str, T.Any]] + self.dependencies = [] # type: T.List[T.Dict[str, T.Any]] + self.project_node = None # type: BaseNode self.funcs.update({ 'add_languages': self.func_add_languages, @@ -70,7 +85,7 @@ 'both_libraries': self.func_both_lib, }) - def func_project(self, node, args, kwargs): + def func_project(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: if self.project_node: raise InvalidArguments('Second call to project()') self.project_node = node @@ -89,17 +104,18 @@ if os.path.exists(self.option_file): oi = optinterpreter.OptionInterpreter(self.subproject) oi.process(self.option_file) - self.coredata.merge_user_options(oi.options) + self.coredata.update_project_options(oi.options) def_opts = self.flatten_args(kwargs.get('default_options', [])) - self.project_default_options = mesonlib.stringlistify(def_opts) - self.project_default_options = cdata.create_options_dict(self.project_default_options) + _project_default_options = mesonlib.stringlistify(def_opts) + self.project_default_options = cdata.create_options_dict(_project_default_options, self.subproject) self.default_options.update(self.project_default_options) self.coredata.set_default_options(self.default_options, self.subproject, self.environment) if not self.is_subproject() and 'subproject_dir' in kwargs: spdirname = kwargs['subproject_dir'] - if isinstance(spdirname, ElementaryNode): + if isinstance(spdirname, StringNode): + assert isinstance(spdirname.value, str) self.subproject_dir = spdirname.value if not self.is_subproject(): self.project_data['subprojects'] = [] @@ -110,12 +126,13 @@ self.do_subproject(i) self.coredata.init_backend_options(self.backend) - options = {k: v for k, v in self.environment.cmd_line_options.items() if k.startswith('backend_')} + options = {k: v for k, v in self.environment.options.items() if k.is_backend()} self.coredata.set_options(options) - self.func_add_languages(None, proj_langs, None) + self._add_languages(proj_langs, MachineChoice.HOST) + self._add_languages(proj_langs, MachineChoice.BUILD) - def do_subproject(self, dirname): + def do_subproject(self, dirname: str) -> None: subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir) subpr = os.path.join(subproject_dir_abs, dirname) try: @@ -126,15 +143,29 @@ except (mesonlib.MesonException, RuntimeError): return - def func_add_languages(self, node, args, kwargs): - args = self.flatten_args(args) - for for_machine in [MachineChoice.BUILD, MachineChoice.HOST]: - for lang in sorted(args, key=compilers.sort_clink): - lang = lang.lower() - if lang not in self.coredata.compilers[for_machine]: - self.environment.detect_compiler_for(lang, for_machine) + def func_add_languages(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + kwargs = self.flatten_kwargs(kwargs) + if 'native' in kwargs: + native = kwargs.get('native', False) + self._add_languages(args, MachineChoice.BUILD if native else MachineChoice.HOST) + else: + for for_machine in [MachineChoice.BUILD, MachineChoice.HOST]: + self._add_languages(args, for_machine) + + def _add_languages(self, raw_langs: T.List[TYPE_nvar], for_machine: MachineChoice) -> None: + langs = [] # type: T.List[str] + for l in self.flatten_args(raw_langs): + if isinstance(l, str): + langs.append(l) + elif isinstance(l, StringNode): + langs.append(l.value) + + for lang in sorted(langs, key=compilers.sort_clink): + lang = lang.lower() + if lang not in self.coredata.compilers[for_machine]: + detect_compiler_for(self.environment, lang, for_machine) - def func_dependency(self, node, args, kwargs): + def func_dependency(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: args = self.flatten_args(args) kwargs = self.flatten_kwargs(kwargs) if not args: @@ -145,7 +176,6 @@ version = kwargs.get('version', []) if not isinstance(version, list): version = [version] - condition_level = node.condition_level if hasattr(node, 'condition_level') else 0 if isinstance(required, ElementaryNode): required = required.value if not isinstance(required, bool): @@ -155,59 +185,70 @@ 'required': required, 'version': version, 'has_fallback': has_fallback, - 'conditional': condition_level > 0, - 'node': node, + 'conditional': node.condition_level > 0, + 'node': node }] - def build_target(self, node, args, kwargs, targetclass): + def build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs_raw: T.Dict[str, TYPE_nvar], targetclass: T.Type[BuildTarget]) -> T.Optional[T.Dict[str, T.Any]]: args = self.flatten_args(args) if not args or not isinstance(args[0], str): - return + return None name = args[0] srcqueue = [node] + extra_queue = [] # Process the sources BEFORE flattening the kwargs, to preserve the original nodes - if 'sources' in kwargs: - srcqueue += mesonlib.listify(kwargs['sources']) + if 'sources' in kwargs_raw: + srcqueue += mesonlib.listify(kwargs_raw['sources']) + + if 'extra_files' in kwargs_raw: + extra_queue += mesonlib.listify(kwargs_raw['extra_files']) - kwargs = self.flatten_kwargs(kwargs, True) + kwargs = self.flatten_kwargs(kwargs_raw, True) - source_nodes = [] - while srcqueue: - curr = srcqueue.pop(0) - arg_node = None - assert(isinstance(curr, BaseNode)) - if isinstance(curr, FunctionNode): - arg_node = curr.args - elif isinstance(curr, ArrayNode): - arg_node = curr.args - elif isinstance(curr, IdNode): - # Try to resolve the ID and append the node to the queue - var_name = curr.value - if var_name in self.assignments and self.assignments[var_name]: - tmp_node = self.assignments[var_name][0] - if isinstance(tmp_node, (ArrayNode, IdNode, FunctionNode)): - srcqueue += [tmp_node] - elif isinstance(curr, ArithmeticNode): - srcqueue += [curr.left, curr.right] - if arg_node is None: - continue - arg_nodes = arg_node.arguments.copy() - # Pop the first element if the function is a build target function - if isinstance(curr, FunctionNode) and curr.func_name in build_target_functions: - arg_nodes.pop(0) - elemetary_nodes = [x for x in arg_nodes if isinstance(x, (str, StringNode))] - srcqueue += [x for x in arg_nodes if isinstance(x, (FunctionNode, ArrayNode, IdNode, ArithmeticNode))] - if elemetary_nodes: - source_nodes += [curr] + def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: + res = [] # type: T.List[BaseNode] + while inqueue: + curr = inqueue.pop(0) + arg_node = None + assert isinstance(curr, BaseNode) + if isinstance(curr, FunctionNode): + arg_node = curr.args + elif isinstance(curr, ArrayNode): + arg_node = curr.args + elif isinstance(curr, IdNode): + # Try to resolve the ID and append the node to the queue + assert isinstance(curr.value, str) + var_name = curr.value + if var_name in self.assignments: + tmp_node = self.assignments[var_name] + if isinstance(tmp_node, (ArrayNode, IdNode, FunctionNode)): + inqueue += [tmp_node] + elif isinstance(curr, ArithmeticNode): + inqueue += [curr.left, curr.right] + if arg_node is None: + continue + arg_nodes = arg_node.arguments.copy() + # Pop the first element if the function is a build target function + if isinstance(curr, FunctionNode) and curr.func_name in build_target_functions: + arg_nodes.pop(0) + elemetary_nodes = [x for x in arg_nodes if isinstance(x, (str, StringNode))] + inqueue += [x for x in arg_nodes if isinstance(x, (FunctionNode, ArrayNode, IdNode, ArithmeticNode))] + if elemetary_nodes: + res += [curr] + return res + + source_nodes = traverse_nodes(srcqueue) + extraf_nodes = traverse_nodes(extra_queue) # Make sure nothing can crash when creating the build class kwargs_reduced = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs and k in ['install', 'build_by_default', 'build_always']} kwargs_reduced = {k: v.value if isinstance(v, ElementaryNode) else v for k, v in kwargs_reduced.items()} kwargs_reduced = {k: v for k, v in kwargs_reduced.items() if not isinstance(v, BaseNode)} for_machine = MachineChoice.HOST - objects = [] - empty_sources = [] # Passing the unresolved sources list causes errors + objects = [] # type: T.List[T.Any] + empty_sources = [] # type: T.List[T.Any] + # Passing the unresolved sources list causes errors target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, objects, self.environment, kwargs_reduced) new_target = { @@ -220,6 +261,7 @@ 'installed': target.should_install(), 'outputs': target.get_outputs(), 'sources': source_nodes, + 'extra_files': extraf_nodes, 'kwargs': kwargs, 'node': node, } @@ -227,39 +269,40 @@ self.targets += [new_target] return new_target - def build_library(self, node, args, kwargs): - default_library = self.coredata.get_builtin_option('default_library') + def build_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + default_library = self.coredata.get_option(OptionKey('default_library')) if default_library == 'shared': return self.build_target(node, args, kwargs, SharedLibrary) elif default_library == 'static': return self.build_target(node, args, kwargs, StaticLibrary) elif default_library == 'both': return self.build_target(node, args, kwargs, SharedLibrary) + return None - def func_executable(self, node, args, kwargs): + def func_executable(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, Executable) - def func_static_lib(self, node, args, kwargs): + def func_static_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, StaticLibrary) - def func_shared_lib(self, node, args, kwargs): + def func_shared_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, SharedLibrary) - def func_both_lib(self, node, args, kwargs): + def func_both_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, SharedLibrary) - def func_shared_module(self, node, args, kwargs): + def func_shared_module(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, SharedModule) - def func_library(self, node, args, kwargs): + def func_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_library(node, args, kwargs) - def func_jar(self, node, args, kwargs): + def func_jar(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, Jar) - def func_build_target(self, node, args, kwargs): + def func_build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: if 'target_type' not in kwargs: - return + return None target_type = kwargs.pop('target_type') if isinstance(target_type, ElementaryNode): target_type = target_type.value @@ -275,11 +318,12 @@ return self.build_library(node, args, kwargs) elif target_type == 'jar': return self.build_target(node, args, kwargs, Jar) + return None - def is_subproject(self): + def is_subproject(self) -> bool: return self.subproject != '' - def analyze(self): + def analyze(self) -> None: self.load_root_meson_file() self.sanity_check_ast() self.parse_project() diff -Nru meson-0.53.2/mesonbuild/ast/postprocess.py meson-0.61.2/mesonbuild/ast/postprocess.py --- meson-0.53.2/mesonbuild/ast/postprocess.py 2019-03-06 20:48:10.000000000 +0000 +++ meson-0.61.2/mesonbuild/ast/postprocess.py 2021-04-01 21:12:21.000000000 +0000 @@ -17,48 +17,49 @@ from . import AstVisitor from .. import mparser +import typing as T class AstIndentationGenerator(AstVisitor): - def __init__(self): + def __init__(self) -> None: self.level = 0 - def visit_default_func(self, node: mparser.BaseNode): + def visit_default_func(self, node: mparser.BaseNode) -> None: # Store the current level in the node node.level = self.level - def visit_ArrayNode(self, node: mparser.ArrayNode): + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: self.visit_default_func(node) self.level += 1 node.args.accept(self) self.level -= 1 - def visit_DictNode(self, node: mparser.DictNode): + def visit_DictNode(self, node: mparser.DictNode) -> None: self.visit_default_func(node) self.level += 1 node.args.accept(self) self.level -= 1 - def visit_MethodNode(self, node: mparser.MethodNode): + def visit_MethodNode(self, node: mparser.MethodNode) -> None: self.visit_default_func(node) node.source_object.accept(self) self.level += 1 node.args.accept(self) self.level -= 1 - def visit_FunctionNode(self, node: mparser.FunctionNode): + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: self.visit_default_func(node) self.level += 1 node.args.accept(self) self.level -= 1 - def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode): + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: self.visit_default_func(node) self.level += 1 node.items.accept(self) node.block.accept(self) self.level -= 1 - def visit_IfClauseNode(self, node: mparser.IfClauseNode): + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: self.visit_default_func(node) for i in node.ifs: i.accept(self) @@ -67,7 +68,7 @@ node.elseblock.accept(self) self.level -= 1 - def visit_IfNode(self, node: mparser.IfNode): + def visit_IfNode(self, node: mparser.IfNode) -> None: self.visit_default_func(node) self.level += 1 node.condition.accept(self) @@ -75,10 +76,10 @@ self.level -= 1 class AstIDGenerator(AstVisitor): - def __init__(self): - self.counter = {} + def __init__(self) -> None: + self.counter = {} # type: T.Dict[str, int] - def visit_default_func(self, node: mparser.BaseNode): + def visit_default_func(self, node: mparser.BaseNode) -> None: name = type(node).__name__ if name not in self.counter: self.counter[name] = 0 @@ -86,20 +87,20 @@ self.counter[name] += 1 class AstConditionLevel(AstVisitor): - def __init__(self): + def __init__(self) -> None: self.condition_level = 0 - def visit_default_func(self, node: mparser.BaseNode): + def visit_default_func(self, node: mparser.BaseNode) -> None: node.condition_level = self.condition_level - def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode): + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: self.visit_default_func(node) self.condition_level += 1 node.items.accept(self) node.block.accept(self) self.condition_level -= 1 - def visit_IfClauseNode(self, node: mparser.IfClauseNode): + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: self.visit_default_func(node) for i in node.ifs: i.accept(self) @@ -108,7 +109,7 @@ node.elseblock.accept(self) self.condition_level -= 1 - def visit_IfNode(self, node: mparser.IfNode): + def visit_IfNode(self, node: mparser.IfNode) -> None: self.visit_default_func(node) self.condition_level += 1 node.condition.accept(self) diff -Nru meson-0.53.2/mesonbuild/ast/printer.py meson-0.61.2/mesonbuild/ast/printer.py --- meson-0.53.2/mesonbuild/ast/printer.py 2019-12-29 22:47:27.000000000 +0000 +++ meson-0.61.2/mesonbuild/ast/printer.py 2021-08-18 11:22:25.000000000 +0000 @@ -18,6 +18,7 @@ from .. import mparser from . import AstVisitor import re +import typing as T arithmic_map = { 'add': '+', @@ -36,114 +37,115 @@ self.is_newline = True self.last_level = 0 - def post_process(self): + def post_process(self) -> None: self.result = re.sub(r'\s+\n', '\n', self.result) - def append(self, data: str, node: mparser.BaseNode): - level = 0 - if node and hasattr(node, 'level'): - level = node.level - else: - level = self.last_level - self.last_level = level + def append(self, data: str, node: mparser.BaseNode) -> None: + self.last_level = node.level if self.is_newline: - self.result += ' ' * (level * self.indent) + self.result += ' ' * (node.level * self.indent) self.result += data self.is_newline = False - def append_padded(self, data: str, node: mparser.BaseNode): - if self.result[-1] not in [' ', '\n']: + def append_padded(self, data: str, node: mparser.BaseNode) -> None: + if self.result and self.result[-1] not in [' ', '\n']: data = ' ' + data self.append(data + ' ', node) - def newline(self): + def newline(self) -> None: self.result += '\n' self.is_newline = True - def visit_BooleanNode(self, node: mparser.BooleanNode): + def visit_BooleanNode(self, node: mparser.BooleanNode) -> None: self.append('true' if node.value else 'false', node) - def visit_IdNode(self, node: mparser.IdNode): + def visit_IdNode(self, node: mparser.IdNode) -> None: + assert isinstance(node.value, str) self.append(node.value, node) - def visit_NumberNode(self, node: mparser.NumberNode): + def visit_NumberNode(self, node: mparser.NumberNode) -> None: self.append(str(node.value), node) - def visit_StringNode(self, node: mparser.StringNode): + def visit_StringNode(self, node: mparser.StringNode) -> None: + assert isinstance(node.value, str) self.append("'" + node.value + "'", node) - def visit_ContinueNode(self, node: mparser.ContinueNode): + def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: + assert isinstance(node.value, str) + self.append("f'" + node.value + "'", node) + + def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: self.append('continue', node) - def visit_BreakNode(self, node: mparser.BreakNode): + def visit_BreakNode(self, node: mparser.BreakNode) -> None: self.append('break', node) - def visit_ArrayNode(self, node: mparser.ArrayNode): + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: self.append('[', node) node.args.accept(self) self.append(']', node) - def visit_DictNode(self, node: mparser.DictNode): + def visit_DictNode(self, node: mparser.DictNode) -> None: self.append('{', node) node.args.accept(self) self.append('}', node) - def visit_OrNode(self, node: mparser.OrNode): + def visit_OrNode(self, node: mparser.OrNode) -> None: node.left.accept(self) self.append_padded('or', node) node.right.accept(self) - def visit_AndNode(self, node: mparser.AndNode): + def visit_AndNode(self, node: mparser.AndNode) -> None: node.left.accept(self) self.append_padded('and', node) node.right.accept(self) - def visit_ComparisonNode(self, node: mparser.ComparisonNode): + def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: node.left.accept(self) self.append_padded(node.ctype, node) node.right.accept(self) - def visit_ArithmeticNode(self, node: mparser.ArithmeticNode): + def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: node.left.accept(self) self.append_padded(arithmic_map[node.operation], node) node.right.accept(self) - def visit_NotNode(self, node: mparser.NotNode): + def visit_NotNode(self, node: mparser.NotNode) -> None: self.append_padded('not', node) node.value.accept(self) - def visit_CodeBlockNode(self, node: mparser.CodeBlockNode): + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: for i in node.lines: i.accept(self) self.newline() - def visit_IndexNode(self, node: mparser.IndexNode): + def visit_IndexNode(self, node: mparser.IndexNode) -> None: node.iobject.accept(self) self.append('[', node) node.index.accept(self) self.append(']', node) - def visit_MethodNode(self, node: mparser.MethodNode): + def visit_MethodNode(self, node: mparser.MethodNode) -> None: node.source_object.accept(self) self.append('.' + node.name + '(', node) node.args.accept(self) self.append(')', node) - def visit_FunctionNode(self, node: mparser.FunctionNode): + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: self.append(node.func_name + '(', node) node.args.accept(self) self.append(')', node) - def visit_AssignmentNode(self, node: mparser.AssignmentNode): + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: self.append(node.var_name + ' = ', node) node.value.accept(self) - def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode): + def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: self.append(node.var_name + ' += ', node) node.value.accept(self) - def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode): - varnames = [x.value for x in node.varnames] + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + varnames = [x for x in node.varnames] self.append_padded('foreach', node) self.append_padded(', '.join(varnames), node) self.append_padded(':', node) @@ -152,34 +154,34 @@ node.block.accept(self) self.append('endforeach', node) - def visit_IfClauseNode(self, node: mparser.IfClauseNode): + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: prefix = '' for i in node.ifs: self.append_padded(prefix + 'if', node) prefix = 'el' i.accept(self) - if node.elseblock: + if not isinstance(node.elseblock, mparser.EmptyNode): self.append('else', node) node.elseblock.accept(self) self.append('endif', node) - def visit_UMinusNode(self, node: mparser.UMinusNode): + def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: self.append_padded('-', node) node.value.accept(self) - def visit_IfNode(self, node: mparser.IfNode): + def visit_IfNode(self, node: mparser.IfNode) -> None: node.condition.accept(self) self.newline() node.block.accept(self) - def visit_TernaryNode(self, node: mparser.TernaryNode): + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: node.condition.accept(self) self.append_padded('?', node) node.trueblock.accept(self) self.append_padded(':', node) node.falseblock.accept(self) - def visit_ArgumentNode(self, node: mparser.ArgumentNode): + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: break_args = (len(node.arguments) + len(node.kwargs)) > self.arg_newline_cutoff for i in node.arguments + list(node.kwargs.values()): if not isinstance(i, (mparser.ElementaryNode, mparser.IndexNode)): @@ -192,10 +194,7 @@ if break_args: self.newline() for key, val in node.kwargs.items(): - if isinstance(key, str): - self.append(key, node) - else: - key.accept(self) + key.accept(self) self.append_padded(':', node) val.accept(self) self.append(', ', node) @@ -205,3 +204,163 @@ self.result = re.sub(r', \n$', '\n', self.result) else: self.result = re.sub(r', $', '', self.result) + +class AstJSONPrinter(AstVisitor): + def __init__(self) -> None: + self.result = {} # type: T.Dict[str, T.Any] + self.current = self.result + + def _accept(self, key: str, node: mparser.BaseNode) -> None: + old = self.current + data = {} # type: T.Dict[str, T.Any] + self.current = data + node.accept(self) + self.current = old + self.current[key] = data + + def _accept_list(self, key: str, nodes: T.Sequence[mparser.BaseNode]) -> None: + old = self.current + datalist = [] # type: T.List[T.Dict[str, T.Any]] + for i in nodes: + self.current = {} + i.accept(self) + datalist += [self.current] + self.current = old + self.current[key] = datalist + + def _raw_accept(self, node: mparser.BaseNode, data: T.Dict[str, T.Any]) -> None: + old = self.current + self.current = data + node.accept(self) + self.current = old + + def setbase(self, node: mparser.BaseNode) -> None: + self.current['node'] = type(node).__name__ + self.current['lineno'] = node.lineno + self.current['colno'] = node.colno + self.current['end_lineno'] = node.end_lineno + self.current['end_colno'] = node.end_colno + + def visit_default_func(self, node: mparser.BaseNode) -> None: + self.setbase(node) + + def gen_ElementaryNode(self, node: mparser.ElementaryNode) -> None: + self.current['value'] = node.value + self.setbase(node) + + def visit_BooleanNode(self, node: mparser.BooleanNode) -> None: + self.gen_ElementaryNode(node) + + def visit_IdNode(self, node: mparser.IdNode) -> None: + self.gen_ElementaryNode(node) + + def visit_NumberNode(self, node: mparser.NumberNode) -> None: + self.gen_ElementaryNode(node) + + def visit_StringNode(self, node: mparser.StringNode) -> None: + self.gen_ElementaryNode(node) + + def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: + self.gen_ElementaryNode(node) + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + self._accept('args', node.args) + self.setbase(node) + + def visit_DictNode(self, node: mparser.DictNode) -> None: + self._accept('args', node.args) + self.setbase(node) + + def visit_OrNode(self, node: mparser.OrNode) -> None: + self._accept('left', node.left) + self._accept('right', node.right) + self.setbase(node) + + def visit_AndNode(self, node: mparser.AndNode) -> None: + self._accept('left', node.left) + self._accept('right', node.right) + self.setbase(node) + + def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: + self._accept('left', node.left) + self._accept('right', node.right) + self.current['ctype'] = node.ctype + self.setbase(node) + + def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: + self._accept('left', node.left) + self._accept('right', node.right) + self.current['op'] = arithmic_map[node.operation] + self.setbase(node) + + def visit_NotNode(self, node: mparser.NotNode) -> None: + self._accept('right', node.value) + self.setbase(node) + + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: + self._accept_list('lines', node.lines) + self.setbase(node) + + def visit_IndexNode(self, node: mparser.IndexNode) -> None: + self._accept('object', node.iobject) + self._accept('index', node.index) + self.setbase(node) + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + self._accept('object', node.source_object) + self._accept('args', node.args) + self.current['name'] = node.name + self.setbase(node) + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + self._accept('args', node.args) + self.current['name'] = node.func_name + self.setbase(node) + + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: + self._accept('value', node.value) + self.current['var_name'] = node.var_name + self.setbase(node) + + def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: + self._accept('value', node.value) + self.current['var_name'] = node.var_name + self.setbase(node) + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + self._accept('items', node.items) + self._accept('block', node.block) + self.current['varnames'] = node.varnames + self.setbase(node) + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + self._accept_list('ifs', node.ifs) + self._accept('else', node.elseblock) + self.setbase(node) + + def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: + self._accept('right', node.value) + self.setbase(node) + + def visit_IfNode(self, node: mparser.IfNode) -> None: + self._accept('condition', node.condition) + self._accept('block', node.block) + self.setbase(node) + + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: + self._accept('condition', node.condition) + self._accept('true', node.trueblock) + self._accept('false', node.falseblock) + self.setbase(node) + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + self._accept_list('positional', node.arguments) + kwargs_list = [] # type: T.List[T.Dict[str, T.Dict[str, T.Any]]] + for key, val in node.kwargs.items(): + key_res = {} # type: T.Dict[str, T.Any] + val_res = {} # type: T.Dict[str, T.Any] + self._raw_accept(key, key_res) + self._raw_accept(val, val_res) + kwargs_list += [{'key': key_res, 'val': val_res}] + self.current['kwargs'] = kwargs_list + self.setbase(node) diff -Nru meson-0.53.2/mesonbuild/ast/visitor.py meson-0.61.2/mesonbuild/ast/visitor.py --- meson-0.53.2/mesonbuild/ast/visitor.py 2019-08-28 17:15:39.000000000 +0000 +++ meson-0.61.2/mesonbuild/ast/visitor.py 2021-08-18 11:22:25.000000000 +0000 @@ -18,122 +18,125 @@ from .. import mparser class AstVisitor: - def __init__(self): + def __init__(self) -> None: pass - def visit_default_func(self, node: mparser.BaseNode): + def visit_default_func(self, node: mparser.BaseNode) -> None: pass - def visit_BooleanNode(self, node: mparser.BooleanNode): + def visit_BooleanNode(self, node: mparser.BooleanNode) -> None: self.visit_default_func(node) - def visit_IdNode(self, node: mparser.IdNode): + def visit_IdNode(self, node: mparser.IdNode) -> None: self.visit_default_func(node) - def visit_NumberNode(self, node: mparser.NumberNode): + def visit_NumberNode(self, node: mparser.NumberNode) -> None: self.visit_default_func(node) - def visit_StringNode(self, node: mparser.StringNode): + def visit_StringNode(self, node: mparser.StringNode) -> None: self.visit_default_func(node) - def visit_ContinueNode(self, node: mparser.ContinueNode): + def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: self.visit_default_func(node) - def visit_BreakNode(self, node: mparser.BreakNode): + def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: self.visit_default_func(node) - def visit_ArrayNode(self, node: mparser.ArrayNode): + def visit_BreakNode(self, node: mparser.BreakNode) -> None: + self.visit_default_func(node) + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: self.visit_default_func(node) node.args.accept(self) - def visit_DictNode(self, node: mparser.DictNode): + def visit_DictNode(self, node: mparser.DictNode) -> None: self.visit_default_func(node) node.args.accept(self) - def visit_EmptyNode(self, node: mparser.EmptyNode): + def visit_EmptyNode(self, node: mparser.EmptyNode) -> None: self.visit_default_func(node) - def visit_OrNode(self, node: mparser.OrNode): + def visit_OrNode(self, node: mparser.OrNode) -> None: self.visit_default_func(node) node.left.accept(self) node.right.accept(self) - def visit_AndNode(self, node: mparser.AndNode): + def visit_AndNode(self, node: mparser.AndNode) -> None: self.visit_default_func(node) node.left.accept(self) node.right.accept(self) - def visit_ComparisonNode(self, node: mparser.ComparisonNode): + def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: self.visit_default_func(node) node.left.accept(self) node.right.accept(self) - def visit_ArithmeticNode(self, node: mparser.ArithmeticNode): + def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: self.visit_default_func(node) node.left.accept(self) node.right.accept(self) - def visit_NotNode(self, node: mparser.NotNode): + def visit_NotNode(self, node: mparser.NotNode) -> None: self.visit_default_func(node) node.value.accept(self) - def visit_CodeBlockNode(self, node: mparser.CodeBlockNode): + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: self.visit_default_func(node) for i in node.lines: i.accept(self) - def visit_IndexNode(self, node: mparser.IndexNode): + def visit_IndexNode(self, node: mparser.IndexNode) -> None: self.visit_default_func(node) node.iobject.accept(self) node.index.accept(self) - def visit_MethodNode(self, node: mparser.MethodNode): + def visit_MethodNode(self, node: mparser.MethodNode) -> None: self.visit_default_func(node) node.source_object.accept(self) node.args.accept(self) - def visit_FunctionNode(self, node: mparser.FunctionNode): + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: self.visit_default_func(node) node.args.accept(self) - def visit_AssignmentNode(self, node: mparser.AssignmentNode): + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: self.visit_default_func(node) node.value.accept(self) - def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode): + def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: self.visit_default_func(node) node.value.accept(self) - def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode): + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: self.visit_default_func(node) node.items.accept(self) node.block.accept(self) - def visit_IfClauseNode(self, node: mparser.IfClauseNode): + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: self.visit_default_func(node) for i in node.ifs: i.accept(self) - if node.elseblock: - node.elseblock.accept(self) + node.elseblock.accept(self) - def visit_UMinusNode(self, node: mparser.UMinusNode): + def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: self.visit_default_func(node) node.value.accept(self) - def visit_IfNode(self, node: mparser.IfNode): + def visit_IfNode(self, node: mparser.IfNode) -> None: self.visit_default_func(node) node.condition.accept(self) node.block.accept(self) - def visit_TernaryNode(self, node: mparser.TernaryNode): + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: self.visit_default_func(node) node.condition.accept(self) node.trueblock.accept(self) node.falseblock.accept(self) - def visit_ArgumentNode(self, node: mparser.ArgumentNode): + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: self.visit_default_func(node) for i in node.arguments: i.accept(self) - for val in node.kwargs.values(): + for key, val in node.kwargs.items(): + key.accept(self) val.accept(self) diff -Nru meson-0.53.2/mesonbuild/backend/backends.py meson-0.61.2/mesonbuild/backend/backends.py --- meson-0.53.2/mesonbuild/backend/backends.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/backends.py 2022-02-14 19:03:13.000000000 +0000 @@ -12,22 +12,89 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os, pickle, re -import textwrap +from collections import OrderedDict +from functools import lru_cache +from itertools import chain +from pathlib import Path +import enum +import json +import os +import pickle +import re +import typing as T +import hashlib + from .. import build from .. import dependencies +from .. import programs from .. import mesonlib from .. import mlog -import json -import subprocess -from ..mesonlib import MachineChoice, MesonException, OrderedSet, OptionOverrideProxy -from ..mesonlib import classify_unity_sources -from ..mesonlib import File -from ..compilers import CompilerArgs, VisualStudioLikeCompiler -from collections import OrderedDict -import shlex -from functools import lru_cache -import typing as T +from ..compilers import LANGUAGES_USING_LDFLAGS, detect +from ..mesonlib import ( + File, MachineChoice, MesonException, OptionType, OrderedSet, OptionOverrideProxy, + classify_unity_sources, OptionKey, join_args +) + +if T.TYPE_CHECKING: + from .._typing import ImmutableListProtocol + from ..arglist import CompilerArgs + from ..compilers import Compiler + from ..environment import Environment + from ..interpreter import Interpreter, Test + from ..linkers import StaticLinker + from ..mesonlib import FileMode, FileOrString + from ..wrap import WrapMode + + from typing_extensions import TypedDict + + class TargetIntrospectionData(TypedDict): + + language: str + compiler : T.List[str] + parameters: T.List[str] + sources: T.List[str] + generated_sources: T.List[str] + + +# Languages that can mix with C or C++ but don't support unity builds yet +# because the syntax we use for unity builds is specific to C/++/ObjC/++. +# Assembly files cannot be unitified and neither can LLVM IR files +LANGS_CANT_UNITY = ('d', 'fortran', 'vala') + +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 + +class TestProtocol(enum.Enum): + + EXITCODE = 0 + TAP = 1 + GTEST = 2 + RUST = 3 + + @classmethod + def from_str(cls, string: str) -> 'TestProtocol': + if string == 'exitcode': + return cls.EXITCODE + elif string == 'tap': + return cls.TAP + elif string == 'gtest': + return cls.GTEST + elif string == 'rust': + return cls.RUST + raise MesonException(f'unknown test format {string}') + + def __str__(self) -> str: + cls = type(self) + if self is cls.EXITCODE: + return 'exitcode' + elif self is cls.GTEST: + return 'gtest' + elif self is cls.RUST: + return 'rust' + return 'tap' class CleanTrees: @@ -35,66 +102,136 @@ 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, trees): + def __init__(self, build_dir: str, trees: T.List[str]): self.build_dir = build_dir self.trees = trees class InstallData: - def __init__(self, source_dir, build_dir, prefix, strip_bin, - install_umask, mesonintrospect): + 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 - self.targets = [] - self.headers = [] - self.man = [] - self.data = [] - self.po_package_name = '' - self.po = [] - self.install_scripts = [] - self.install_subdirs = [] + self.targets: T.List[TargetInstallData] = [] + self.headers: T.List[InstallDataBase] = [] + self.man: T.List[InstallDataBase] = [] + self.emptydir: T.List[InstallEmptyDir] = [] + self.data: T.List[InstallDataBase] = [] + 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 class TargetInstallData: - def __init__(self, fname, outdir, aliases, strip, install_name_mappings, install_rpath, install_mode, optional=False): + + # TODO: install_mode should just always be a FileMode object + + 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 + +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 + +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 + +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 + +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]], + subproject: str, tag: T.Optional[str] = None, data_type: T.Optional[str] = None): + super().__init__(path, install_path, install_path_name, install_mode, subproject, tag, data_type) + self.exclude = exclude class ExecutableSerialisation: - def __init__(self, cmd_args, env=None, exe_wrapper=None, - workdir=None, extra_paths=None, capture=None): + + # 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 or {} + self.env = env if exe_wrapper is not None: - assert(isinstance(exe_wrapper, dependencies.ExternalProgram)) - self.exe_runner = exe_wrapper + 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 + self.pickled = False + self.skip_if_destdir = False + self.verbose = verbose + self.subproject = '' + self.tag = tag class TestSerialisation: - def __init__(self, name: str, project: str, suite: str, fname: T.List[str], - is_cross_built: bool, exe_wrapper: T.Optional[build.Executable], + 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: str, priority: int): + 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, dependencies.ExternalProgram)) - self.exe_runner = exe_wrapper + assert isinstance(exe_wrapper, programs.ExternalProgram) + self.exe_wrapper = exe_wrapper self.is_parallel = is_parallel self.cmd_args = cmd_args self.env = env @@ -105,85 +242,128 @@ 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 -def get_backend_from_name(backend, build): + +def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, interpreter: T.Optional['Interpreter'] = None) -> T.Optional['Backend']: if backend == 'ninja': from . import ninjabackend - return ninjabackend.NinjaBackend(build) + return ninjabackend.NinjaBackend(build, interpreter) elif backend == 'vs': from . import vs2010backend - return vs2010backend.autodetect_vs_version(build) + return vs2010backend.autodetect_vs_version(build, interpreter) elif backend == 'vs2010': from . import vs2010backend - return vs2010backend.Vs2010Backend(build) + return vs2010backend.Vs2010Backend(build, interpreter) + elif backend == 'vs2012': + from . import vs2012backend + return vs2012backend.Vs2012Backend(build, interpreter) + elif backend == 'vs2013': + from . import vs2013backend + return vs2013backend.Vs2013Backend(build, interpreter) elif backend == 'vs2015': from . import vs2015backend - return vs2015backend.Vs2015Backend(build) + return vs2015backend.Vs2015Backend(build, interpreter) elif backend == 'vs2017': from . import vs2017backend - return vs2017backend.Vs2017Backend(build) + return vs2017backend.Vs2017Backend(build, interpreter) elif backend == 'vs2019': from . import vs2019backend - return vs2019backend.Vs2019Backend(build) + return vs2019backend.Vs2019Backend(build, interpreter) + elif backend == 'vs2022': + from . import vs2022backend + return vs2022backend.Vs2022Backend(build, interpreter) elif backend == 'xcode': from . import xcodebackend - return xcodebackend.XCodeBackend(build) + return xcodebackend.XCodeBackend(build, interpreter) return None # This class contains the basic functionality that is needed by all backends. # Feel free to move stuff in and out of it as you see fit. class Backend: - def __init__(self, build): + + environment: T.Optional['Environment'] + + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional['Interpreter']): # Make it possible to construct a dummy backend # This is used for introspection without a build directory if build is None: self.environment = None return self.build = build + self.interpreter = interpreter self.environment = build.environment - self.processed_targets = {} + self.processed_targets: T.Set[str] = set() + self.name = '' self.build_dir = self.environment.get_build_dir() self.source_dir = self.environment.get_source_dir() self.build_to_src = mesonlib.relpath(self.environment.get_source_dir(), self.environment.get_build_dir()) + self.src_to_build = mesonlib.relpath(self.environment.get_build_dir(), + self.environment.get_source_dir()) + + def generate(self) -> None: + raise RuntimeError(f'generate is not implemented in {type(self).__name__}') - def get_target_filename(self, t): + def get_target_filename(self, t: T.Union[build.Target, build.CustomTargetIndex], *, warn_multi_output: bool = True) -> str: if isinstance(t, build.CustomTarget): - if len(t.get_outputs()) != 1: - mlog.warning('custom_target {!r} has more than one output! ' - 'Using the first one.'.format(t.name)) + if warn_multi_output and len(t.get_outputs()) != 1: + mlog.warning(f'custom_target {t.name!r} has more than one output! ' + 'Using the first one.') filename = t.get_outputs()[0] elif isinstance(t, build.CustomTargetIndex): filename = t.get_outputs()[0] else: - assert(isinstance(t, build.BuildTarget)) + assert isinstance(t, build.BuildTarget) filename = t.get_filename() return os.path.join(self.get_target_dir(t), filename) - def get_target_filename_abs(self, target): + def get_target_filename_abs(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target)) - def get_builtin_options_for_target(self, target): - return OptionOverrideProxy(target.option_overrides, - self.environment.coredata.builtins) - - def get_base_options_for_target(self, target): - return OptionOverrideProxy(target.option_overrides, - self.environment.coredata.builtins, - self.environment.coredata.base_options) - - def get_compiler_options_for_target(self, target): - return OptionOverrideProxy( - target.option_overrides, - self.environment.coredata.compiler_options[target.for_machine]) - - def get_option_for_target(self, option_name, target): - if option_name in target.option_overrides: - override = target.option_overrides[option_name] - return self.environment.coredata.validate_option_value(option_name, override) - return self.environment.coredata.get_builtin_option(option_name) + def get_base_options_for_target(self, target: build.BuildTarget) -> OptionOverrideProxy: + return OptionOverrideProxy(target.option_overrides_base, + {k: v for k, v in self.environment.coredata.options.items() + if k.type in {OptionType.BASE, OptionType.BUILTIN}}) + + def get_compiler_options_for_target(self, target: build.BuildTarget) -> OptionOverrideProxy: + comp_reg = {k: v for k, v in self.environment.coredata.options.items() if k.is_compiler()} + comp_override = target.option_overrides_compiler + return OptionOverrideProxy(comp_override, comp_reg) + + def get_option_for_target(self, option_name: 'OptionKey', target: build.BuildTarget) -> T.Union[str, int, bool, 'WrapMode']: + if option_name in target.option_overrides_base: + override = target.option_overrides_base[option_name] + v = self.environment.coredata.validate_option_value(option_name, override) + else: + v = self.environment.coredata.get_option(option_name.evolve(subproject=target.subproject)) + # We don't actually have wrapmode here to do an assert, so just do a + # cast, we know what's in coredata anyway. + # TODO: if it's possible to annotate get_option or validate_option_value + # in the future we might be able to remove the cast here + return T.cast(T.Union[str, int, bool, 'WrapMode'], v) + + def get_source_dir_include_args(self, target: build.BuildTarget, compiler: 'Compiler', *, absolute_path: bool = False) -> T.List[str]: + curdir = target.get_subdir() + if absolute_path: + lead = self.source_dir + else: + lead = self.build_to_src + tmppath = os.path.normpath(os.path.join(lead, curdir)) + return compiler.get_include_args(tmppath, False) + + def get_build_dir_include_args(self, target: build.BuildTarget, compiler: 'Compiler', *, absolute_path: bool = False) -> T.List[str]: + if absolute_path: + curdir = os.path.join(self.build_dir, target.get_subdir()) + else: + curdir = target.get_subdir() + if curdir == '': + curdir = '.' + return compiler.get_include_args(curdir, False) - def get_target_filename_for_linking(self, target): + def get_target_filename_for_linking(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> T.Optional[str]: # On some platforms (msvc for instance), the file that is used for # dynamic linking is not the same as the dynamic library itself. This # file is called an import library, and we want to link against that. @@ -195,44 +375,50 @@ return os.path.join(self.get_target_dir(target), target.get_filename()) elif isinstance(target, (build.CustomTarget, build.CustomTargetIndex)): if not target.is_linkable_target(): - raise MesonException('Tried to link against custom target "%s", which is not linkable.' % target.name) + raise MesonException(f'Tried to link against custom target "{target.name}", which is not linkable.') return os.path.join(self.get_target_dir(target), target.get_filename()) elif isinstance(target, build.Executable): if target.import_filename: return os.path.join(self.get_target_dir(target), target.get_import_filename()) else: return None - raise AssertionError('BUG: Tried to link to {!r} which is not linkable'.format(target)) + raise AssertionError(f'BUG: Tried to link to {target!r} which is not linkable') @lru_cache(maxsize=None) - def get_target_dir(self, target): - if self.environment.coredata.get_builtin_option('layout') == 'mirror': + def get_target_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: + if isinstance(target, build.RunTarget): + # this produces no output, only a dummy top-level name + dirname = '' + elif self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': dirname = target.get_subdir() else: dirname = 'meson-out' return dirname - def get_target_dir_relative_to(self, t, o): + def get_target_dir_relative_to(self, t: build.Target, o: build.Target) -> str: '''Get a target dir relative to another target's directory''' target_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(t)) othert_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(o)) return os.path.relpath(target_dir, othert_dir) - def get_target_source_dir(self, target): + def get_target_source_dir(self, target: build.Target) -> str: # if target dir is empty, avoid extraneous trailing / from os.path.join() target_dir = self.get_target_dir(target) if target_dir: return os.path.join(self.build_to_src, target_dir) return self.build_to_src - def get_target_private_dir(self, target): - return os.path.join(self.get_target_dir(target), target.get_id()) + def get_target_private_dir(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]) -> str: + return os.path.join(self.get_target_filename(target, warn_multi_output=False) + '.p') - def get_target_private_dir_abs(self, target): + def get_target_private_dir_abs(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]) -> str: return os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target)) @lru_cache(maxsize=None) - def get_target_generated_dir(self, target, gensrc, src): + def get_target_generated_dir( + self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex], + gensrc: T.Union[build.CustomTarget, build.CustomTargetIndex, build.GeneratedList], + src: str) -> str: """ Takes a BuildTarget, a generator source (CustomTarget or GeneratedList), and a generated source filename. @@ -245,19 +431,22 @@ # target that the GeneratedList is used in return os.path.join(self.get_target_private_dir(target), src) - def get_unity_source_file(self, target, suffix): + def get_unity_source_file(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex], + suffix: str, number: int) -> mesonlib.File: # There is a potential conflict here, but it is unlikely that # anyone both enables unity builds and has a file called foo-unity.cpp. - osrc = target.name + '-unity.' + suffix + osrc = f'{target.name}-unity{number}.{suffix}' return mesonlib.File.from_built_file(self.get_target_private_dir(target), osrc) - def generate_unity_files(self, target, unity_src): - abs_files = [] - result = [] + def generate_unity_files(self, target: build.BuildTarget, unity_src: str) -> T.List[mesonlib.File]: + abs_files: T.List[str] = [] + result: T.List[mesonlib.File] = [] compsrcs = classify_unity_sources(target.compilers.values(), unity_src) + unity_size = self.get_option_for_target(OptionKey('unity_size'), target) + assert isinstance(unity_size, int), 'for mypy' - def init_language_file(suffix): - unity_src = self.get_unity_source_file(target, suffix) + def init_language_file(suffix: str, unity_file_number: int) -> T.TextIO: + unity_src = self.get_unity_source_file(target, suffix, unity_file_number) outfileabs = unity_src.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) outfileabs_tmp = outfileabs + '.tmp' @@ -266,33 +455,58 @@ if not os.path.exists(outfileabs_tmp_dir): os.makedirs(outfileabs_tmp_dir) result.append(unity_src) - return open(outfileabs_tmp, 'w') + return open(outfileabs_tmp, 'w', encoding='utf-8') - # For each language, generate a unity source file and return the list + # For each language, generate unity source files and return the list for comp, srcs in compsrcs.items(): - with init_language_file(comp.get_default_suffix()) as ofile: - for src in srcs: - ofile.write('#include<%s>\n' % src) - [mesonlib.replace_if_different(x, x + '.tmp') for x in abs_files] + files_in_current = unity_size + 1 + unity_file_number = 0 + # TODO: this could be simplified with an algorithm that pre-sorts + # the sources into the size of chunks we want + ofile = None + for src in srcs: + if files_in_current >= unity_size: + if ofile: + ofile.close() + ofile = init_language_file(comp.get_default_suffix(), unity_file_number) + unity_file_number += 1 + files_in_current = 0 + ofile.write(f'#include<{src}>\n') + files_in_current += 1 + if ofile: + ofile.close() + + for x in abs_files: + mesonlib.replace_if_different(x, x + '.tmp') return result - def relpath(self, todir, fromdir): + @staticmethod + def relpath(todir: str, fromdir: str) -> str: return os.path.relpath(os.path.join('dummyprefixdir', todir), os.path.join('dummyprefixdir', fromdir)) - def flatten_object_list(self, target, proj_dir_to_build_root=''): + def flatten_object_list(self, target: build.BuildTarget, proj_dir_to_build_root: str = '') -> T.List[str]: obj_list = self._flatten_object_list(target, target.get_objects(), proj_dir_to_build_root) return list(dict.fromkeys(obj_list)) - def _flatten_object_list(self, target, objects, proj_dir_to_build_root): - obj_list = [] + def _flatten_object_list(self, target: build.BuildTarget, + objects: T.Sequence[T.Union[str, 'File', build.ExtractedObjects]], + proj_dir_to_build_root: str) -> T.List[str]: + obj_list: T.List[str] = [] for obj in objects: if isinstance(obj, str): o = os.path.join(proj_dir_to_build_root, self.build_to_src, target.get_subdir(), obj) obj_list.append(o) elif isinstance(obj, mesonlib.File): - obj_list.append(obj.rel_to_builddir(self.build_to_src)) + if obj.is_built: + o = os.path.join(proj_dir_to_build_root, + obj.rel_to_builddir(self.build_to_src)) + obj_list.append(o) + else: + o = os.path.join(proj_dir_to_build_root, + self.build_to_src) + obj_list.append(obj.rel_to_builddir(o)) elif isinstance(obj, build.ExtractedObjects): if obj.recursive: obj_list += self._flatten_object_list(obj.target, obj.objlist, proj_dir_to_build_root) @@ -301,77 +515,172 @@ raise MesonException('Unknown data type in object list.') return obj_list - def as_meson_exe_cmdline(self, tname, exe, cmd_args, workdir=None, - for_machine=MachineChoice.BUILD, - extra_bdeps=None, capture=None, force_serialize=False): - ''' - Serialize an executable for running with a generator or a custom target - ''' - import hashlib - machine = self.environment.machines[for_machine] - if machine.is_windows() or machine.is_cygwin(): - extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps or []) - else: - extra_paths = [] + @staticmethod + def is_swift_target(target: build.BuildTarget) -> bool: + for s in target.sources: + if s.endswith('swift'): + return True + return False + + def determine_swift_dep_dirs(self, target: build.BuildTarget) -> T.List[str]: + result: T.List[str] = [] + for l in target.link_targets: + result.append(self.get_target_private_dir_abs(l)) + return result - if isinstance(exe, dependencies.ExternalProgram): + def get_executable_serialisation( + self, cmd: T.Sequence[T.Union[programs.ExternalProgram, build.BuildTarget, build.CustomTarget, File, str]], + workdir: T.Optional[str] = None, + extra_bdeps: T.Optional[T.List[build.BuildTarget]] = None, + capture: T.Optional[bool] = None, + feed: T.Optional[bool] = None, + env: T.Optional[build.EnvironmentVariables] = None, + tag: T.Optional[str] = None, + verbose: bool = False) -> 'ExecutableSerialisation': + + # XXX: cmd_args either need to be lowered to strings, or need to be checked for non-string arguments, right? + exe, *raw_cmd_args = cmd + if isinstance(exe, programs.ExternalProgram): exe_cmd = exe.get_command() exe_for_machine = exe.for_machine - elif isinstance(exe, (build.BuildTarget, build.CustomTarget)): + elif isinstance(exe, build.BuildTarget): exe_cmd = [self.get_target_filename_abs(exe)] exe_for_machine = exe.for_machine + elif isinstance(exe, build.CustomTarget): + # The output of a custom target can either be directly runnable + # or not, that is, a script, a native binary or a cross compiled + # binary when exe wrapper is available and when it is not. + # This implementation is not exhaustive but it works in the + # common cases. + exe_cmd = [self.get_target_filename_abs(exe)] + exe_for_machine = MachineChoice.BUILD + elif isinstance(exe, mesonlib.File): + exe_cmd = [exe.rel_to_builddir(self.environment.source_dir)] + exe_for_machine = MachineChoice.BUILD else: exe_cmd = [exe] exe_for_machine = MachineChoice.BUILD + cmd_args: T.List[str] = [] + for c in raw_cmd_args: + if isinstance(c, programs.ExternalProgram): + p = c.get_path() + assert isinstance(p, str) + cmd_args.append(p) + elif isinstance(c, (build.BuildTarget, build.CustomTarget)): + cmd_args.append(self.get_target_filename_abs(c)) + elif isinstance(c, mesonlib.File): + cmd_args.append(c.rel_to_builddir(self.environment.source_dir)) + else: + cmd_args.append(c) + + machine = self.environment.machines[exe_for_machine] + if machine.is_windows() or machine.is_cygwin(): + extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps or []) + else: + extra_paths = [] + is_cross_built = not self.environment.machines.matches_build_machine(exe_for_machine) if is_cross_built and self.environment.need_exe_wrapper(): exe_wrapper = self.environment.get_exe_wrapper() - if not exe_wrapper.found(): - msg = 'The exe_wrapper {!r} defined in the cross file is ' \ - 'needed by target {!r}, but was not found. Please ' \ - 'check the command and/or add it to PATH.' - raise MesonException(msg.format(exe_wrapper.name, tname)) + if not exe_wrapper or not exe_wrapper.found(): + msg = 'An exe_wrapper is needed but was not found. Please define one ' \ + 'in cross file and check the command and/or add it to PATH.' + raise MesonException(msg) else: if exe_cmd[0].endswith('.jar'): exe_cmd = ['java', '-jar'] + exe_cmd - elif exe_cmd[0].endswith('.exe') and not (mesonlib.is_windows() or mesonlib.is_cygwin()): + elif exe_cmd[0].endswith('.exe') and not (mesonlib.is_windows() or mesonlib.is_cygwin() or mesonlib.is_wsl()): exe_cmd = ['mono'] + exe_cmd exe_wrapper = None - force_serialize = force_serialize or extra_paths or workdir or \ - exe_wrapper or any('\n' in c for c in cmd_args) + workdir = workdir or self.environment.get_build_dir() + return ExecutableSerialisation(exe_cmd + cmd_args, env, + exe_wrapper, workdir, + extra_paths, capture, feed, tag, verbose) + + def as_meson_exe_cmdline(self, exe: T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, programs.ExternalProgram], + cmd_args: T.Sequence[T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, programs.ExternalProgram]], + workdir: T.Optional[str] = None, + extra_bdeps: T.Optional[T.List[build.BuildTarget]] = None, + capture: T.Optional[bool] = None, + feed: T.Optional[bool] = None, + force_serialize: bool = False, + env: T.Optional[build.EnvironmentVariables] = None, + verbose: bool = False) -> T.Tuple[T.Sequence[T.Union[str, File, build.Target, programs.ExternalProgram]], str]: + ''' + Serialize an executable for running with a generator or a custom target + ''' + cmd: T.List[T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, programs.ExternalProgram]] = [] + cmd.append(exe) + cmd.extend(cmd_args) + es = self.get_executable_serialisation(cmd, workdir, extra_bdeps, capture, feed, env, verbose=verbose) + reasons: T.List[str] = [] + if es.extra_paths: + reasons.append('to set PATH') + + if es.exe_wrapper: + reasons.append('to use exe_wrapper') + + if workdir: + reasons.append('to set workdir') + + if any('\n' in c for c in es.cmd_args): + reasons.append('because command contains newlines') + + if es.env and es.env.varnames: + reasons.append('to set env') + + force_serialize = force_serialize or bool(reasons) + + if capture: + reasons.append('to capture output') + if feed: + reasons.append('to feed input') + if not force_serialize: - if not capture: - return None - return (self.environment.get_build_command() + - ['--internal', 'exe', '--capture', capture, '--'] + exe_cmd + cmd_args) + if not capture and not feed: + return es.cmd_args, '' + args: T.List[str] = [] + if capture: + args += ['--capture', str(capture)] + if feed: + args += ['--feed', str(feed)] + + return ( + self.environment.get_build_command() + ['--internal', 'exe'] + args + ['--'] + es.cmd_args, + ', '.join(reasons) + ) - workdir = workdir or self.environment.get_build_dir() - env = {} - if isinstance(exe, (dependencies.ExternalProgram, + if isinstance(exe, (programs.ExternalProgram, build.BuildTarget, build.CustomTarget)): basename = exe.name + elif isinstance(exe, mesonlib.File): + basename = os.path.basename(exe.fname) else: basename = os.path.basename(exe) # Can't just use exe.name here; it will likely be run more than once - # Take a digest of the cmd args, env, workdir, and capture. This avoids - # collisions and also makes the name deterministic over regenerations - # which avoids a rebuild by Ninja because the cmdline stays the same. - data = bytes(str(sorted(env.items())) + str(cmd_args) + str(workdir) + str(capture), - encoding='utf-8') - digest = hashlib.sha1(data).hexdigest() - scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename, digest) + # Take a digest of the cmd args, env, workdir, capture, and feed. This + # avoids collisions and also makes the name deterministic over + # regenerations which avoids a rebuild by Ninja because the cmdline + # stays the same. + hasher = hashlib.sha1() + if es.env: + es.env.hash(hasher) + hasher.update(bytes(str(es.cmd_args), encoding='utf-8')) + hasher.update(bytes(str(es.workdir), encoding='utf-8')) + hasher.update(bytes(str(capture), encoding='utf-8')) + hasher.update(bytes(str(feed), encoding='utf-8')) + digest = hasher.hexdigest() + scratch_file = f'meson_exe_{basename}_{digest}.dat' exe_data = os.path.join(self.environment.get_scratch_dir(), scratch_file) with open(exe_data, 'wb') as f: - es = ExecutableSerialisation(exe_cmd + cmd_args, env, - exe_wrapper, workdir, - extra_paths, capture) pickle.dump(es, f) - return self.environment.get_build_command() + ['--internal', 'exe', '--unpickle', exe_data] + return (self.environment.get_build_command() + ['--internal', 'exe', '--unpickle', exe_data], + ', '.join(reasons)) - def serialize_tests(self): + def serialize_tests(self) -> T.Tuple[str, str]: test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat') with open(test_data, 'wb') as datafile: self.write_test_file(datafile) @@ -380,7 +689,7 @@ self.write_benchmark_file(datafile) return test_data, benchmark_data - def determine_linker_and_stdlib_args(self, target): + def determine_linker_and_stdlib_args(self, target: build.BuildTarget) -> T.Tuple[T.Union['Compiler', 'StaticLinker'], T.List[str]]: ''' If we're building a static library, there is only one static linker. Otherwise, we query the target for the dynamic linker. @@ -391,49 +700,116 @@ return l, stdlib_args @staticmethod - def _libdir_is_system(libdir, compilers, env): + def _libdir_is_system(libdir: str, compilers: T.Mapping[str, 'Compiler'], env: 'Environment') -> bool: libdir = os.path.normpath(libdir) for cc in compilers.values(): if libdir in cc.get_library_dirs(env): return True return False - def rpaths_for_bundled_shared_libraries(self, target, exclude_system=True): - paths = [] + def get_external_rpath_dirs(self, target: build.BuildTarget) -> T.Set[str]: + args: T.List[str] = [] + for lang in LANGUAGES_USING_LDFLAGS: + try: + e = self.environment.coredata.get_external_link_args(target.for_machine, lang) + if isinstance(e, str): + args.append(e) + else: + 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, + rpath_regex = re.compile(r'-Wl,-rpath[=,]([^,]+)') + # Match solaris style compat runpath formats: + # -Wl,-R + # -Wl,-R, + runpath_regex = re.compile(r'-Wl,-R[,]?([^,]+)') + # Match symbols formats: + # -Wl,--just-symbols= + # -Wl,--just-symbols, + symbols_regex = re.compile(r'-Wl,--just-symbols[=,]([^,]+)') + for arg in args: + rpath_match = rpath_regex.match(arg) + if rpath_match: + for dir in rpath_match.group(1).split(':'): + dirs.add(dir) + runpath_match = runpath_regex.match(arg) + if runpath_match: + for dir in runpath_match.group(1).split(':'): + # The symbols arg is an rpath if the path is a directory + if Path(dir).is_dir(): + dirs.add(dir) + symbols_match = symbols_regex.match(arg) + if symbols_match: + for dir in symbols_match.group(1).split(':'): + # Prevent usage of --just-symbols to specify rpath + if Path(dir).is_dir(): + raise MesonException(f'Invalid arg for --just-symbols, {dir} is a directory.') + return dirs + + @lru_cache(maxsize=None) + 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 - # 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), 'rel_to_src: {} is absolute'.format(rel_to_src) - paths.append(os.path.join(self.build_to_src, rel_to_src)) - else: - paths.append(libdir) - return paths + 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.update(self.rpaths_for_non_system_absolute_shared_libraries(i, exclude_system)) + return list(paths) - def determine_rpath_dirs(self, target): - if self.environment.coredata.get_builtin_option('layout') == 'mirror': - result = target.get_link_dep_subdirs() + # This may take other types + def determine_rpath_dirs(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex] + ) -> T.Tuple[str, ...]: + result: OrderedSet[str] + if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': + # Need a copy here + result = OrderedSet(target.get_link_dep_subdirs()) else: result = OrderedSet() result.add('meson-out') - result.update(self.rpaths_for_bundled_shared_libraries(target)) + if isinstance(target, build.BuildTarget): + 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) - def object_filename_from_source(self, target, source): + @staticmethod + def canonicalize_filename(fname: str) -> str: + for ch in ('/', '\\', ':'): + fname = fname.replace(ch, '_') + return fname + + def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOrString') -> str: assert isinstance(source, mesonlib.File) build_dir = self.environment.get_build_dir() rel_src = source.rel_to_builddir(self.build_to_src) @@ -448,42 +824,41 @@ else: rel_src = os.path.basename(rel_src) # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. - source = 'meson-generated_' + rel_src[:-5] + '.c' + gen_source = 'meson-generated_' + rel_src[:-5] + '.c' elif source.is_built: if os.path.isabs(rel_src): rel_src = rel_src[len(build_dir) + 1:] targetdir = self.get_target_private_dir(target) # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. - source = 'meson-generated_' + os.path.relpath(rel_src, targetdir) + gen_source = 'meson-generated_' + os.path.relpath(rel_src, targetdir) else: if os.path.isabs(rel_src): - # Not from the source directory; hopefully this doesn't conflict with user's source files. - source = os.path.basename(rel_src) + # Use the absolute path directly to avoid file name conflicts + gen_source = rel_src else: - source = os.path.relpath(os.path.join(build_dir, rel_src), - os.path.join(self.environment.get_source_dir(), target.get_subdir())) + gen_source = os.path.relpath(os.path.join(build_dir, rel_src), + os.path.join(self.environment.get_source_dir(), target.get_subdir())) machine = self.environment.machines[target.for_machine] - return source.replace('/', '_').replace('\\', '_') + '.' + machine.get_object_suffix() + return self.canonicalize_filename(gen_source) + '.' + machine.get_object_suffix() - def determine_ext_objs(self, extobj, proj_dir_to_build_root): - result = [] + def determine_ext_objs(self, extobj: 'build.ExtractedObjects', proj_dir_to_build_root: str) -> T.List[str]: + result: T.List[str] = [] # Merge sources and generated sources - sources = list(extobj.srclist) + raw_sources = list(extobj.srclist) for gensrc in extobj.genlist: - for s in gensrc.get_outputs(): - path = self.get_target_generated_dir(extobj.target, gensrc, s) + for r in gensrc.get_outputs(): + path = self.get_target_generated_dir(extobj.target, gensrc, r) dirpart, fnamepart = os.path.split(path) - sources.append(File(True, dirpart, fnamepart)) + raw_sources.append(File(True, dirpart, fnamepart)) # Filter out headers and all non-source files - filtered_sources = [] - for s in sources: + sources: T.List['FileOrString'] = [] + for s in raw_sources: if self.environment.is_source(s) and not self.environment.is_header(s): - filtered_sources.append(s) + sources.append(s) elif self.environment.is_object(s): result.append(s.relative_name()) - sources = filtered_sources # extobj could contain only objects and no sources if not sources: @@ -491,16 +866,23 @@ targetdir = self.get_target_private_dir(extobj.target) - # With unity builds, there's just one object that contains all the - # sources, and we only support extracting all the objects in this mode, - # so just return that. + # With unity builds, sources don't map directly to objects, + # we only support extracting all the objects in this mode, + # so just return all object files. if self.is_unity(extobj.target): compsrcs = classify_unity_sources(extobj.target.compilers.values(), sources) sources = [] - for comp in compsrcs.keys(): - osrc = self.get_unity_source_file(extobj.target, - comp.get_default_suffix()) - sources.append(osrc) + unity_size = self.get_option_for_target(OptionKey('unity_size'), extobj.target) + assert isinstance(unity_size, int), 'for mypy' + + for comp, srcs in compsrcs.items(): + if comp.language in LANGS_CANT_UNITY: + sources += srcs + continue + for i in range(len(srcs) // unity_size + 1): + _src = self.get_unity_source_file(extobj.target, + comp.get_default_suffix(), i) + sources.append(_src) for osrc in sources: objname = self.object_filename_from_source(extobj.target, osrc) @@ -509,8 +891,8 @@ return result - def get_pch_include_args(self, compiler, target): - args = [] + def get_pch_include_args(self, compiler: 'Compiler', target: build.BuildTarget) -> T.List[str]: + args: T.List[str] = [] pchpath = self.get_target_private_dir(target) includeargs = compiler.get_include_args(pchpath, False) p = target.get_pch(compiler.get_language()) @@ -518,87 +900,92 @@ args += compiler.get_pch_use_args(pchpath, p[0]) return includeargs + args - def create_msvc_pch_implementation(self, target, lang, pch_header): + def create_msvc_pch_implementation(self, target: build.BuildTarget, lang: str, pch_header: str) -> str: # We have to include the language in the file name, otherwise # pch.c and pch.cpp will both end up as pch.obj in VS backends. - impl_name = 'meson_pch-%s.%s' % (lang, lang) + impl_name = f'meson_pch-{lang}.{lang}' pch_rel_to_build = os.path.join(self.get_target_private_dir(target), impl_name) # Make sure to prepend the build dir, since the working directory is # not defined. Otherwise, we might create the file in the wrong path. pch_file = os.path.join(self.build_dir, pch_rel_to_build) os.makedirs(os.path.dirname(pch_file), exist_ok=True) - content = '#include "%s"' % os.path.basename(pch_header) + content = f'#include "{os.path.basename(pch_header)}"' pch_file_tmp = pch_file + '.tmp' - with open(pch_file_tmp, 'w') as f: + with open(pch_file_tmp, 'w', encoding='utf-8') as f: f.write(content) mesonlib.replace_if_different(pch_file, pch_file_tmp) return pch_rel_to_build @staticmethod - def escape_extra_args(compiler, args): - # No extra escaping/quoting needed when not running on Windows - if not mesonlib.is_windows(): - return args - extra_args = [] - # Compiler-specific escaping is needed for -D args but not for any others - if isinstance(compiler, VisualStudioLikeCompiler): - # MSVC needs escaping when a -D argument ends in \ or \" - for arg in args: - if arg.startswith('-D') or arg.startswith('/D'): - # Without extra escaping for these two, the next character - # gets eaten - if arg.endswith('\\'): - arg += '\\' - elif arg.endswith('\\"'): - arg = arg[:-2] + '\\\\"' - extra_args.append(arg) - else: - # MinGW GCC needs all backslashes in defines to be doubly-escaped - # FIXME: Not sure about Cygwin or Clang - for arg in args: - if arg.startswith('-D') or arg.startswith('/D'): - arg = arg.replace('\\', '\\\\') - extra_args.append(arg) + def escape_extra_args(args: T.List[str]) -> T.List[str]: + # all backslashes in defines are doubly-escaped + extra_args: T.List[str] = [] + for arg in args: + if arg.startswith(('-D', '/D')): + arg = arg.replace('\\', '\\\\') + extra_args.append(arg) + return extra_args - def generate_basic_compiler_args(self, target, compiler, no_warn_args=False): + def get_no_stdlib_args(self, target: 'build.BuildTarget', compiler: 'Compiler') -> T.List[str]: + if compiler.language in self.build.stdlibs[target.for_machine]: + return compiler.get_no_stdinc_args() + return [] + + def generate_basic_compiler_args(self, target: build.BuildTarget, compiler: 'Compiler', no_warn_args: bool = False) -> 'CompilerArgs': # Create an empty commands list, and start adding arguments from # various sources in the order in which they must override each other # starting from hard-coded defaults followed by build options and so on. - commands = CompilerArgs(compiler) + commands = compiler.compiler_args() copt_proxy = self.get_compiler_options_for_target(target) # First, the trivial ones that are impossible to override. # # Add -nostdinc/-nostdinc++ if needed; can't be overridden - commands += self.get_cross_stdlib_args(target, compiler) + commands += self.get_no_stdlib_args(target, compiler) # Add things like /NOLOGO or -pipe; usually can't be overridden commands += compiler.get_always_args() # Only add warning-flags by default if the buildtype enables it, and if # we weren't explicitly asked to not emit warnings (for Vala, f.ex) if no_warn_args: commands += compiler.get_no_warn_args() - elif self.get_option_for_target('buildtype', target) != 'plain': - commands += compiler.get_warn_args(self.get_option_for_target('warning_level', target)) + else: + # warning_level is a string, but mypy can't determine that + commands += compiler.get_warn_args(T.cast(str, self.get_option_for_target(OptionKey('warning_level'), target))) # Add -Werror if werror=true is set in the build options set on the # command-line or default_options inside project(). This only sets the # action to be done for warnings if/when they are emitted, so it's ok # to set it after get_no_warn_args() or get_warn_args(). - if self.get_option_for_target('werror', target): + if self.get_option_for_target(OptionKey('werror'), target): commands += compiler.get_werror_args() # Add compile args for c_* or cpp_* build options set on the # command-line or default_options inside project(). commands += compiler.get_option_compile_args(copt_proxy) + # Add buildtype args: optimization level, debugging, etc. - commands += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target)) - commands += compiler.get_optimization_args(self.get_option_for_target('optimization', target)) - commands += compiler.get_debug_args(self.get_option_for_target('debug', target)) + buildtype = self.get_option_for_target(OptionKey('buildtype'), target) + assert isinstance(buildtype, str), 'for mypy' + commands += compiler.get_buildtype_args(buildtype) + + optimization = self.get_option_for_target(OptionKey('optimization'), target) + assert isinstance(optimization, str), 'for mypy' + commands += compiler.get_optimization_args(optimization) + + debug = self.get_option_for_target(OptionKey('debug'), target) + assert isinstance(debug, bool), 'for mypy' + commands += compiler.get_debug_args(debug) + # Add compile args added using add_project_arguments() commands += self.build.get_project_args(compiler, target.subproject, target.for_machine) # Add compile args added using add_global_arguments() # These override per-project arguments commands += self.build.get_global_args(compiler, target.for_machine) + # Using both /ZI and /Zi at the same times produces a compiler warning. + # We do not add /ZI by default. If it is being used it is because the user has explicitly enabled it. + # /ZI needs to be removed in that case to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi') + if ('/ZI' in commands) and ('/Zi' in commands): + commands.remove('/Zi') # Compile args added from the env: CFLAGS/CXXFLAGS, etc, or the cross # file. We want these to override all the defaults, but not the # per-target compile args. @@ -609,7 +996,7 @@ # Set -fPIC for static libraries by default unless explicitly disabled if isinstance(target, build.StaticLibrary) and target.pic: commands += compiler.get_pic_args() - if isinstance(target, build.Executable) and target.pie: + elif isinstance(target, (build.StaticLibrary, build.Executable)) and target.pie: commands += compiler.get_pie_args() # Add compile args needed to find external dependencies. Link args are # added while generating the link command. @@ -639,16 +1026,16 @@ # pkg-config puts the thread flags itself via `Cflags:` # Fortran requires extra include directives. if compiler.language == 'fortran': - for lt in target.link_targets: + for lt in chain(target.link_targets, target.link_whole_targets): priv_dir = self.get_target_private_dir(lt) commands += compiler.get_include_args(priv_dir, False) return commands - def build_target_link_arguments(self, compiler, deps): - args = [] + def build_target_link_arguments(self, compiler: 'Compiler', deps: T.List[build.Target]) -> T.List[str]: + args: T.List[str] = [] for d in deps: - if not (d.is_linkable_target()): - raise RuntimeError('Tried to link with a non-library target "%s".' % d.get_basename()) + if not d.is_linkable_target(): + raise RuntimeError(f'Tried to link with a non-library target "{d.get_basename()}".') arg = self.get_target_filename_for_linking(d) if not arg: continue @@ -659,8 +1046,8 @@ args.append(arg) return args - def get_mingw_extra_paths(self, target): - paths = OrderedSet() + def get_mingw_extra_paths(self, target: build.BuildTarget) -> T.List[str]: + paths: OrderedSet[str] = OrderedSet() # The cross bindir root = self.environment.properties[target.for_machine].get_root() if root: @@ -676,24 +1063,28 @@ paths.update(cc.get_library_dirs(self.environment)) return list(paths) - def determine_windows_extra_paths(self, target: T.Union[build.BuildTarget, str], extra_bdeps): - '''On Windows there is no such thing as an rpath. + def determine_windows_extra_paths( + self, target: T.Union[build.BuildTarget, build.CustomTarget, programs.ExternalProgram, mesonlib.File, str], + extra_bdeps: T.Sequence[T.Union[build.BuildTarget, build.CustomTarget]]) -> T.List[str]: + """On Windows there is no such thing as an rpath. + We must determine all locations of DLLs that this exe links to and return them so they can be used in unit - tests.''' - result = set() - prospectives = set() + tests. + """ + result: T.Set[str] = set() + prospectives: T.Set[build.Target] = 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.update(bdep.get_transitive_link_deps()) + prospectives.add(bdep) + if isinstance(bdep, build.BuildTarget): + prospectives.update(bdep.get_transitive_link_deps()) # Internal deps for ld in prospectives: - if ld == '' or ld == '.': - continue dirseg = os.path.join(self.environment.get_build_dir(), self.get_target_dir(ld)) result.add(dirseg) if (isinstance(target, build.BuildTarget) and @@ -701,119 +1092,164 @@ result.update(self.get_mingw_extra_paths(target)) return list(result) - def write_benchmark_file(self, datafile): + def write_benchmark_file(self, datafile: T.BinaryIO) -> None: self.write_test_serialisation(self.build.get_benchmarks(), datafile) - def write_test_file(self, datafile): + def write_test_file(self, datafile: T.BinaryIO) -> None: self.write_test_serialisation(self.build.get_tests(), datafile) - def create_test_serialisation(self, tests): - arr = [] + def create_test_serialisation(self, tests: T.List['Test']) -> T.List[TestSerialisation]: + arr: T.List[TestSerialisation] = [] for t in sorted(tests, key=lambda tst: -1 * tst.priority): exe = t.get_exe() - if isinstance(exe, dependencies.ExternalProgram): + if isinstance(exe, programs.ExternalProgram): cmd = exe.get_command() else: - cmd = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))] - if isinstance(exe, (build.BuildTarget, dependencies.ExternalProgram)): + cmd = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe))] + if isinstance(exe, (build.BuildTarget, programs.ExternalProgram)): test_for_machine = exe.for_machine else: # E.g. an external verifier or simulator program run on a generated executable. # Can always be run without a wrapper. test_for_machine = MachineChoice.BUILD - is_cross = not self.environment.machines.matches_build_machine(test_for_machine) + + # we allow passing compiled executables to tests, which may be cross built. + # We need to consider these as well when considering whether the target is cross or not. + for a in t.cmd_args: + if isinstance(a, build.BuildTarget): + if a.for_machine is MachineChoice.HOST: + test_for_machine = MachineChoice.HOST + break + + is_cross = self.environment.is_cross_build(test_for_machine) if is_cross and self.environment.need_exe_wrapper(): exe_wrapper = self.environment.get_exe_wrapper() else: exe_wrapper = None machine = self.environment.machines[exe.for_machine] if machine.is_windows() or machine.is_cygwin(): - extra_bdeps = [] + extra_bdeps: T.List[T.Union[build.BuildTarget, build.CustomTarget]] = [] if isinstance(exe, build.CustomTarget): - extra_bdeps = exe.get_transitive_build_target_deps() + extra_bdeps = list(exe.get_transitive_build_target_deps()) extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps) else: extra_paths = [] - cmd_args = [] + + cmd_args: T.List[str] = [] + depends: T.Set[build.Target] = set(t.depends) + if isinstance(exe, build.Target): + depends.add(exe) for a in t.cmd_args: - if hasattr(a, 'held_object'): - a = a.held_object + if isinstance(a, build.Target): + depends.add(a) + elif isinstance(a, build.CustomTargetIndex): + depends.add(a.target) if isinstance(a, build.BuildTarget): extra_paths += self.determine_windows_extra_paths(a, []) + if isinstance(a, mesonlib.File): a = os.path.join(self.environment.get_build_dir(), a.rel_to_builddir(self.build_to_src)) cmd_args.append(a) elif isinstance(a, str): cmd_args.append(a) - elif isinstance(a, build.Target): - cmd_args.append(self.construct_target_rel_path(a, t.workdir)) + elif isinstance(a, (build.Target, build.CustomTargetIndex)): + cmd_args.extend(self.construct_target_rel_paths(a, t.workdir)) else: raise MesonException('Bad object in test command.') ts = TestSerialisation(t.get_name(), t.project_name, t.suite, cmd, is_cross, exe_wrapper, self.environment.need_exe_wrapper(), t.is_parallel, cmd_args, t.env, t.should_fail, t.timeout, t.workdir, - extra_paths, t.protocol, t.priority) + extra_paths, t.protocol, t.priority, + isinstance(exe, build.Executable), + [x.get_id() for x in depends], + self.environment.coredata.version) arr.append(ts) return arr - def write_test_serialisation(self, tests, datafile): + def write_test_serialisation(self, tests: T.List['Test'], datafile: T.BinaryIO) -> None: pickle.dump(self.create_test_serialisation(tests), datafile) - def construct_target_rel_path(self, a, workdir): - if workdir is None: - return self.get_target_filename(a) - assert(os.path.isabs(workdir)) - abs_path = self.get_target_filename_abs(a) - return os.path.relpath(abs_path, workdir) + def construct_target_rel_paths(self, t: T.Union[build.Target, build.CustomTargetIndex], workdir: T.Optional[str]) -> T.List[str]: + target_dir = self.get_target_dir(t) + # ensure that test executables can be run when passed as arguments + if isinstance(t, build.Executable) and workdir is None: + target_dir = target_dir or '.' + + if isinstance(t, build.BuildTarget): + outputs = [t.get_filename()] + else: + assert isinstance(t, (build.CustomTarget, build.CustomTargetIndex)) + outputs = t.get_outputs() - def generate_depmf_install(self, d): + outputs = [os.path.join(target_dir, x) for x in outputs] + if workdir is not None: + assert os.path.isabs(workdir) + outputs = [os.path.join(self.environment.get_build_dir(), x) for x in outputs] + outputs = [os.path.relpath(x, workdir) for x in outputs] + return outputs + + def generate_depmf_install(self, d: InstallData) -> None: if self.build.dep_manifest_name is None: return ifilename = os.path.join(self.environment.get_build_dir(), 'depmf.json') ofilename = os.path.join(self.environment.get_prefix(), self.build.dep_manifest_name) - mfobj = {'type': 'dependency manifest', 'version': '1.0', 'projects': self.build.dep_manifest} - with open(ifilename, 'w') as f: + out_name = os.path.join('{prefix}', self.build.dep_manifest_name) + mfobj = {'type': 'dependency manifest', 'version': '1.0', + 'projects': {k: v.to_json() for k, v in self.build.dep_manifest.items()}} + with open(ifilename, 'w', encoding='utf-8') as f: f.write(json.dumps(mfobj)) # Copy file from, to, and with mode unchanged - d.data.append([ifilename, ofilename, None]) + d.data.append(InstallDataBase(ifilename, ofilename, out_name, None, '', + tag='devel', data_type='depmf')) - def get_regen_filelist(self): + def get_regen_filelist(self) -> T.List[str]: '''List of all files whose alteration means that the build definition needs to be regenerated.''' - deps = [os.path.join(self.build_to_src, df) - for df in self.interpreter.get_build_def_files()] + deps = OrderedSet([str(Path(self.build_to_src) / df) + for df in self.interpreter.get_build_def_files()]) if self.environment.is_cross_build(): - deps.extend(self.environment.coredata.cross_files) - deps.extend(self.environment.coredata.config_files) - deps.append('meson-private/coredata.dat') - if os.path.exists(os.path.join(self.environment.get_source_dir(), 'meson_options.txt')): - deps.append(os.path.join(self.build_to_src, 'meson_options.txt')) - for sp in self.build.subprojects.keys(): - fname = os.path.join(self.environment.get_source_dir(), sp, 'meson_options.txt') - if os.path.isfile(fname): - deps.append(os.path.join(self.build_to_src, sp, 'meson_options.txt')) - return deps - - def exe_object_to_cmd_array(self, exe): - if isinstance(exe, build.BuildTarget): - if exe.for_machine is not MachineChoice.BUILD: - if (self.environment.is_cross_build() and - self.environment.exe_wrapper is None and - self.environment.need_exe_wrapper()): - s = textwrap.dedent(''' - Cannot use target {} as a generator because it is built for the - host machine and no exe wrapper is defined or needs_exe_wrapper is - true. You might want to set `native: true` instead to build it for - the build machine.'''.format(exe.name)) - raise MesonException(s) - exe_arr = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe))] + deps.update(self.environment.coredata.cross_files) + deps.update(self.environment.coredata.config_files) + deps.add('meson-private/coredata.dat') + self.check_clock_skew(deps) + return list(deps) + + def generate_regen_info(self) -> None: + deps = self.get_regen_filelist() + regeninfo = RegenInfo(self.environment.get_source_dir(), + self.environment.get_build_dir(), + deps) + filename = os.path.join(self.environment.get_scratch_dir(), + 'regeninfo.dump') + with open(filename, 'wb') as f: + pickle.dump(regeninfo, f) + + def check_clock_skew(self, file_list: T.Iterable[str]) -> None: + # If a file that leads to reconfiguration has a time + # stamp in the future, it will trigger an eternal reconfigure + # loop. + import time + now = time.time() + for f in file_list: + absf = os.path.join(self.environment.get_build_dir(), f) + ftime = os.path.getmtime(absf) + delta = ftime - now + # On Windows disk time stamps sometimes point + # to the future by a minuscule amount, less than + # 0.001 seconds. I don't know why. + if delta > 0.001: + raise MesonException(f'Clock skew detected. File {absf} has a time stamp {delta:.4f}s in the future.') + + def build_target_to_cmd_array(self, bt: T.Union[build.BuildTarget, programs.ExternalProgram]) -> T.List[str]: + if isinstance(bt, build.BuildTarget): + arr = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(bt))] else: - exe_arr = exe.get_command() - return exe_arr + arr = bt.get_command() + return arr - def replace_extra_args(self, args, genlist): - final_args = [] + def replace_extra_args(self, args: T.List[str], genlist: 'build.GeneratedList') -> T.List[str]: + final_args: T.List[str] = [] for a in args: if a == '@EXTRA_ARGS@': final_args += genlist.get_extra_args() @@ -821,37 +1257,33 @@ final_args.append(a) return final_args - def replace_outputs(self, args, private_dir, output_list): - newargs = [] + def replace_outputs(self, args: T.List[str], private_dir: str, output_list: T.List[str]) -> T.List[str]: + newargs: T.List[str] = [] regex = re.compile(r'@OUTPUT(\d+)@') for arg in args: m = regex.search(arg) while m is not None: index = int(m.group(1)) - src = '@OUTPUT%d@' % index + src = f'@OUTPUT{index}@' arg = arg.replace(src, os.path.join(private_dir, output_list[index])) m = regex.search(arg) newargs.append(arg) return newargs - def get_build_by_default_targets(self): - result = OrderedDict() + def get_build_by_default_targets(self) -> 'T.OrderedDict[str, T.Union[build.BuildTarget, build.CustomTarget]]': + result: 'T.OrderedDict[str, T.Union[build.BuildTarget, build.CustomTarget]]' = OrderedDict() # Get all build and custom targets that must be built by default - for name, t in self.build.get_targets().items(): - if t.build_by_default: - result[name] = t + for name, b in self.build.get_targets().items(): + if b.build_by_default: + result[name] = b # Get all targets used as test executables and arguments. These must # also be built by default. XXX: Sometime in the future these should be # built only before running tests. for t in self.build.get_tests(): exe = t.exe - if hasattr(exe, 'held_object'): - exe = exe.held_object if isinstance(exe, (build.CustomTarget, build.BuildTarget)): result[exe.get_id()] = exe for arg in t.cmd_args: - if hasattr(arg, 'held_object'): - arg = arg.held_object if not isinstance(arg, (build.CustomTarget, build.BuildTarget)): continue result[arg.get_id()] = arg @@ -861,49 +1293,45 @@ return result @lru_cache(maxsize=None) - def get_custom_target_provided_by_generated_source(self, generated_source): - libs = [] + def get_custom_target_provided_by_generated_source(self, generated_source: build.CustomTarget) -> 'ImmutableListProtocol[str]': + libs: T.List[str] = [] for f in generated_source.get_outputs(): if self.environment.is_library(f): libs.append(os.path.join(self.get_target_dir(generated_source), f)) return libs @lru_cache(maxsize=None) - def get_custom_target_provided_libraries(self, target): - libs = [] + def get_custom_target_provided_libraries(self, target: T.Union[build.BuildTarget, build.CustomTarget]) -> 'ImmutableListProtocol[str]': + libs: T.List[str] = [] for t in target.get_generated_sources(): if not isinstance(t, build.CustomTarget): continue - l = self.get_custom_target_provided_by_generated_source(t) - libs = libs + l + libs.extend(self.get_custom_target_provided_by_generated_source(t)) return libs - def is_unity(self, target): - optval = self.get_option_for_target('unity', target) - if optval == 'on' or (optval == 'subprojects' and target.subproject != ''): - return True - return False + def is_unity(self, target: build.BuildTarget) -> bool: + optval = self.get_option_for_target(OptionKey('unity'), target) + return optval == 'on' or (optval == 'subprojects' and target.subproject != '') - def get_custom_target_sources(self, target): + def get_custom_target_sources(self, target: build.CustomTarget) -> T.List[str]: ''' Custom target sources can be of various object types; strings, File, BuildTarget, even other CustomTargets. Returns the path to them relative to the build root directory. ''' - srcs = [] + srcs: T.List[str] = [] for i in target.get_sources(): - if hasattr(i, 'held_object'): - i = i.held_object if isinstance(i, str): fname = [os.path.join(self.build_to_src, target.subdir, i)] elif isinstance(i, build.BuildTarget): fname = [self.get_target_filename(i)] elif isinstance(i, (build.CustomTarget, build.CustomTargetIndex)): - fname = [os.path.join(self.get_target_dir(i), p) for p in i.get_outputs()] + fname = [os.path.join(self.get_custom_target_output_dir(i), p) for p in i.get_outputs()] elif isinstance(i, build.GeneratedList): fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outputs()] elif isinstance(i, build.ExtractedObjects): - fname = [os.path.join(self.get_target_private_dir(i.target), p) for p in i.get_outputs(self)] + outputs = i.get_outputs(self) + fname = self.get_extracted_obj_paths(i.target, outputs) else: fname = [i.rel_to_builddir(self.build_to_src)] if target.absolute_paths: @@ -911,8 +1339,11 @@ srcs += fname return srcs - def get_custom_target_depend_files(self, target, absolute_paths=False): - deps = [] + def get_extracted_obj_paths(self, target: build.BuildTarget, outputs: T.List[str]) -> T.List[str]: + return [os.path.join(self.get_target_private_dir(target), p) for p in outputs] + + def get_custom_target_depend_files(self, target: build.CustomTarget, absolute_paths: bool = False) -> T.List[str]: + deps: T.List[str] = [] for i in target.depend_files: if isinstance(i, mesonlib.File): if absolute_paths: @@ -927,69 +1358,99 @@ deps.append(os.path.join(self.build_to_src, target.subdir, i)) return deps - def eval_custom_target_command(self, target, absolute_outputs=False): + def get_custom_target_output_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: + # The XCode backend is special. A target foo/bar does + # not go to ${BUILDDIR}/foo/bar but instead to + # ${BUILDDIR}/${BUILDTYPE}/foo/bar. + # Currently we set the include dir to be the former, + # and not the latter. Thus we need this extra customisation + # point. If in the future we make include dirs et al match + # ${BUILDDIR}/${BUILDTYPE} instead, this becomes unnecessary. + return self.get_target_dir(target) + + @lru_cache(maxsize=None) + def get_normpath_target(self, source: str) -> str: + return os.path.normpath(source) + + def get_custom_target_dirs(self, target: build.CustomTarget, compiler: 'Compiler', *, + absolute_path: bool = False) -> T.List[str]: + custom_target_include_dirs: T.List[str] = [] + for i in target.get_generated_sources(): + # Generator output goes into the target private dir which is + # already in the include paths list. Only custom targets have their + # own target build dir. + if not isinstance(i, (build.CustomTarget, build.CustomTargetIndex)): + continue + idir = self.get_normpath_target(self.get_custom_target_output_dir(i)) + if not idir: + idir = '.' + if absolute_path: + idir = os.path.join(self.environment.get_build_dir(), idir) + if idir not in custom_target_include_dirs: + custom_target_include_dirs.append(idir) + return custom_target_include_dirs + + def get_custom_target_dir_include_args( + self, target: build.CustomTarget, compiler: 'Compiler', *, + absolute_path: bool = False) -> T.List[str]: + incs: T.List[str] = [] + for i in self.get_custom_target_dirs(target, compiler, absolute_path=absolute_path): + incs += compiler.get_include_args(i, False) + return incs + + def eval_custom_target_command( + self, target: build.CustomTarget, absolute_outputs: bool = False) -> \ + T.Tuple[T.List[str], T.List[str], T.List[str]]: # We want the outputs to be absolute only when using the VS backend # XXX: Maybe allow the vs backend to use relative paths too? source_root = self.build_to_src build_root = '.' - outdir = self.get_target_dir(target) + outdir = self.get_custom_target_output_dir(target) if absolute_outputs: source_root = self.environment.get_source_dir() build_root = self.environment.get_build_dir() outdir = os.path.join(self.environment.get_build_dir(), outdir) - outputs = [] - for i in target.get_outputs(): - outputs.append(os.path.join(outdir, i)) + outputs = [os.path.join(outdir, i) for i in target.get_outputs()] inputs = self.get_custom_target_sources(target) # Evaluate the command list - cmd = [] + cmd: T.List[str] = [] for i in target.command: - if isinstance(i, build.Executable): - cmd += self.exe_object_to_cmd_array(i) + if isinstance(i, build.BuildTarget): + cmd += self.build_target_to_cmd_array(i) continue elif isinstance(i, build.CustomTarget): # GIR scanner will attempt to execute this binary but # it assumes that it is in path, so always give it a full path. tmp = i.get_outputs()[0] - i = os.path.join(self.get_target_dir(i), tmp) + i = os.path.join(self.get_custom_target_output_dir(i), tmp) elif isinstance(i, mesonlib.File): i = i.rel_to_builddir(self.build_to_src) - if target.absolute_paths: + if target.absolute_paths or absolute_outputs: i = os.path.join(self.environment.get_build_dir(), i) # FIXME: str types are blindly added ignoring 'target.absolute_paths' # because we can't know if they refer to a file or just a string - elif not isinstance(i, str): - err_msg = 'Argument {0} is of unknown type {1}' - raise RuntimeError(err_msg.format(str(i), str(type(i)))) - elif '@SOURCE_ROOT@' in i: - i = i.replace('@SOURCE_ROOT@', source_root) - elif '@BUILD_ROOT@' in i: - i = i.replace('@BUILD_ROOT@', build_root) - elif '@DEPFILE@' in i: - if target.depfile is None: - msg = 'Custom target {!r} has @DEPFILE@ but no depfile ' \ - 'keyword argument.'.format(target.name) - raise MesonException(msg) - dfilename = os.path.join(outdir, target.depfile) - i = i.replace('@DEPFILE@', dfilename) - elif '@PRIVATE_DIR@' in i: - if target.absolute_paths: - pdir = self.get_target_private_dir_abs(target) - else: - pdir = self.get_target_private_dir(target) - i = i.replace('@PRIVATE_DIR@', pdir) - elif '@PRIVATE_OUTDIR_' in i: - match = re.search(r'@PRIVATE_OUTDIR_(ABS_)?([^/\s*]*)@', i) - if not match: - msg = 'Custom target {!r} has an invalid argument {!r}' \ - ''.format(target.name, i) - raise MesonException(msg) - source = match.group(0) - if match.group(1) is None and not target.absolute_paths: - lead_dir = '' - else: - lead_dir = self.environment.get_build_dir() - i = i.replace(source, os.path.join(lead_dir, outdir)) + elif isinstance(i, str): + if '@SOURCE_ROOT@' in i: + i = i.replace('@SOURCE_ROOT@', source_root) + if '@BUILD_ROOT@' in i: + i = i.replace('@BUILD_ROOT@', build_root) + if '@CURRENT_SOURCE_DIR@' in i: + i = i.replace('@CURRENT_SOURCE_DIR@', os.path.join(source_root, target.subdir)) + if '@DEPFILE@' in i: + if target.depfile is None: + msg = f'Custom target {target.name!r} has @DEPFILE@ but no depfile ' \ + 'keyword argument.' + raise MesonException(msg) + dfilename = os.path.join(outdir, target.depfile) + i = i.replace('@DEPFILE@', dfilename) + if '@PRIVATE_DIR@' in i: + if target.absolute_paths: + pdir = self.get_target_private_dir_abs(target) + else: + pdir = self.get_target_private_dir(target) + i = i.replace('@PRIVATE_DIR@', pdir) + else: + raise RuntimeError(f'Argument {i} is of unknown type {type(i)}') cmd.append(i) # Substitute the rest of the template strings values = mesonlib.get_filenames_templates_dict(inputs, outputs) @@ -1015,51 +1476,93 @@ cmd = [i.replace('\\', '/') for i in cmd] return inputs, outputs, cmd - def run_postconf_scripts(self): + def get_run_target_env(self, target: build.RunTarget) -> build.EnvironmentVariables: + env = target.env if target.env else build.EnvironmentVariables() + introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) + env.set('MESON_SOURCE_ROOT', [self.environment.get_source_dir()]) + env.set('MESON_BUILD_ROOT', [self.environment.get_build_dir()]) + env.set('MESON_SUBDIR', [target.subdir]) + env.set('MESONINTROSPECT', [introspect_cmd]) + return env + + def run_postconf_scripts(self) -> None: + from ..scripts.meson_exe import run_exe + introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) env = {'MESON_SOURCE_ROOT': self.environment.get_source_dir(), 'MESON_BUILD_ROOT': self.environment.get_build_dir(), - 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in self.environment.get_build_command() + ['introspect']]), + 'MESONINTROSPECT': introspect_cmd, } - child_env = os.environ.copy() - child_env.update(env) for s in self.build.postconf_scripts: - cmd = s['exe'] + s['args'] - subprocess.check_call(cmd, env=child_env) + name = ' '.join(s.cmd_args) + mlog.log(f'Running postconf script {name!r}') + run_exe(s, env) - def create_install_data(self): - strip_bin = self.environment.binaries.host.lookup_entry('strip') + def create_install_data(self) -> InstallData: + strip_bin = self.environment.lookup_binary_entry(MachineChoice.HOST, 'strip') if strip_bin is None: if self.environment.is_cross_build(): mlog.warning('Cross file does not specify strip binary, result will not be stripped.') else: # TODO go through all candidates, like others - strip_bin = [self.environment.default_strip[0]] + strip_bin = [detect.defaults['strip'][0]] + + umask = self.environment.coredata.get_option(OptionKey('install_umask')) + assert isinstance(umask, (str, int)), 'for mypy' + d = InstallData(self.environment.get_source_dir(), self.environment.get_build_dir(), self.environment.get_prefix(), + self.environment.get_libdir(), strip_bin, - self.environment.coredata.get_builtin_option('install_umask'), - self.environment.get_build_command() + ['introspect']) + umask, + self.environment.get_build_command() + ['introspect'], + self.environment.coredata.version, + self.environment.is_cross_build()) self.generate_depmf_install(d) self.generate_target_install(d) self.generate_header_install(d) self.generate_man_install(d) + self.generate_emptydir_install(d) self.generate_data_install(d) + self.generate_symlink_install(d) self.generate_custom_install_script(d) self.generate_subdir_install(d) return d - def create_install_data_files(self): + def create_install_data_files(self) -> None: install_data_file = os.path.join(self.environment.get_scratch_dir(), 'install.dat') with open(install_data_file, 'wb') as ofile: pickle.dump(self.create_install_data(), ofile) - def generate_target_install(self, d): + def guess_install_tag(self, fname: str, outdir: T.Optional[str] = None) -> T.Optional[str]: + prefix = self.environment.get_prefix() + bindir = Path(prefix, self.environment.get_bindir()) + libdir = Path(prefix, self.environment.get_libdir()) + incdir = Path(prefix, self.environment.get_includedir()) + _ldir = self.environment.coredata.get_option(mesonlib.OptionKey('localedir')) + assert isinstance(_ldir, str), 'for mypy' + localedir = Path(prefix, _ldir) + dest_path = Path(prefix, outdir, Path(fname).name) if outdir else Path(prefix, fname) + if bindir in dest_path.parents: + return 'runtime' + elif libdir in dest_path.parents: + if dest_path.suffix in {'.a', '.pc'}: + return 'devel' + elif dest_path.suffix in {'.so', '.dll'}: + return 'runtime' + elif incdir in dest_path.parents: + return 'devel' + elif localedir in dest_path.parents: + return 'i18n' + mlog.debug('Failed to guess install tag for', dest_path) + return None + + def generate_target_install(self, d: InstallData) -> None: for t in self.build.get_targets().values(): if not t.should_install(): continue - outdirs, custom_install_dir = t.get_install_dir(self.environment) + outdirs, install_dir_name, custom_install_dir = t.get_install_dir(self.environment) # Sanity-check the outputs and install_dirs num_outdirs, num_out = len(outdirs), len(t.get_outputs()) if num_outdirs != 1 and num_outdirs != num_out: @@ -1067,6 +1570,7 @@ "Pass 'false' for outputs that should not be installed and 'true' for\n" \ 'using the default installation directory for an output.' raise MesonException(m.format(t.name, num_out, t.get_outputs(), num_outdirs)) + assert len(t.install_tag) == num_out install_mode = t.get_custom_install_mode() # Install the target output(s) if isinstance(t, build.BuildTarget): @@ -1083,14 +1587,18 @@ # # TODO: Create GNUStrip/AppleStrip/etc. hierarchy for more # fine-grained stripping of static archives. - should_strip = not isinstance(t, build.StaticLibrary) and self.get_option_for_target('strip', t) + should_strip = not isinstance(t, build.StaticLibrary) and self.get_option_for_target(OptionKey('strip'), t) + assert isinstance(should_strip, bool), 'for mypy' # Install primary build output (library/executable/jar, etc) # Done separately because of strip/aliases/rpath if outdirs[0] is not False: + tag = t.install_tag[0] or ('devel' if isinstance(t, build.StaticLibrary) else 'runtime') mappings = t.get_link_deps_mapping(d.prefix, self.environment) i = TargetInstallData(self.get_target_filename(t), outdirs[0], - t.get_aliases(), should_strip, mappings, - t.install_rpath, install_mode) + install_dir_name, t.get_aliases(), + should_strip, mappings, t.rpath_dirs_to_remove, + t.install_rpath, install_mode, t.subproject, + tag=tag) d.targets.append(i) if isinstance(t, (build.SharedLibrary, build.SharedModule, build.Executable)): @@ -1107,24 +1615,30 @@ implib_install_dir = self.environment.get_import_lib_dir() # Install the import library; may not exist for shared modules i = TargetInstallData(self.get_target_filename_for_linking(t), - implib_install_dir, {}, False, {}, '', install_mode, - optional=isinstance(t, build.SharedModule)) + implib_install_dir, install_dir_name, + {}, False, {}, set(), '', install_mode, + t.subproject, optional=isinstance(t, build.SharedModule), + tag='devel') d.targets.append(i) if not should_strip and t.get_debug_filename(): debug_file = os.path.join(self.get_target_dir(t), t.get_debug_filename()) i = TargetInstallData(debug_file, outdirs[0], - {}, False, {}, '', - install_mode, optional=True) + install_dir_name, + {}, False, {}, set(), '', + install_mode, t.subproject, + optional=True, tag='devel') d.targets.append(i) # Install secondary outputs. Only used for Vala right now. if num_outdirs > 1: - for output, outdir in zip(t.get_outputs()[1:], outdirs[1:]): + for output, outdir, tag in zip(t.get_outputs()[1:], outdirs[1:], t.install_tag[1:]): # User requested that we not install this output if outdir is False: continue f = os.path.join(self.get_target_dir(t), output) - i = TargetInstallData(f, outdir, {}, False, {}, None, install_mode) + i = TargetInstallData(f, outdir, install_dir_name, {}, False, {}, set(), None, + install_mode, t.subproject, + tag=tag) d.targets.append(i) elif isinstance(t, build.CustomTarget): # If only one install_dir is specified, assume that all @@ -1135,55 +1649,57 @@ # To selectively install only some outputs, pass `false` as # the install_dir for the corresponding output by index if num_outdirs == 1 and num_out > 1: - for output in t.get_outputs(): + for output, tag in zip(t.get_outputs(), t.install_tag): f = os.path.join(self.get_target_dir(t), output) - i = TargetInstallData(f, outdirs[0], {}, False, {}, None, install_mode, - optional=not t.build_by_default) + if not install_dir_name: + dir_name = os.path.join('{prefix}', outdirs[0]) + i = TargetInstallData(f, outdirs[0], dir_name, {}, + False, {}, set(), None, install_mode, + t.subproject, optional=not t.build_by_default, + tag=tag) d.targets.append(i) else: - for output, outdir in zip(t.get_outputs(), outdirs): + for output, outdir, tag in zip(t.get_outputs(), outdirs, t.install_tag): # User requested that we not install this output if outdir is False: continue f = os.path.join(self.get_target_dir(t), output) - i = TargetInstallData(f, outdir, {}, False, {}, None, install_mode, - optional=not t.build_by_default) + if not install_dir_name: + dir_name = os.path.join('{prefix}', outdir) + i = TargetInstallData(f, outdir, dir_name, + {}, False, {}, set(), None, install_mode, + t.subproject, optional=not t.build_by_default, + tag=tag) d.targets.append(i) - def generate_custom_install_script(self, d): - result = [] - srcdir = self.environment.get_source_dir() - builddir = self.environment.get_build_dir() - for i in self.build.install_scripts: - exe = i['exe'] - args = i['args'] - fixed_args = [] - for a in args: - a = a.replace('@SOURCE_ROOT@', srcdir) - a = a.replace('@BUILD_ROOT@', builddir) - fixed_args.append(a) - result.append(build.RunScript(exe, fixed_args)) - d.install_scripts = result + def generate_custom_install_script(self, d: InstallData) -> None: + d.install_scripts = self.build.install_scripts - def generate_header_install(self, d): + def generate_header_install(self, d: InstallData) -> None: incroot = self.environment.get_includedir() headers = self.build.get_headers() srcdir = self.environment.get_source_dir() builddir = self.environment.get_build_dir() for h in headers: - outdir = h.get_custom_install_dir() + outdir = outdir_name = h.get_custom_install_dir() if outdir is None: - outdir = os.path.join(incroot, h.get_install_subdir()) + subdir = h.get_install_subdir() + if subdir is None: + outdir = incroot + outdir_name = '{includedir}' + else: + outdir = os.path.join(incroot, subdir) + outdir_name = os.path.join('{includedir}', subdir) + for f in h.get_sources(): if not isinstance(f, File): - msg = 'Invalid header type {!r} can\'t be installed' - raise MesonException(msg.format(f)) + raise MesonException(f'Invalid header type {f!r} can\'t be installed') abspath = f.absolute_path(srcdir, builddir) - i = [abspath, outdir, h.get_custom_install_mode()] + i = InstallDataBase(abspath, outdir, outdir_name, h.get_custom_install_mode(), h.subproject, tag='devel') d.headers.append(i) - def generate_man_install(self, d): + def generate_man_install(self, d: InstallData) -> None: manroot = self.environment.get_mandir() man = self.build.get_man() for m in man: @@ -1191,40 +1707,73 @@ num = f.split('.')[-1] subdir = m.get_custom_install_dir() if subdir is None: - subdir = os.path.join(manroot, 'man' + num) + if m.locale: + subdir = os.path.join('{mandir}', m.locale, 'man' + num) + else: + subdir = os.path.join('{mandir}', 'man' + num) + fname = f.fname + if m.locale: # strip locale from file name + fname = fname.replace(f'.{m.locale}', '') srcabs = f.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) - dstabs = os.path.join(subdir, os.path.basename(f.fname)) - i = [srcabs, dstabs, m.get_custom_install_mode()] + dstname = os.path.join(subdir, os.path.basename(fname)) + dstabs = dstname.replace('{mandir}', manroot) + i = InstallDataBase(srcabs, dstabs, dstname, m.get_custom_install_mode(), m.subproject, tag='man') d.man.append(i) - def generate_data_install(self, d): + def generate_emptydir_install(self, d: InstallData) -> None: + emptydir: T.List[build.EmptyDir] = self.build.get_emptydir() + for e in emptydir: + i = InstallEmptyDir(e.path, e.install_mode, e.subproject, e.install_tag) + d.emptydir.append(i) + + def generate_data_install(self, d: InstallData) -> None: data = self.build.get_data() srcdir = self.environment.get_source_dir() builddir = self.environment.get_build_dir() for de in data: - assert(isinstance(de, build.Data)) + assert isinstance(de, build.Data) subdir = de.install_dir + subdir_name = de.install_dir_name if not subdir: subdir = os.path.join(self.environment.get_datadir(), self.interpreter.build.project_name) + subdir_name = os.path.join('{datadir}', self.interpreter.build.project_name) for src_file, dst_name in zip(de.sources, de.rename): - assert(isinstance(src_file, mesonlib.File)) + assert isinstance(src_file, mesonlib.File) dst_abs = os.path.join(subdir, dst_name) - i = [src_file.absolute_path(srcdir, builddir), dst_abs, de.install_mode] + dstdir_name = os.path.join(subdir_name, dst_name) + tag = de.install_tag or self.guess_install_tag(dst_abs) + i = InstallDataBase(src_file.absolute_path(srcdir, builddir), dst_abs, dstdir_name, + de.install_mode, de.subproject, tag=tag, data_type=de.data_type) d.data.append(i) - def generate_subdir_install(self, d): + def generate_symlink_install(self, d: InstallData) -> None: + links: T.List[build.SymlinkData] = self.build.get_symlinks() + for l in links: + assert isinstance(l, build.SymlinkData) + install_dir = l.install_dir + name_abs = os.path.join(install_dir, l.name) + s = InstallSymlinkData(l.target, name_abs, install_dir, l.subproject, l.install_tag) + d.symlinks.append(s) + + def generate_subdir_install(self, d: InstallData) -> None: for sd in self.build.get_install_subdirs(): - src_dir = os.path.join(self.environment.get_source_dir(), + if sd.from_source_dir: + from_dir = self.environment.get_source_dir() + else: + from_dir = self.environment.get_build_dir() + src_dir = os.path.join(from_dir, sd.source_subdir, sd.installable_subdir).rstrip('/') dst_dir = os.path.join(self.environment.get_prefix(), sd.install_dir) + dst_name = os.path.join('{prefix}', sd.install_dir) if not sd.strip_directory: dst_dir = os.path.join(dst_dir, os.path.basename(src_dir)) - d.install_subdirs.append([src_dir, dst_dir, sd.install_mode, - sd.exclude]) + dst_name = os.path.join(dst_dir, os.path.basename(src_dir)) + i = SubdirInstallData(src_dir, dst_dir, dst_name, sd.install_mode, sd.exclude, sd.subproject, sd.install_tag) + d.install_subdirs.append(i) - def get_introspection_data(self, target_id, target): + def get_introspection_data(self, target_id: str, target: build.Target) -> T.List['TargetIntrospectionData']: ''' Returns a list of source dicts with the following format for a given target: [ @@ -1240,20 +1789,20 @@ This is a limited fallback / reference implementation. The backend should override this method. ''' if isinstance(target, (build.CustomTarget, build.BuildTarget)): - source_list_raw = target.sources + target.extra_files + source_list_raw = target.sources source_list = [] for j in source_list_raw: if isinstance(j, mesonlib.File): source_list += [j.absolute_path(self.source_dir, self.build_dir)] elif isinstance(j, str): source_list += [os.path.join(self.source_dir, j)] + elif isinstance(j, (build.CustomTarget, build.BuildTarget)): + source_list += [os.path.join(self.build_dir, j.get_subdir(), o) for o in j.get_outputs()] source_list = list(map(lambda x: os.path.normpath(x), source_list)) - compiler = [] + compiler: T.List[str] = [] if isinstance(target, build.CustomTarget): tmp_compiler = target.command - if not isinstance(compiler, list): - tmp_compiler = [compiler] for j in tmp_compiler: if isinstance(j, mesonlib.File): compiler += [j.absolute_path(self.source_dir, self.build_dir)] @@ -1262,7 +1811,7 @@ elif isinstance(j, (build.BuildTarget, build.CustomTarget)): compiler += j.get_outputs() else: - raise RuntimeError('Type "{}" is not supported in get_introspection_data. This is a bug'.format(type(j).__name__)) + raise RuntimeError(f'Type "{type(j).__name__}" is not supported in get_introspection_data. This is a bug') return [{ 'language': 'unknown', @@ -1273,3 +1822,37 @@ }] return [] + + def get_devenv(self) -> build.EnvironmentVariables: + env = build.EnvironmentVariables() + extra_paths = set() + library_paths = set() + for t in self.build.get_targets().values(): + cross_built = not self.environment.machines.matches_build_machine(t.for_machine) + can_run = not cross_built or not self.environment.need_exe_wrapper() + in_default_dir = t.should_install() and not t.get_install_dir(self.environment)[2] + if not can_run or not in_default_dir: + continue + tdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(t)) + if isinstance(t, build.Executable): + # Add binaries that are going to be installed in bindir into PATH + # so they get used by default instead of searching on system when + # in developer environment. + extra_paths.add(tdir) + if mesonlib.is_windows() or mesonlib.is_cygwin(): + # On windows we cannot rely on rpath to run executables from build + # directory. We have to add in PATH the location of every DLL needed. + extra_paths.update(self.determine_windows_extra_paths(t, [])) + elif isinstance(t, build.SharedLibrary): + # Add libraries that are going to be installed in libdir into + # LD_LIBRARY_PATH. This allows running system applications using + # that library. + library_paths.add(tdir) + if mesonlib.is_windows() or mesonlib.is_cygwin(): + extra_paths.update(library_paths) + elif mesonlib.is_osx(): + env.prepend('DYLD_LIBRARY_PATH', list(library_paths)) + else: + env.prepend('LD_LIBRARY_PATH', list(library_paths)) + env.prepend('PATH', list(extra_paths)) + return env diff -Nru meson-0.53.2/mesonbuild/backend/ninjabackend.py meson-0.61.2/mesonbuild/backend/ninjabackend.py --- meson-0.53.2/mesonbuild/backend/ninjabackend.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/ninjabackend.py 2022-02-14 19:03:13.000000000 +0000 @@ -11,65 +11,161 @@ # 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 typing as T + +from collections import OrderedDict +from enum import Enum, unique +from functools import lru_cache +from pathlib import PurePath, Path +from textwrap import dedent +import itertools +import json import os -import re import pickle +import re +import shlex import subprocess -from collections import OrderedDict -import itertools -from pathlib import PurePath, Path -from functools import lru_cache +import typing as T from . import backends from .. import modules from .. import environment, mesonlib from .. import build from .. import mlog -from .. import dependencies from .. import compilers -from ..compilers import (Compiler, CompilerArgs, CCompiler, FortranCompiler, - PGICCompiler, VisualStudioLikeCompiler) -from ..linkers import ArLinker +from ..arglist import CompilerArgs +from ..compilers import ( + Compiler, CCompiler, + FortranCompiler, + mixins, + PGICCompiler, + VisualStudioLikeCompiler, +) +from ..linkers import ArLinker, RSPFileSyntax from ..mesonlib import ( - File, LibType, MachineChoice, MesonException, OrderedSet, PerMachine, ProgressBar, quote_arg + File, LibType, MachineChoice, MesonException, OrderedSet, PerMachine, + ProgressBar, quote_arg ) -from ..mesonlib import get_compiler_for_source, has_path_sep +from ..mesonlib import get_compiler_for_source, has_path_sep, OptionKey from .backends import CleanTrees -from ..build import InvalidArguments +from ..build import GeneratedList, InvalidArguments, ExtractedObjects +from ..interpreter import Interpreter + +if T.TYPE_CHECKING: + from .._typing import ImmutableListProtocol + from ..linkers import DynamicLinker, StaticLinker + from ..compilers.cs import CsCompiler + FORTRAN_INCLUDE_PAT = r"^\s*#?include\s*['\"](\w+\.\w+)['\"]" FORTRAN_MODULE_PAT = r"^\s*\bmodule\b\s+(\w+)\s*(?:!+.*)*$" FORTRAN_SUBMOD_PAT = r"^\s*\bsubmodule\b\s*\((\w+:?\w+)\)\s*(\w+)" FORTRAN_USE_PAT = r"^\s*use,?\s*(?:non_intrinsic)?\s*(?:::)?\s*(\w+)" +def cmd_quote(s): + # see: https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw#remarks + + # backslash escape any existing double quotes + # any existing backslashes preceding a quote are doubled + s = re.sub(r'(\\*)"', lambda m: '\\' * (len(m.group(1)) * 2 + 1) + '"', s) + # any terminal backslashes likewise need doubling + s = re.sub(r'(\\*)$', lambda m: '\\' * (len(m.group(1)) * 2), s) + # and double quote + s = f'"{s}"' + + return s + +def gcc_rsp_quote(s): + # see: the function buildargv() in libiberty + # + # this differs from sh-quoting in that a backslash *always* escapes the + # following character, even inside single quotes. + + s = s.replace('\\', '\\\\') + + return shlex.quote(s) + +# How ninja executes command lines differs between Unix and Windows +# (see https://ninja-build.org/manual.html#ref_rule_command) if mesonlib.is_windows(): - # FIXME: can't use quote_arg on Windows just yet; there are a number of existing workarounds - # throughout the codebase that cumulatively make the current code work (see, e.g. Backend.escape_extra_args - # and NinjaBuildElement.write below) and need to be properly untangled before attempting this - quote_func = lambda s: '"{}"'.format(s) - execute_wrapper = ['cmd', '/c'] + quote_func = cmd_quote + execute_wrapper = ['cmd', '/c'] # unused rmfile_prefix = ['del', '/f', '/s', '/q', '{}', '&&'] else: quote_func = quote_arg execute_wrapper = [] rmfile_prefix = ['rm', '-f', '{}', '&&'] -def ninja_quote(text, is_build_line=False): + +def get_rsp_threshold(): + '''Return a conservative estimate of the commandline size in bytes + above which a response file should be used. May be overridden for + debugging by setting environment variable MESON_RSP_THRESHOLD.''' + + if mesonlib.is_windows(): + # Usually 32k, but some projects might use cmd.exe, + # and that has a limit of 8k. + limit = 8192 + else: + # On Linux, ninja always passes the commandline as a single + # big string to /bin/sh, and the kernel limits the size of a + # single argument; see MAX_ARG_STRLEN + limit = 131072 + # Be conservative + limit = limit / 2 + return int(os.environ.get('MESON_RSP_THRESHOLD', limit)) + +# a conservative estimate of the command-line length limit +rsp_threshold = get_rsp_threshold() + +# ninja variables whose value should remain unquoted. The value of these ninja +# variables (or variables we use them in) is interpreted directly by ninja +# (e.g. the value of the depfile variable is a pathname that ninja will read +# from, etc.), so it must not be shell quoted. +raw_names = {'DEPFILE_UNQUOTED', 'DESC', 'pool', 'description', 'targetdep', 'dyndep'} + +NINJA_QUOTE_BUILD_PAT = re.compile(r"[$ :\n]") +NINJA_QUOTE_VAR_PAT = re.compile(r"[$ \n]") + +def ninja_quote(text: str, is_build_line=False) -> str: if is_build_line: - qcs = ('$', ' ', ':') + quote_re = NINJA_QUOTE_BUILD_PAT else: - qcs = ('$', ' ') - for char in qcs: - text = text.replace(char, '$' + char) + quote_re = NINJA_QUOTE_VAR_PAT + # Fast path for when no quoting is necessary + if not quote_re.search(text): + return text if '\n' in text: - errmsg = '''Ninja does not support newlines in rules. The content was: + errmsg = f'''Ninja does not support newlines in rules. The content was: -%s +{text} -Please report this error with a test case to the Meson bug tracker.''' % text +Please report this error with a test case to the Meson bug tracker.''' raise MesonException(errmsg) - return text + return quote_re.sub(r'$\g<0>', text) + +class TargetDependencyScannerInfo: + def __init__(self, private_dir: str, source2object: T.Dict[str, str]): + self.private_dir = private_dir + self.source2object = source2object + +@unique +class Quoting(Enum): + both = 0 + notShell = 1 + notNinja = 2 + none = 3 + +class NinjaCommandArg: + def __init__(self, s, quoting = Quoting.both): + self.s = s + self.quoting = quoting + + def __str__(self): + return self.s + + @staticmethod + def list(l, q): + return [NinjaCommandArg(i, q) for i in l] class NinjaComment: def __init__(self, comment): @@ -84,48 +180,129 @@ class NinjaRule: def __init__(self, rule, command, args, description, - rspable = False, deps = None, depfile = None, extra = None): + rspable = False, deps = None, depfile = None, extra = None, + rspfile_quote_style: RSPFileSyntax = RSPFileSyntax.GCC): + + def strToCommandArg(c): + if isinstance(c, NinjaCommandArg): + return c + + # deal with common cases here, so we don't have to explicitly + # annotate the required quoting everywhere + if c == '&&': + # shell constructs shouldn't be shell quoted + return NinjaCommandArg(c, Quoting.notShell) + if c.startswith('$'): + var = re.search(r'\$\{?(\w*)\}?', c).group(1) + if var not in raw_names: + # ninja variables shouldn't be ninja quoted, and their value + # is already shell quoted + return NinjaCommandArg(c, Quoting.none) + else: + # shell quote the use of ninja variables whose value must + # not be shell quoted (as it also used by ninja) + return NinjaCommandArg(c, Quoting.notNinja) + + return NinjaCommandArg(c) + self.name = rule - self.command = command # includes args which never go into a rspfile - self.args = args # args which will go into a rspfile, if used + self.command = list(map(strToCommandArg, command)) # includes args which never go into a rspfile + self.args = list(map(strToCommandArg, args)) # args which will go into a rspfile, if used self.description = description self.deps = deps # depstyle 'gcc' or 'msvc' self.depfile = depfile self.extra = extra self.rspable = rspable # if a rspfile can be used self.refcount = 0 + self.rsprefcount = 0 + self.rspfile_quote_style = rspfile_quote_style + + if self.depfile == '$DEPFILE': + self.depfile += '_UNQUOTED' + + @staticmethod + def _quoter(x, qf = quote_func): + if isinstance(x, NinjaCommandArg): + if x.quoting == Quoting.none: + return x.s + elif x.quoting == Quoting.notNinja: + return qf(x.s) + elif x.quoting == Quoting.notShell: + return ninja_quote(x.s) + # fallthrough + return ninja_quote(qf(str(x))) def write(self, outfile): - if not self.refcount: - return + if self.rspfile_quote_style is RSPFileSyntax.MSVC: + rspfile_quote_func = cmd_quote + else: + rspfile_quote_func = gcc_rsp_quote - outfile.write('rule %s\n' % self.name) - if self.rspable: - outfile.write(' command = %s @$out.rsp\n' % ' '.join(self.command)) - outfile.write(' rspfile = $out.rsp\n') - outfile.write(' rspfile_content = %s\n' % ' '.join(self.args)) - else: - outfile.write(' command = %s\n' % ' '.join(self.command + self.args)) - if self.deps: - outfile.write(' deps = %s\n' % self.deps) - if self.depfile: - outfile.write(' depfile = %s\n' % self.depfile) - outfile.write(' description = %s\n' % self.description) - if self.extra: - for l in self.extra.split('\n'): - outfile.write(' ') - outfile.write(l) - outfile.write('\n') - outfile.write('\n') + def rule_iter(): + if self.refcount: + yield '' + if self.rsprefcount: + yield '_RSP' + + for rsp in rule_iter(): + outfile.write(f'rule {self.name}{rsp}\n') + if rsp == '_RSP': + outfile.write(' command = {} @$out.rsp\n'.format(' '.join([self._quoter(x) for x in self.command]))) + outfile.write(' rspfile = $out.rsp\n') + outfile.write(' rspfile_content = {}\n'.format(' '.join([self._quoter(x, rspfile_quote_func) for x in self.args]))) + else: + outfile.write(' command = {}\n'.format(' '.join([self._quoter(x) for x in self.command + self.args]))) + if self.deps: + outfile.write(f' deps = {self.deps}\n') + if self.depfile: + outfile.write(f' depfile = {self.depfile}\n') + outfile.write(f' description = {self.description}\n') + if self.extra: + for l in self.extra.split('\n'): + outfile.write(' ') + outfile.write(l) + outfile.write('\n') + outfile.write('\n') + + def length_estimate(self, infiles, outfiles, elems): + # determine variables + # this order of actions only approximates ninja's scoping rules, as + # documented at: https://ninja-build.org/manual.html#ref_scope + ninja_vars = {} + for e in elems: + (name, value) = e + ninja_vars[name] = value + ninja_vars['deps'] = self.deps + ninja_vars['depfile'] = self.depfile + ninja_vars['in'] = infiles + ninja_vars['out'] = outfiles + + # expand variables in command + command = ' '.join([self._quoter(x) for x in self.command + self.args]) + estimate = len(command) + for m in re.finditer(r'(\${\w+}|\$\w+)?[^$]*', command): + if m.start(1) != -1: + estimate -= m.end(1) - m.start(1) + 1 + chunk = m.group(1) + if chunk[1] == '{': + chunk = chunk[2:-1] + else: + chunk = chunk[1:] + chunk = ninja_vars.get(chunk, []) # undefined ninja variables are empty + estimate += len(' '.join(chunk)) + + # determine command length + return estimate class NinjaBuildElement: - def __init__(self, all_outputs, outfilenames, rule, infilenames): + def __init__(self, all_outputs, outfilenames, rulename, infilenames, implicit_outs=None): + self.implicit_outfilenames = implicit_outs or [] if isinstance(outfilenames, str): self.outfilenames = [outfilenames] else: self.outfilenames = outfilenames - assert(isinstance(rule, str)) - self.rule = rule + assert isinstance(rulename, str) + self.rulename = rulename if isinstance(infilenames, str): self.infilenames = [infilenames] else: @@ -148,19 +325,57 @@ self.orderdeps.add(dep) def add_item(self, name, elems): + # Always convert from GCC-style argument naming to the naming used by the + # current compiler. Also filter system include paths, deduplicate, etc. + if isinstance(elems, CompilerArgs): + elems = elems.to_native() if isinstance(elems, str): elems = [elems] self.elems.append((name, elems)) + if name == 'DEPFILE': + self.elems.append((name + '_UNQUOTED', elems)) + + def _should_use_rspfile(self): + # 'phony' is a rule built-in to ninja + if self.rulename == 'phony': + return False + + if not self.rule.rspable: + return False + + infilenames = ' '.join([ninja_quote(i, True) for i in self.infilenames]) + outfilenames = ' '.join([ninja_quote(i, True) for i in self.outfilenames]) + + return self.rule.length_estimate(infilenames, + outfilenames, + self.elems) >= rsp_threshold + + def count_rule_references(self): + if self.rulename != 'phony': + if self._should_use_rspfile(): + self.rule.rsprefcount += 1 + else: + self.rule.refcount += 1 + def write(self, outfile): self.check_outputs() - line = 'build %s: %s %s' % (' '.join([ninja_quote(i, True) for i in self.outfilenames]), - self.rule, - ' '.join([ninja_quote(i, True) for i in self.infilenames])) + ins = ' '.join([ninja_quote(i, True) for i in self.infilenames]) + outs = ' '.join([ninja_quote(i, True) for i in self.outfilenames]) + implicit_outs = ' '.join([ninja_quote(i, True) for i in self.implicit_outfilenames]) + if implicit_outs: + implicit_outs = ' | ' + implicit_outs + use_rspfile = self._should_use_rspfile() + if use_rspfile: + rulename = self.rulename + '_RSP' + mlog.debug(f'Command line for building {self.outfilenames} is long, using a response file') + else: + rulename = self.rulename + line = f'build {outs}{implicit_outs}: {rulename} {ins}' if len(self.deps) > 0: - line += ' | ' + ' '.join([ninja_quote(x, True) for x in self.deps]) + line += ' | ' + ' '.join([ninja_quote(x, True) for x in sorted(self.deps)]) if len(self.orderdeps) > 0: - line += ' || ' + ' '.join([ninja_quote(x, True) for x in self.orderdeps]) + line += ' || ' + ' '.join([ninja_quote(x, True) for x in sorted(self.orderdeps)]) line += '\n' # This is the only way I could find to make this work on all # platforms including Windows command shell. Slash is a dir separator @@ -168,28 +383,33 @@ # do not require quoting, unless explicitly specified, which is necessary for # the csc compiler. line = line.replace('\\', '/') + if mesonlib.is_windows(): + # Support network paths as backslash, otherwise they are interpreted as + # arguments for compile/link commands when using MSVC + line = ' '.join( + (l.replace('//', '\\\\', 1) if l.startswith('//') else l) + for l in line.split(' ') + ) outfile.write(line) - # ninja variables whose value should remain unquoted. The value of these - # ninja variables (or variables we use them in) is interpreted directly - # by ninja (e.g. the value of the depfile variable is a pathname that - # ninja will read from, etc.), so it must not be shell quoted. - raw_names = {'DEPFILE', 'DESC', 'pool', 'description', 'targetdep'} + if use_rspfile: + if self.rule.rspfile_quote_style is RSPFileSyntax.MSVC: + qf = cmd_quote + else: + qf = gcc_rsp_quote + else: + qf = quote_func for e in self.elems: (name, elems) = e should_quote = name not in raw_names - line = ' %s = ' % name + line = f' {name} = ' newelems = [] for i in elems: if not should_quote or i == '&&': # Hackety hack hack - quoter = ninja_quote + newelems.append(ninja_quote(i)) else: - quoter = lambda x: ninja_quote(quote_func(x)) - i = i.replace('\\', '\\\\') - if quote_func('') == '""': - i = i.replace('"', '\\"') - newelems.append(quoter(i)) + newelems.append(ninja_quote(qf(i))) line += ' '.join(newelems) line += '\n' outfile.write(line) @@ -198,13 +418,13 @@ def check_outputs(self): for n in self.outfilenames: if n in self.all_outputs: - raise MesonException('Multiple producers for Ninja target "%s". Please rename your targets.' % n) + raise MesonException(f'Multiple producers for Ninja target "{n}". Please rename your targets.') self.all_outputs[n] = True class NinjaBackend(backends.Backend): - def __init__(self, build): - super().__init__(build) + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) self.name = 'ninja' self.ninja_filename = 'build.ninja' self.fortran_deps = {} @@ -219,8 +439,7 @@ # 'benchmark', etc, and also for RunTargets. # https://github.com/mesonbuild/meson/issues/1644 if not to_target.startswith('meson-'): - m = 'Invalid usage of create_target_alias with {!r}' - raise AssertionError(m.format(to_target)) + raise AssertionError(f'Invalid usage of create_target_alias with {to_target!r}') from_target = to_target[len('meson-'):] elem = NinjaBuildElement(self.all_outputs, from_target, 'phony', to_target) self.add_build(elem) @@ -245,10 +464,11 @@ return open(tempfilename, 'a', encoding='utf-8') filename = os.path.join(self.environment.get_scratch_dir(), 'incdetect.c') - with open(filename, 'w') as f: - f.write('''#include -int dummy; -''') + with open(filename, 'w', encoding='utf-8') as f: + f.write(dedent('''\ + #include + int dummy; + ''')) # The output of cl dependency information is language # and locale dependent. Any attempt at converting it to @@ -264,7 +484,14 @@ # 'Note: including file: d:\MyDir\include\stdio.h', however # different locales have different messages with a different # number of colons. Match up to the the drive name 'd:\'. - matchre = re.compile(rb"^(.*\s)[a-zA-Z]:\\.*stdio.h$") + # When used in cross compilation, the path separator is a + # forward slash rather than a backslash so handle both; i.e. + # the path is /MyDir/include/stdio.h. + # With certain cross compilation wrappings of MSVC, the paths + # use backslashes, but without the leading drive name, so + # allow the path to start with any path separator, i.e. + # \MyDir\include\stdio.h. + matchre = re.compile(rb"^(.*\s)([a-zA-Z]:\\|[\\\/]).*stdio.h$") def detect_prefix(out): for line in re.split(rb'\r?\n', out): @@ -283,27 +510,38 @@ raise MesonException('Could not determine vs dep dependency prefix string.') - def generate(self, interp): - self.interpreter = interp + def generate(self): ninja = environment.detect_ninja_command_and_version(log=True) + if self.build.need_vsenv: + builddir = Path(self.environment.get_build_dir()) + try: + # For prettier printing, reduce to a relative path. If + # impossible (e.g., because builddir and cwd are on + # different Windows drives), skip and use the full path. + builddir = builddir.relative_to(Path.cwd()) + except ValueError: + pass + meson_command = mesonlib.join_args(mesonlib.get_meson_command()) + mlog.log() + mlog.log('Visual Studio environment is needed to run Ninja. It is recommended to use Meson wrapper:') + mlog.log(f'{meson_command} compile -C {builddir}') if ninja is None: - raise MesonException('Could not detect Ninja v1.5 or newer') + raise MesonException('Could not detect Ninja v1.8.2 or newer') (self.ninja_command, self.ninja_version) = ninja outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename) tempfilename = outfilename + '~' with open(tempfilename, 'w', encoding='utf-8') as outfile: - outfile.write('# This is the build file for project "%s"\n' % - self.build.get_project()) + outfile.write(f'# This is the build file for project "{self.build.get_project()}"\n') outfile.write('# It is autogenerated by the Meson build system.\n') outfile.write('# Do not edit by hand.\n\n') - outfile.write('ninja_required_version = 1.5.1\n\n') + outfile.write('ninja_required_version = 1.8.2\n\n') - num_pools = self.environment.coredata.backend_options['backend_max_links'].value + num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value if num_pools > 0: - outfile.write('''pool link_pool - depth = %d + outfile.write(f'''pool link_pool + depth = {num_pools} -''' % num_pools) +''') with self.detect_vs_dep_prefix(tempfilename) as outfile: self.generate_rules() @@ -318,10 +556,17 @@ self.add_build_comment(NinjaComment('Install rules')) self.generate_install() self.generate_dist() - if 'b_coverage' in self.environment.coredata.base_options and \ - self.environment.coredata.base_options['b_coverage'].value: - self.add_build_comment(NinjaComment('Coverage rules')) - self.generate_coverage_rules() + key = OptionKey('b_coverage') + if (key in self.environment.coredata.options and + self.environment.coredata.options[key].value): + gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, _ = environment.find_coverage_tools() + if gcovr_exe or (lcov_exe and genhtml_exe): + self.add_build_comment(NinjaComment('Coverage rules')) + self.generate_coverage_rules(gcovr_exe, gcovr_version) + else: + # FIXME: since we explicitly opted in, should this be an error? + # The docs just say these targets will be created "if possible". + mlog.warning('Need gcovr or lcov/genhtml to generate any coverage reports') self.add_build_comment(NinjaComment('Suffix')) self.generate_utils() self.generate_ending() @@ -335,17 +580,25 @@ # fully created. os.replace(tempfilename, outfilename) mlog.cmd_ci_include(outfilename) # For CI debugging + # Refresh Ninja's caches. https://github.com/ninja-build/ninja/pull/1685 + if mesonlib.version_compare(self.ninja_version, '>=1.10.0') and os.path.exists('.ninja_deps'): + subprocess.call(self.ninja_command + ['-t', 'restat']) + subprocess.call(self.ninja_command + ['-t', 'cleandead']) self.generate_compdb() # http://clang.llvm.org/docs/JSONCompilationDatabase.html def generate_compdb(self): rules = [] + # TODO: Rather than an explicit list here, rules could be marked in the + # rule store as being wanted in compdb for for_machine in MachineChoice: for lang in self.environment.coredata.compilers[for_machine]: - rules += [self.get_compiler_rule_name(lang, for_machine)] - rules += [self.get_pch_rule_name(lang, for_machine)] + rules += [f"{rule}{ext}" for rule in [self.get_compiler_rule_name(lang, for_machine)] + for ext in ['', '_RSP']] + rules += [f"{rule}{ext}" for rule in [self.get_pch_rule_name(lang, for_machine)] + for ext in ['', '_RSP']] compdb_options = ['-x'] if mesonlib.version_compare(self.ninja_version, '>=1.9') else [] - ninja_compdb = [self.ninja_command, '-t', 'compdb'] + compdb_options + rules + ninja_compdb = self.ninja_command + ['-t', 'compdb'] + compdb_options + rules builddir = self.environment.get_build_dir() try: jsondb = subprocess.check_output(ninja_compdb, cwd=builddir) @@ -377,44 +630,39 @@ target.cached_generated_headers = header_deps return header_deps - def get_target_generated_sources(self, target): + def get_target_generated_sources(self, target: build.BuildTarget) -> T.MutableMapping[str, File]: """ Returns a dictionary with the keys being the path to the file (relative to the build directory) of that type and the value being the GeneratorList or CustomTarget that generated it. """ - srcs = OrderedDict() + srcs: T.MutableMapping[str, File] = OrderedDict() for gensrc in target.get_generated_sources(): for s in gensrc.get_outputs(): f = self.get_target_generated_dir(target, gensrc, s) srcs[f] = s return srcs - def get_target_sources(self, target): - srcs = OrderedDict() + def get_target_sources(self, target: build.BuildTarget) -> T.MutableMapping[str, File]: + srcs: T.MutableMapping[str, File] = OrderedDict() for s in target.get_sources(): # BuildTarget sources are always mesonlib.File files which are # either in the source root, or generated with configure_file and # in the build root if not isinstance(s, File): - raise InvalidArguments('All sources in target {!r} must be of type mesonlib.File'.format(s)) + raise InvalidArguments(f'All sources in target {s!r} must be of type mesonlib.File') f = s.rel_to_builddir(self.build_to_src) srcs[f] = s return srcs - # Languages that can mix with C or C++ but don't support unity builds yet - # because the syntax we use for unity builds is specific to C/++/ObjC/++. - # Assembly files cannot be unitified and neither can LLVM IR files - langs_cant_unity = ('d', 'fortran') - def get_target_source_can_unity(self, target, source): if isinstance(source, File): source = source.fname if self.environment.is_llvm_ir(source) or \ self.environment.is_assembly(source): return False - suffix = os.path.splitext(source)[1][1:] - for lang in self.langs_cant_unity: + suffix = os.path.splitext(source)[1][1:].lower() + for lang in backends.LANGS_CANT_UNITY: if lang not in target.compilers: continue if suffix in target.compilers[lang].file_suffixes: @@ -467,32 +715,35 @@ src_block['sources'] += sources src_block['generated_sources'] += generated_sources - def is_rust_target(self, target): - if len(target.sources) > 0: - first_file = target.sources[0] - if first_file.fname.endswith('.rs'): - return True - return False - def generate_target(self, target): + try: + if isinstance(target, build.BuildTarget): + os.makedirs(self.get_target_private_dir_abs(target)) + except FileExistsError: + pass if isinstance(target, build.CustomTarget): self.generate_custom_target(target) if isinstance(target, build.RunTarget): self.generate_run_target(target) + compiled_sources = [] + source2object = {} name = target.get_id() if name in self.processed_targets: return - self.processed_targets[name] = True + self.processed_targets.add(name) # Initialize an empty introspection source list self.introspection_data[name] = {} # Generate rules for all dependency targets self.process_target_dependencies(target) + + self.generate_shlib_aliases(target, self.get_target_dir(target)) + # If target uses a language that cannot link to C objects, # just generate for that language and return. if isinstance(target, build.Jar): self.generate_jar_target(target) return - if self.is_rust_target(target): + if target.uses_rust(): self.generate_rust_target(target) return if 'cs' in target.compilers: @@ -502,26 +753,30 @@ self.generate_swift_target(target) return - # Now we handle the following languages: - # ObjC++, ObjC, C++, C, D, Fortran, Vala + # Pre-existing target C/C++ sources to be built; dict of full path to + # source relative to build root and the original File object. + target_sources: T.MutableMapping[str, File] + + # GeneratedList and CustomTarget sources to be built; dict of the full + # path to source relative to build root and the generating target/list + generated_sources: T.MutableMapping[str, File] + + # List of sources that have been transpiled from a DSL (like Vala) into + # a language that is haneled below, such as C or C++ + transpiled_sources: T.List[str] - # target_sources: - # Pre-existing target C/C++ sources to be built; dict of full path to - # source relative to build root and the original File object. - # generated_sources: - # GeneratedList and CustomTarget sources to be built; dict of the full - # path to source relative to build root and the generating target/list - # vala_generated_sources: - # Array of sources generated by valac that have to be compiled if 'vala' in target.compilers: # Sources consumed by valac are filtered out. These only contain # C/C++ sources, objects, generated libs, and unknown sources now. target_sources, generated_sources, \ - vala_generated_sources = self.generate_vala_compile(target) + transpiled_sources = self.generate_vala_compile(target) + elif 'cython' in target.compilers: + target_sources, generated_sources, \ + transpiled_sources = self.generate_cython_transpile(target) else: target_sources = self.get_target_sources(target) generated_sources = self.get_target_generated_sources(target) - vala_generated_sources = [] + transpiled_sources = [] self.scan_fortran_module_outputs(target) # Generate rules for GeneratedLists self.generate_generator_list_rules(target) @@ -538,13 +793,12 @@ if is_unity: # Warn about incompatible sources if a unity build is enabled langs = set(target.compilers.keys()) - langs_cant = langs.intersection(self.langs_cant_unity) + langs_cant = langs.intersection(backends.LANGS_CANT_UNITY) if langs_cant: langs_are = langs = ', '.join(langs_cant).upper() langs_are += ' are' if len(langs_cant) > 1 else ' is' - msg = '{} not supported in Unity builds yet, so {} ' \ - 'sources in the {!r} target will be compiled normally' \ - ''.format(langs_are, langs, target.name) + msg = f'{langs_are} not supported in Unity builds yet, so {langs} ' \ + f'sources in the {target.name!r} target will be compiled normally' mlog.log(mlog.red('FIXME'), msg) # Get a list of all generated headers that will be needed while building @@ -564,7 +818,7 @@ generated_source_files.append(raw_src) elif self.environment.is_object(rel_src): obj_list.append(rel_src) - elif self.environment.is_library(rel_src): + elif self.environment.is_library(rel_src) or modules.is_module_library(rel_src): pass else: # Assume anything not specifically a source file is a header. This is because @@ -576,13 +830,15 @@ # because we need `header_deps` to be fully generated in the above loop. for src in generated_source_files: if self.environment.is_llvm_ir(src): - o = self.generate_llvm_ir_compile(target, src) + o, s = self.generate_llvm_ir_compile(target, src) else: - o = self.generate_single_compile(target, src, True, - header_deps=header_deps) + o, s = self.generate_single_compile(target, src, True, + order_deps=header_deps) + compiled_sources.append(s) + source2object[s] = o obj_list.append(o) - use_pch = self.environment.coredata.base_options.get('b_pch', False) + use_pch = self.environment.coredata.options.get(OptionKey('b_pch')) if use_pch and target.has_pch(): pch_objects = self.generate_pch(target, header_deps=header_deps) else: @@ -591,51 +847,122 @@ # Generate compilation targets for C sources generated from Vala # sources. This can be extended to other $LANG->C compilers later if # necessary. This needs to be separate for at least Vala + # + # Do not try to unity-build the generated c files from vala, as these + # often contain duplicate symbols and will fail to compile properly vala_generated_source_files = [] - for src in vala_generated_sources: + for src in transpiled_sources: dirpart, fnamepart = os.path.split(src) raw_src = File(True, dirpart, fnamepart) - if is_unity: - unity_src.append(os.path.join(self.environment.get_build_dir(), src)) + # Generated targets are ordered deps because the must exist + # before the sources compiling them are used. After the first + # compile we get precise dependency info from dep files. + # This should work in all cases. If it does not, then just + # move them from orderdeps to proper deps. + if self.environment.is_header(src): header_deps.append(raw_src) else: - # Generated targets are ordered deps because the must exist - # before the sources compiling them are used. After the first - # compile we get precise dependency info from dep files. - # This should work in all cases. If it does not, then just - # move them from orderdeps to proper deps. - if self.environment.is_header(src): - header_deps.append(raw_src) - else: - # We gather all these and generate compile rules below - # after `header_deps` (above) is fully generated - vala_generated_source_files.append(raw_src) + # We gather all these and generate compile rules below + # after `header_deps` (above) is fully generated + vala_generated_source_files.append(raw_src) for src in vala_generated_source_files: # Passing 'vala' here signifies that we want the compile # arguments to be specialized for C code generated by # valac. For instance, no warnings should be emitted. - obj_list.append(self.generate_single_compile(target, src, 'vala', [], header_deps)) + o, s = self.generate_single_compile(target, src, 'vala', [], header_deps) + obj_list.append(o) # Generate compile targets for all the pre-existing sources for this target for src in target_sources.values(): if not self.environment.is_header(src): if self.environment.is_llvm_ir(src): - obj_list.append(self.generate_llvm_ir_compile(target, src)) + o, s = self.generate_llvm_ir_compile(target, src) + obj_list.append(o) elif is_unity and self.get_target_source_can_unity(target, src): abs_src = os.path.join(self.environment.get_build_dir(), src.rel_to_builddir(self.build_to_src)) unity_src.append(abs_src) else: - obj_list.append(self.generate_single_compile(target, src, False, [], header_deps)) + o, s = self.generate_single_compile(target, src, False, [], header_deps) + obj_list.append(o) + compiled_sources.append(s) + source2object[s] = o + obj_list += self.flatten_object_list(target) if is_unity: for src in self.generate_unity_files(target, unity_src): - obj_list.append(self.generate_single_compile(target, src, True, unity_deps + header_deps)) + o, s = self.generate_single_compile(target, src, True, unity_deps + header_deps) + obj_list.append(o) + compiled_sources.append(s) + source2object[s] = o linker, stdlib_args = self.determine_linker_and_stdlib_args(target) - elem = self.generate_link(target, outname, obj_list, linker, pch_objects, stdlib_args=stdlib_args) - self.generate_shlib_aliases(target, self.get_target_dir(target)) + if isinstance(target, build.StaticLibrary) and target.prelink: + final_obj_list = self.generate_prelink(target, obj_list) + else: + final_obj_list = obj_list + elem = self.generate_link(target, outname, final_obj_list, linker, pch_objects, stdlib_args=stdlib_args) + self.generate_dependency_scan_target(target, compiled_sources, source2object, generated_source_files) self.add_build(elem) + def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool: + if mesonlib.version_compare(self.ninja_version, '<1.10.0'): + return False + if 'fortran' in target.compilers: + return True + if 'cpp' not in target.compilers: + return False + # Currently only the preview version of Visual Studio is supported. + cpp = target.compilers['cpp'] + if cpp.get_id() != 'msvc': + return False + cppversion = self.environment.coredata.options[OptionKey('std', machine=target.for_machine, lang='cpp')].value + if cppversion not in ('latest', 'c++latest', 'vc++latest'): + return False + if not mesonlib.current_vs_supports_modules(): + return False + if mesonlib.version_compare(cpp.version, '<19.28.28617'): + return False + return True + + def generate_dependency_scan_target(self, target, compiled_sources, source2object, generated_source_files: T.List[mesonlib.File]): + if not self.should_use_dyndeps_for_target(target): + return + depscan_file = self.get_dep_scan_file_for(target) + pickle_base = target.name + '.dat' + pickle_file = os.path.join(self.get_target_private_dir(target), pickle_base).replace('\\', '/') + pickle_abs = os.path.join(self.get_target_private_dir_abs(target), pickle_base).replace('\\', '/') + json_abs = os.path.join(self.get_target_private_dir_abs(target), f'{target.name}-deps.json').replace('\\', '/') + rule_name = 'depscan' + scan_sources = self.select_sources_to_scan(compiled_sources) + + # Dump the sources as a json list. This avoids potential probllems where + # the number of sources passed to depscan exceedes the limit imposed by + # the OS. + with open(json_abs, 'w', encoding='utf-8') as f: + json.dump(scan_sources, f) + elem = NinjaBuildElement(self.all_outputs, depscan_file, rule_name, json_abs) + elem.add_item('picklefile', pickle_file) + # Add any generated outputs to the order deps of the scan target, so + # that those sources are present + for g in generated_source_files: + elem.orderdeps.add(g.relative_name()) + scaninfo = TargetDependencyScannerInfo(self.get_target_private_dir(target), source2object) + with open(pickle_abs, 'wb') as p: + pickle.dump(scaninfo, p) + self.add_build(elem) + + def select_sources_to_scan(self, compiled_sources): + # in practice pick up C++ and Fortran files. If some other language + # requires scanning (possibly Java to deal with inner class files) + # then add them here. + all_suffixes = set(compilers.lang_suffixes['cpp']) | set(compilers.lang_suffixes['fortran']) + selected_sources = [] + for source in compiled_sources: + ext = os.path.splitext(source)[1][1:].lower() + if ext in all_suffixes: + selected_sources.append(source) + return selected_sources + def process_target_dependencies(self, target): for t in target.get_dependencies(): if t.get_id() not in self.processed_targets: @@ -643,8 +970,6 @@ def custom_target_generator_inputs(self, target): for s in target.sources: - if hasattr(s, 'held_object'): - s = s.held_object if isinstance(s, build.GeneratedList): self.generate_genlist_for_target(s, target) @@ -664,7 +989,6 @@ (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) deps = self.unwrap_dep_list(target) deps += self.get_custom_target_depend_files(target) - desc = 'Generating {0} with a {1} command.' if target.build_always_stale: deps.append('PHONY') if target.depfile is None: @@ -678,15 +1002,16 @@ for output in d.get_outputs(): elem.add_dep(os.path.join(self.get_target_dir(d), output)) - meson_exe_cmd = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:], - for_machine=target.for_machine, - extra_bdeps=target.get_transitive_build_target_deps(), - capture=ofilenames[0] if target.capture else None) - if meson_exe_cmd: - cmd = meson_exe_cmd - cmd_type = 'meson_exe.py custom' + cmd, reason = self.as_meson_exe_cmdline(target.command[0], cmd[1:], + 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, + verbose=target.console) + if reason: + cmd_type = f' (wrapped by meson {reason})' else: - cmd_type = 'custom' + cmd_type = '' if target.depfile is not None: depfile = target.get_dep_outname(elem.infilenames) rel_dfile = os.path.join(self.get_target_dir(target), depfile) @@ -695,84 +1020,55 @@ elem.add_item('DEPFILE', rel_dfile) if target.console: elem.add_item('pool', 'console') - cmd = self.replace_paths(target, cmd) + full_name = Path(target.subdir, target.name).as_posix() elem.add_item('COMMAND', cmd) - elem.add_item('description', desc.format(target.name, cmd_type)) + elem.add_item('description', f'Generating {full_name} with a custom command{cmd_type}') self.add_build(elem) - self.processed_targets[target.get_id()] = True + self.processed_targets.add(target.get_id()) def build_run_target_name(self, target): if target.subproject != '': - subproject_prefix = '{}@@'.format(target.subproject) + subproject_prefix = f'{target.subproject}@@' else: subproject_prefix = '' - return '{}{}'.format(subproject_prefix, target.name) + return f'{subproject_prefix}{target.name}' def generate_run_target(self, target): - cmd = self.environment.get_build_command() + ['--internal', 'commandrunner'] - deps = self.unwrap_dep_list(target) - arg_strings = [] - for i in target.args: - if isinstance(i, str): - arg_strings.append(i) - elif isinstance(i, (build.BuildTarget, build.CustomTarget)): - relfname = self.get_target_filename(i) - arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname)) - deps.append(relfname) - elif isinstance(i, mesonlib.File): - relfname = i.rel_to_builddir(self.build_to_src) - arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname)) - else: - raise AssertionError('Unreachable code in generate_run_target: ' + str(i)) - cmd += [self.environment.get_source_dir(), - self.environment.get_build_dir(), - target.subdir] + self.environment.get_build_command() - texe = target.command - try: - texe = texe.held_object - except AttributeError: - pass - if isinstance(texe, build.Executable): - abs_exe = os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe)) - deps.append(self.get_target_filename(texe)) - if self.environment.is_cross_build(): - exe_wrap = self.environment.get_exe_wrapper() - if exe_wrap: - if not exe_wrap.found(): - msg = 'The exe_wrapper {!r} defined in the cross file is ' \ - 'needed by run target {!r}, but was not found. ' \ - 'Please check the command and/or add it to PATH.' - raise MesonException(msg.format(exe_wrap.name, target.name)) - cmd += exe_wrap.get_command() - cmd.append(abs_exe) - elif isinstance(texe, dependencies.ExternalProgram): - cmd += texe.get_command() - elif isinstance(texe, build.CustomTarget): - deps.append(self.get_target_filename(texe)) - cmd += [os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe))] - elif isinstance(texe, mesonlib.File): - cmd.append(texe.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())) - else: - cmd.append(target.command) - cmd += arg_strings - - if texe: - target_name = 'meson-{}'.format(self.build_run_target_name(target)) - elem = NinjaBuildElement(self.all_outputs, target_name, 'CUSTOM_COMMAND', []) - elem.add_item('COMMAND', cmd) - elem.add_item('description', 'Running external command %s.' % target.name) + target_name = self.build_run_target_name(target) + if not target.command: + # This is an alias target, it has no command, it just depends on + # other targets. + elem = NinjaBuildElement(self.all_outputs, target_name, 'phony', []) + else: + target_env = self.get_run_target_env(target) + _, _, cmd = self.eval_custom_target_command(target) + meson_exe_cmd, reason = self.as_meson_exe_cmdline(target.command[0], cmd[1:], + force_serialize=True, env=target_env, + verbose=True) + cmd_type = f' (wrapped by meson {reason})' + internal_target_name = f'meson-{target_name}' + elem = NinjaBuildElement(self.all_outputs, internal_target_name, 'CUSTOM_COMMAND', []) + elem.add_item('COMMAND', meson_exe_cmd) + elem.add_item('description', f'Running external command {target.name}{cmd_type}') elem.add_item('pool', 'console') # Alias that runs the target defined above with the name the user specified - self.create_target_alias(target_name) - else: - target_name = self.build_run_target_name(target) - elem = NinjaBuildElement(self.all_outputs, target_name, 'phony', []) - + self.create_target_alias(internal_target_name) + deps = self.unwrap_dep_list(target) + deps += self.get_custom_target_depend_files(target) elem.add_dep(deps) self.add_build(elem) - self.processed_targets[target.get_id()] = True + self.processed_targets.add(target.get_id()) def generate_coverage_command(self, elem, outputs): + targets = self.build.get_targets().values() + use_llvm_cov = False + for target in targets: + if not hasattr(target, 'compilers'): + continue + for compiler in target.compilers.values(): + if compiler.get_id() == 'clang' and not compiler.info.is_darwin(): + use_llvm_cov = True + break elem.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'coverage'] + outputs + @@ -780,39 +1076,49 @@ os.path.join(self.environment.get_source_dir(), self.build.get_subproject_dir()), self.environment.get_build_dir(), - self.environment.get_log_dir()]) + self.environment.get_log_dir()] + + (['--use_llvm_cov'] if use_llvm_cov else [])) - def generate_coverage_rules(self): + def generate_coverage_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): e = NinjaBuildElement(self.all_outputs, 'meson-coverage', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, []) - e.add_item('description', 'Generates coverage reports.') + e.add_item('description', 'Generates coverage reports') self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-coverage') - self.generate_coverage_legacy_rules() - - def generate_coverage_legacy_rules(self): - e = NinjaBuildElement(self.all_outputs, 'meson-coverage-xml', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--xml']) - e.add_item('description', 'Generates XML coverage report.') - self.add_build(e) - # Alias that runs the target defined above - self.create_target_alias('meson-coverage-xml') - - e = NinjaBuildElement(self.all_outputs, 'meson-coverage-text', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--text']) - e.add_item('description', 'Generates text coverage report.') - self.add_build(e) - # Alias that runs the target defined above - self.create_target_alias('meson-coverage-text') + self.generate_coverage_legacy_rules(gcovr_exe, gcovr_version) + def generate_coverage_legacy_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): e = NinjaBuildElement(self.all_outputs, 'meson-coverage-html', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--html']) - e.add_item('description', 'Generates HTML coverage report.') + e.add_item('description', 'Generates HTML coverage report') self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-coverage-html') + if gcovr_exe: + e = NinjaBuildElement(self.all_outputs, 'meson-coverage-xml', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--xml']) + e.add_item('description', 'Generates XML coverage report') + self.add_build(e) + # Alias that runs the target defined above + self.create_target_alias('meson-coverage-xml') + + e = NinjaBuildElement(self.all_outputs, 'meson-coverage-text', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--text']) + e.add_item('description', 'Generates text coverage report') + self.add_build(e) + # Alias that runs the target defined above + self.create_target_alias('meson-coverage-text') + + if mesonlib.version_compare(gcovr_version, '>=4.2'): + e = NinjaBuildElement(self.all_outputs, 'meson-coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--sonarqube']) + e.add_item('description', 'Generates Sonarqube XML coverage report') + self.add_build(e) + # Alias that runs the target defined above + self.create_target_alias('meson-coverage-sonarqube') + def generate_install(self): self.create_install_data_files() elem = NinjaBuildElement(self.all_outputs, 'meson-install', 'CUSTOM_COMMAND', 'PHONY') @@ -827,9 +1133,9 @@ def generate_tests(self): self.serialize_tests() cmd = self.environment.get_build_command(True) + ['test', '--no-rebuild'] - if not self.environment.coredata.get_builtin_option('stdsplit'): + if not self.environment.coredata.get_option(OptionKey('stdsplit')): cmd += ['--no-stdsplit'] - if self.environment.coredata.get_builtin_option('errorlogs'): + if self.environment.coredata.get_option(OptionKey('errorlogs')): cmd += ['--print-errorlogs'] elem = NinjaBuildElement(self.all_outputs, 'meson-test', 'CUSTOM_COMMAND', ['all', 'PHONY']) elem.add_item('COMMAND', cmd) @@ -855,6 +1161,8 @@ self.rules = [] self.ruledict = {} + self.add_rule_comment(NinjaComment('Rules for module scanning.')) + self.generate_scanner_rules() self.add_rule_comment(NinjaComment('Rules for compiling.')) self.generate_compile_rules() self.add_rule_comment(NinjaComment('Rules for linking.')) @@ -869,13 +1177,15 @@ deps='gcc', depfile='$DEPFILE', extra='restat = 1')) - c = [ninja_quote(quote_func(x)) for x in self.environment.get_build_command()] + \ + c = self.environment.get_build_command() + \ ['--internal', 'regenerate', - ninja_quote(quote_func(self.environment.get_source_dir())), - ninja_quote(quote_func(self.environment.get_build_dir()))] + self.environment.get_source_dir(), + self.environment.get_build_dir(), + '--backend', + 'ninja'] self.add_rule(NinjaRule('REGENERATE_BUILD', - c + ['--backend', 'ninja'], [], + c, [], 'Regenerating build files.', extra='generator = 1')) @@ -886,17 +1196,26 @@ self.build_elements.append(comment) def add_rule(self, rule): + if rule.name in self.ruledict: + raise MesonException(f'Tried to add rule {rule.name} twice.') self.rules.append(rule) self.ruledict[rule.name] = rule def add_build(self, build): self.build_elements.append(build) - # increment rule refcount - if build.rule != 'phony': - self.ruledict[build.rule].refcount += 1 + if build.rulename != 'phony': + # reference rule + if build.rulename in self.ruledict: + build.rule = self.ruledict[build.rulename] + else: + mlog.warning(f"build statement for {build.outfilenames} references non-existent rule {build.rulename}") def write_rules(self, outfile): + for b in self.build_elements: + if isinstance(b, NinjaBuildElement): + b.count_rule_references() + for r in self.rules: r.write(outfile) @@ -940,7 +1259,7 @@ manifest_path = os.path.join(self.get_target_private_dir(target), 'META-INF', 'MANIFEST.MF') manifest_fullpath = os.path.join(self.environment.get_build_dir(), manifest_path) os.makedirs(os.path.dirname(manifest_fullpath), exist_ok=True) - with open(manifest_fullpath, 'w') as manifest: + with open(manifest_fullpath, 'w', encoding='utf-8') as manifest: if any(target.link_targets): manifest.write('Class-Path: ') cp_paths = [os.path.join(self.get_target_dir(l), l.get_filename()) for l in target.link_targets] @@ -975,27 +1294,27 @@ ofilename = os.path.join(self.get_target_private_dir(target), ofilebase) elem = NinjaBuildElement(self.all_outputs, ofilename, "CUSTOM_COMMAND", rel_sourcefile) elem.add_item('COMMAND', ['resgen', rel_sourcefile, ofilename]) - elem.add_item('DESC', 'Compiling resource %s.' % rel_sourcefile) + elem.add_item('DESC', f'Compiling resource {rel_sourcefile}') self.add_build(elem) deps.append(ofilename) a = '-resource:' + ofilename else: - raise InvalidArguments('Unknown resource file %s.' % r) + raise InvalidArguments(f'Unknown resource file {r}.') args.append(a) return args, deps - def generate_cs_target(self, target): - buildtype = self.get_option_for_target('buildtype', target) + def generate_cs_target(self, target: build.BuildTarget): + buildtype = self.get_option_for_target(OptionKey('buildtype'), target) fname = target.get_filename() outname_rel = os.path.join(self.get_target_dir(target), fname) src_list = target.get_sources() compiler = target.compilers['cs'] rel_srcs = [os.path.normpath(s.rel_to_builddir(self.build_to_src)) for s in src_list] deps = [] - commands = CompilerArgs(compiler, target.extra_args.get('cs', [])) + commands = compiler.compiler_args(target.extra_args.get('cs', [])) commands += compiler.get_buildtype_args(buildtype) - commands += compiler.get_optimization_args(self.get_option_for_target('optimization', target)) - commands += compiler.get_debug_args(self.get_option_for_target('debug', target)) + commands += compiler.get_optimization_args(self.get_option_for_target(OptionKey('optimization'), target)) + commands += compiler.get_debug_args(self.get_option_for_target(OptionKey('debug'), target)) if isinstance(target, build.Executable): commands.append('-target:exe') elif isinstance(target, build.SharedLibrary): @@ -1036,7 +1355,7 @@ def determine_single_java_compile_args(self, target, compiler): args = [] - args += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target)) + args += compiler.get_buildtype_args(self.get_option_for_target(OptionKey('buildtype'), target)) args += self.build.get_global_args(compiler, target.for_machine) args += self.build.get_project_args(compiler, target.subproject, target.for_machine) args += target.get_java_args() @@ -1069,7 +1388,7 @@ def generate_java_link(self): rule = 'java_LINKER' command = ['jar', '$ARGS'] - description = 'Creating JAR $out.' + description = 'Creating JAR $out' self.add_rule(NinjaRule(rule, command, [], description)) def determine_dep_vapis(self, target): @@ -1086,14 +1405,16 @@ for i in dep.sources: if hasattr(i, 'fname'): i = i.fname - if i.endswith('vala'): + if i.split('.')[-1] in compilers.lang_suffixes['vala']: vapiname = dep.vala_vapi fullname = os.path.join(self.get_target_dir(dep), vapiname) result.add(fullname) break return list(result) - def split_vala_sources(self, t): + def split_vala_sources(self, t: build.BuildTarget) -> \ + T.Tuple[T.MutableMapping[str, File], T.MutableMapping[str, File], + T.Tuple[T.MutableMapping[str, File], T.MutableMapping]]: """ Splits the target's sources into .vala, .gs, .vapi, and other sources. Handles both pre-existing and generated sources. @@ -1102,19 +1423,17 @@ the keys being the path to the file (relative to the build directory) and the value being the object that generated or represents the file. """ - vala = OrderedDict() - vapi = OrderedDict() - others = OrderedDict() - othersgen = OrderedDict() + vala: T.MutableMapping[str, File] = OrderedDict() + vapi: T.MutableMapping[str, File] = OrderedDict() + others: T.MutableMapping[str, File] = OrderedDict() + othersgen: T.MutableMapping[str, File] = OrderedDict() # Split pre-existing sources for s in t.get_sources(): # BuildTarget sources are always mesonlib.File files which are # either in the source root, or generated with configure_file and # in the build root if not isinstance(s, File): - msg = 'All sources in target {!r} must be of type ' \ - 'mesonlib.File, not {!r}'.format(t, s) - raise InvalidArguments(msg) + raise InvalidArguments(f'All sources in target {t!r} must be of type mesonlib.File, not {s!r}') f = s.rel_to_builddir(self.build_to_src) if s.endswith(('.vala', '.gs')): srctype = vala @@ -1146,22 +1465,22 @@ srctype[f] = gensrc return vala, vapi, (others, othersgen) - def generate_vala_compile(self, target): + def generate_vala_compile(self, target: build.BuildTarget) -> \ + T.Tuple[T.MutableMapping[str, File], T.MutableMapping[str, File], T.List[str]]: """Vala is compiled into C. Set up all necessary build steps here.""" (vala_src, vapi_src, other_src) = self.split_vala_sources(target) extra_dep_files = [] if not vala_src: - msg = 'Vala library {!r} has no Vala or Genie source files.' - raise InvalidArguments(msg.format(target.name)) + raise InvalidArguments(f'Vala library {target.name!r} has no Vala or Genie source files.') valac = target.compilers['vala'] c_out_dir = self.get_target_private_dir(target) # C files generated by valac - vala_c_src = [] + vala_c_src: T.List[str] = [] # Files generated by valac - valac_outputs = [] + valac_outputs: T.List = [] # All sources that are passed to valac on the commandline - all_files = list(vapi_src.keys()) + all_files = list(vapi_src) # Passed as --basedir srcbasedir = os.path.join(self.build_to_src, target.get_subdir()) for (vala_file, gensrc) in vala_src.items(): @@ -1199,7 +1518,7 @@ valac_outputs.append(vala_c_file) args = self.generate_basic_compiler_args(target, valac) - args += valac.get_colorout_args(self.environment.coredata.base_options.get('b_colorout').value) + args += valac.get_colorout_args(self.environment.coredata.options.get(OptionKey('b_colorout')).value) # Tell Valac to output everything in our private directory. Sadly this # means it will also preserve the directory components of Vala sources # found inside the build tree (generated sources). @@ -1225,6 +1544,7 @@ args += ['--vapi', os.path.join('..', target.vala_vapi)] valac_outputs.append(vapiname) target.outputs += [target.vala_header, target.vala_vapi] + target.install_tag += ['devel', 'devel'] # Install header and vapi to default locations if user requests this if len(target.install_dir) > 1 and target.install_dir[1] is True: target.install_dir[1] = self.environment.get_includedir() @@ -1236,6 +1556,7 @@ args += ['--gir', os.path.join('..', target.vala_gir)] valac_outputs.append(girname) target.outputs.append(target.vala_gir) + target.install_tag.append('devel') # Install GIR to default location if requested by user if len(target.install_dir) > 3 and target.install_dir[3] is True: target.install_dir[3] = os.path.join(self.environment.get_datadir(), 'gir-1.0') @@ -1265,21 +1586,109 @@ self.create_target_source_introspection(target, valac, args, all_files, []) return other_src[0], other_src[1], vala_c_src - def generate_rust_target(self, target): + def generate_cython_transpile(self, target: build.BuildTarget) -> \ + T.Tuple[T.MutableMapping[str, File], T.MutableMapping[str, File], T.List[str]]: + """Generate rules for transpiling Cython files to C or C++ + + XXX: Currently only C is handled. + """ + static_sources: T.MutableMapping[str, File] = OrderedDict() + generated_sources: T.MutableMapping[str, File] = OrderedDict() + cython_sources: T.List[str] = [] + + cython = target.compilers['cython'] + + opt_proxy = self.get_compiler_options_for_target(target) + + args: T.List[str] = [] + args += cython.get_always_args() + args += cython.get_buildtype_args(self.get_option_for_target(OptionKey('buildtype'), target)) + args += cython.get_debug_args(self.get_option_for_target(OptionKey('debug'), target)) + args += cython.get_optimization_args(self.get_option_for_target(OptionKey('optimization'), target)) + args += cython.get_option_compile_args(opt_proxy) + args += self.build.get_global_args(cython, target.for_machine) + args += self.build.get_project_args(cython, target.subproject, target.for_machine) + + ext = opt_proxy[OptionKey('language', machine=target.for_machine, lang='cython')].value + + for src in target.get_sources(): + if src.endswith('.pyx'): + output = os.path.join(self.get_target_private_dir(target), f'{src}.{ext}') + args = args.copy() + args += cython.get_output_args(output) + element = NinjaBuildElement( + self.all_outputs, [output], + self.compiler_to_rule_name(cython), + [src.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())]) + element.add_item('ARGS', args) + self.add_build(element) + # TODO: introspection? + cython_sources.append(output) + else: + static_sources[src.rel_to_builddir(self.build_to_src)] = src + + for gen in target.get_generated_sources(): + for ssrc in gen.get_outputs(): + if isinstance(gen, GeneratedList): + ssrc = os.path.join(self.get_target_private_dir(target), ssrc) + else: + ssrc = os.path.join(gen.get_subdir(), ssrc) + if ssrc.endswith('.pyx'): + args = args.copy() + output = os.path.join(self.get_target_private_dir(target), f'{ssrc}.{ext}') + args += cython.get_output_args(output) + element = NinjaBuildElement( + self.all_outputs, [output], + self.compiler_to_rule_name(cython), + [ssrc]) + element.add_item('ARGS', args) + self.add_build(element) + # TODO: introspection? + cython_sources.append(output) + else: + generated_sources[ssrc] = mesonlib.File.from_built_file(gen.get_subdir(), ssrc) + + return static_sources, generated_sources, cython_sources + + def generate_rust_target(self, target: build.BuildTarget) -> None: rustc = target.compilers['rust'] # Rust compiler takes only the main file as input and # figures out what other files are needed via import # statements and magic. + base_proxy = self.get_base_options_for_target(target) + args = rustc.compiler_args() + # Compiler args for compiling this target + args += compilers.get_base_compile_args(base_proxy, rustc) + self.generate_generator_list_rules(target) + + # dependencies need to cause a relink, they're not just for odering + deps = [ + os.path.join(t.subdir, t.get_filename()) + for t in itertools.chain(target.link_targets, target.link_whole_targets) + ] + + orderdeps: T.List[str] = [] + main_rust_file = None for i in target.get_sources(): if not rustc.can_compile(i): - raise InvalidArguments('Rust target %s contains a non-rust source file.' % target.get_basename()) + raise InvalidArguments(f'Rust target {target.get_basename()} contains a non-rust source file.') if main_rust_file is None: main_rust_file = i.rel_to_builddir(self.build_to_src) + for g in target.get_generated_sources(): + for i in g.get_outputs(): + if not rustc.can_compile(i): + raise InvalidArguments(f'Rust target {target.get_basename()} contains a non-rust source file.') + if isinstance(g, GeneratedList): + fname = os.path.join(self.get_target_private_dir(target), i) + else: + fname = os.path.join(g.get_subdir(), i) + if main_rust_file is None: + main_rust_file = fname + orderdeps.append(fname) if main_rust_file is None: raise RuntimeError('A Rust target has no Rust sources. This is weird. Also a bug. Please report') target_name = os.path.join(target.subdir, target.get_filename()) - args = ['--crate-type'] if isinstance(target, build.Executable): cratetype = 'bin' elif hasattr(target, 'rust_crate_type'): @@ -1290,42 +1699,63 @@ cratetype = 'rlib' else: raise InvalidArguments('Unknown target type for rustc.') - args.append(cratetype) + args.extend(['--crate-type', cratetype]) # If we're dynamically linking, add those arguments # # Rust is super annoying, calling -C link-arg foo does not work, it has # to be -C link-arg=foo if cratetype in {'bin', 'dylib'}: - for a in rustc.linker.get_always_args(): - args += ['-C', 'link-arg={}'.format(a)] + args.extend(rustc.get_linker_always_args()) - args += ['--crate-name', target.name] - args += rustc.get_buildtype_args(self.get_option_for_target('buildtype', target)) - args += rustc.get_debug_args(self.get_option_for_target('debug', target)) - args += rustc.get_optimization_args(self.get_option_for_target('optimization', target)) - args += self.build.get_global_args(rustc, target.for_machine) - args += self.build.get_project_args(rustc, target.subproject, target.for_machine) + args += self.generate_basic_compiler_args(target, rustc, False) + # This matches rustc's default behavior. + args += ['--crate-name', target.name.replace('-', '_')] depfile = os.path.join(target.subdir, target.name + '.d') - args += ['--emit', 'dep-info={}'.format(depfile), '--emit', 'link'] + args += ['--emit', f'dep-info={depfile}', '--emit', 'link'] args += target.get_extra_args('rust') - args += ['-o', os.path.join(target.subdir, target.get_filename())] - orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets] - linkdirs = OrderedDict() - for d in target.link_targets: - linkdirs[d.subdir] = True - # specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust - # dependency, so that collisions with libraries in rustc's - # sysroot don't cause ambiguity - args += ['--extern', '{}={}'.format(d.name, os.path.join(d.subdir, d.filename))] - for d in linkdirs.keys(): + args += rustc.get_output_args(os.path.join(target.subdir, target.get_filename())) + linkdirs = mesonlib.OrderedSet() + external_deps = target.external_deps.copy() + for d in itertools.chain(target.link_targets, target.link_whole_targets): + linkdirs.add(d.subdir) + if d.uses_rust(): + # specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust + # dependency, so that collisions with libraries in rustc's + # sysroot don't cause ambiguity + args += ['--extern', '{}={}'.format(d.name, os.path.join(d.subdir, d.filename))] + elif d.typename == 'static library': + # Rustc doesn't follow Meson's convention that static libraries + # are called .a, and import libraries are .lib, so we have to + # manually handle that. + if rustc.linker.id in {'link', 'lld-link'}: + args += ['-C', f'link-arg={self.get_target_filename_for_linking(d)}'] + else: + args += ['-l', f'static={d.name}'] + external_deps.extend(d.external_deps) + else: + # Rust uses -l for non rust dependencies, but we still need to + # add dylib=foo + args += ['-l', f'dylib={d.name}'] + for e in external_deps: + for a in e.get_link_args(): + if a.endswith(('.dll', '.so', '.dylib')): + dir_, lib = os.path.split(a) + linkdirs.add(dir_) + lib, ext = os.path.splitext(lib) + if lib.startswith('lib'): + lib = lib[3:] + args.extend(['-l', f'dylib={lib}']) + elif a.startswith('-L'): + args.append(a) + elif a.startswith('-l'): + _type = 'static' if e.static else 'dylib' + args.extend(['-l', f'{_type}={a[2:]}']) + for d in linkdirs: if d == '': d = '.' args += ['-L', d] - has_shared_deps = False - for dep in target.get_dependencies(): - if isinstance(dep, build.SharedLibrary): - has_shared_deps = True + has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target.get_dependencies()) if isinstance(target, build.SharedLibrary) or has_shared_deps: # add prefer-dynamic if any of the Rust libraries we link # against are dynamic, otherwise we'll end up with @@ -1344,20 +1774,23 @@ self.get_target_dir(target)) else: target_slashname_workaround_dir = self.get_target_dir(target) - rpath_args = rustc.build_rpath_args(self.environment, - self.environment.get_build_dir(), - target_slashname_workaround_dir, - self.determine_rpath_dirs(target), - target.build_rpath, - target.install_rpath) + rpath_args, target.rpath_dirs_to_remove = ( + rustc.build_rpath_args(self.environment, + self.environment.get_build_dir(), + target_slashname_workaround_dir, + self.determine_rpath_dirs(target), + target.build_rpath, + target.install_rpath)) # ... but then add rustc's sysroot to account for rustup # installations for rpath_arg in rpath_args: args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')] compiler_name = self.get_compiler_rule_name('rust', target.for_machine) element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, main_rust_file) - if len(orderdeps) > 0: + if orderdeps: element.add_orderdep(orderdeps) + if deps: + element.add_dep(deps) element.add_item('ARGS', args) element.add_item('targetdep', depfile) element.add_item('cratetype', cratetype) @@ -1372,11 +1805,11 @@ @classmethod def get_compiler_rule_name(cls, lang: str, for_machine: MachineChoice) -> str: - return '%s_COMPILER%s' % (lang, cls.get_rule_suffix(for_machine)) + return '{}_COMPILER{}'.format(lang, cls.get_rule_suffix(for_machine)) @classmethod def get_pch_rule_name(cls, lang: str, for_machine: MachineChoice) -> str: - return '%s_PCH%s' % (lang, cls.get_rule_suffix(for_machine)) + return '{}_PCH{}'.format(lang, cls.get_rule_suffix(for_machine)) @classmethod def compiler_to_rule_name(cls, compiler: Compiler) -> str: @@ -1393,12 +1826,6 @@ def target_swift_modulename(self, target): return target.name - def is_swift_target(self, target): - for s in target.sources: - if s.endswith('swift'): - return True - return False - def determine_swift_dep_modules(self, target): result = [] for l in target.link_targets: @@ -1406,12 +1833,6 @@ result.append(self.swift_module_file_name(l)) return result - def determine_swift_dep_dirs(self, target): - result = [] - for l in target.link_targets: - result.append(self.get_target_private_dir_abs(l)) - return result - def get_swift_link_deps(self, target): result = [] for l in target.link_targets: @@ -1448,11 +1869,11 @@ abs_headers.append(absh) header_imports += swiftc.get_header_import_args(absh) else: - raise InvalidArguments('Swift target %s contains a non-swift source file.' % target.get_basename()) + raise InvalidArguments(f'Swift target {target.get_basename()} contains a non-swift source file.') os.makedirs(self.get_target_private_dir_abs(target), exist_ok=True) compile_args = swiftc.get_compile_only_args() - compile_args += swiftc.get_optimization_args(self.get_option_for_target('optimization', target)) - compile_args += swiftc.get_debug_args(self.get_option_for_target('debug', target)) + compile_args += swiftc.get_optimization_args(self.get_option_for_target(OptionKey('optimization'), target)) + compile_args += swiftc.get_debug_args(self.get_option_for_target(OptionKey('debug'), target)) compile_args += swiftc.get_module_args(module_name) compile_args += self.build.get_project_args(swiftc, target.subproject, target.for_machine) compile_args += self.build.get_global_args(swiftc, target.for_machine) @@ -1464,7 +1885,7 @@ else: expdir = basedir srctreedir = os.path.normpath(os.path.join(self.environment.get_build_dir(), self.build_to_src, expdir)) - sargs = swiftc.get_include_args(srctreedir) + sargs = swiftc.get_include_args(srctreedir, False) compile_args += sargs link_args = swiftc.get_output_args(os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))) link_args += self.build.get_project_link_args(swiftc, target.subproject, target.for_machine) @@ -1475,7 +1896,7 @@ abs_module_dirs = self.determine_swift_dep_dirs(target) module_includes = [] for x in abs_module_dirs: - module_includes += swiftc.get_include_args(x) + module_includes += swiftc.get_include_args(x, False) link_deps = self.get_swift_link_deps(target) abs_link_deps = [os.path.join(self.environment.get_build_dir(), x) for x in link_deps] for d in target.link_targets: @@ -1527,15 +1948,26 @@ # Introspection information self.create_target_source_introspection(target, swiftc, compile_args + header_imports + module_includes, relsrc, rel_generated) + def _rsp_options(self, tool: T.Union['Compiler', 'StaticLinker', 'DynamicLinker']) -> T.Dict[str, T.Union[bool, RSPFileSyntax]]: + """Helper method to get rsp options. + + rsp_file_syntax() is only guaranteed to be implemented if + can_linker_accept_rsp() returns True. + """ + options = dict(rspable=tool.can_linker_accept_rsp()) + if options['rspable']: + options['rspfile_quote_style'] = tool.rsp_file_syntax() + return options + def generate_static_link_rules(self): - num_pools = self.environment.coredata.backend_options['backend_max_links'].value + num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value if 'java' in self.environment.coredata.compilers.host: self.generate_java_link() for for_machine in MachineChoice: static_linker = self.build.static_linker[for_machine] if static_linker is None: - return - rule = 'STATIC_LINKER%s' % self.get_rule_suffix(for_machine) + continue + rule = 'STATIC_LINKER{}'.format(self.get_rule_suffix(for_machine)) cmdlist = [] args = ['$in'] # FIXME: Must normalize file names with pathlib.Path before writing @@ -1549,77 +1981,79 @@ cmdlist = execute_wrapper + [c.format('$out') for c in rmfile_prefix] cmdlist += static_linker.get_exelist() cmdlist += ['$LINK_ARGS'] - cmdlist += static_linker.get_output_args('$out') - description = 'Linking static target $out.' + cmdlist += NinjaCommandArg.list(static_linker.get_output_args('$out'), Quoting.none) + description = 'Linking static target $out' if num_pools > 0: pool = 'pool = link_pool' else: pool = None - self.add_rule(NinjaRule(rule, cmdlist, args, description, - rspable=static_linker.can_linker_accept_rsp(), - extra=pool)) + + options = self._rsp_options(static_linker) + self.add_rule(NinjaRule(rule, cmdlist, args, description, **options, extra=pool)) def generate_dynamic_link_rules(self): - num_pools = self.environment.coredata.backend_options['backend_max_links'].value + num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value for for_machine in MachineChoice: complist = self.environment.coredata.compilers[for_machine] for langname, compiler in complist.items(): - if langname == 'java' \ - or langname == 'vala' \ - or langname == 'rust' \ - or langname == 'cs': + if langname in {'java', 'vala', 'rust', 'cs', 'cython'}: continue - rule = '%s_LINKER%s' % (langname, self.get_rule_suffix(for_machine)) + rule = '{}_LINKER{}'.format(langname, self.get_rule_suffix(for_machine)) command = compiler.get_linker_exelist() - args = ['$ARGS'] + compiler.get_linker_output_args('$out') + ['$in', '$LINK_ARGS'] - description = 'Linking target $out.' + args = ['$ARGS'] + NinjaCommandArg.list(compiler.get_linker_output_args('$out'), Quoting.none) + ['$in', '$LINK_ARGS'] + description = 'Linking target $out' if num_pools > 0: pool = 'pool = link_pool' else: pool = None - self.add_rule(NinjaRule(rule, command, args, description, - rspable=compiler.can_linker_accept_rsp(), - extra=pool)) - args = [ninja_quote(quote_func(x)) for x in self.environment.get_build_command()] + \ + options = self._rsp_options(compiler) + self.add_rule(NinjaRule(rule, command, args, description, **options, extra=pool)) + + args = self.environment.get_build_command() + \ ['--internal', 'symbolextractor', + self.environment.get_build_dir(), '$in', + '$IMPLIB', '$out'] symrule = 'SHSYM' symcmd = args + ['$CROSS'] - syndesc = 'Generating symbol file $out.' + syndesc = 'Generating symbol file $out' synstat = 'restat = 1' self.add_rule(NinjaRule(symrule, symcmd, [], syndesc, extra=synstat)) def generate_java_compile_rule(self, compiler): rule = self.compiler_to_rule_name(compiler) - invoc = [ninja_quote(i) for i in compiler.get_exelist()] - command = invoc + ['$ARGS', '$in'] - description = 'Compiling Java object $in.' + command = compiler.get_exelist() + ['$ARGS', '$in'] + description = 'Compiling Java object $in' self.add_rule(NinjaRule(rule, command, [], description)) - def generate_cs_compile_rule(self, compiler): + def generate_cs_compile_rule(self, compiler: 'CsCompiler') -> None: rule = self.compiler_to_rule_name(compiler) - invoc = [ninja_quote(i) for i in compiler.get_exelist()] - command = invoc + command = compiler.get_exelist() args = ['$ARGS', '$in'] - description = 'Compiling C Sharp target $out.' + description = 'Compiling C Sharp target $out' self.add_rule(NinjaRule(rule, command, args, description, - rspable=mesonlib.is_windows())) + rspable=mesonlib.is_windows(), + rspfile_quote_style=compiler.rsp_file_syntax())) def generate_vala_compile_rules(self, compiler): rule = self.compiler_to_rule_name(compiler) - invoc = [ninja_quote(i) for i in compiler.get_exelist()] - command = invoc + ['$ARGS', '$in'] - description = 'Compiling Vala source $in.' + command = compiler.get_exelist() + ['$ARGS', '$in'] + description = 'Compiling Vala source $in' + self.add_rule(NinjaRule(rule, command, [], description, extra='restat = 1')) + + def generate_cython_compile_rules(self, compiler: 'Compiler') -> None: + rule = self.compiler_to_rule_name(compiler) + command = compiler.get_exelist() + ['$ARGS', '$in'] + description = 'Compiling Cython source $in' self.add_rule(NinjaRule(rule, command, [], description, extra='restat = 1')) def generate_rust_compile_rules(self, compiler): rule = self.compiler_to_rule_name(compiler) - invoc = [ninja_quote(i) for i in compiler.get_exelist()] - command = invoc + ['$ARGS', '$in'] - description = 'Compiling Rust source $in.' + command = compiler.get_exelist() + ['$ARGS', '$in'] + description = 'Compiling Rust source $in' depfile = '$targetdep' depstyle = 'gcc' self.add_rule(NinjaRule(rule, command, [], description, deps=depstyle, @@ -1627,18 +2061,26 @@ def generate_swift_compile_rules(self, compiler): rule = self.compiler_to_rule_name(compiler) - full_exe = [ninja_quote(x) for x in self.environment.get_build_command()] + [ + full_exe = self.environment.get_build_command() + [ '--internal', 'dirchanger', '$RUNDIR', ] - invoc = full_exe + [ninja_quote(i) for i in compiler.get_exelist()] + invoc = full_exe + compiler.get_exelist() command = invoc + ['$ARGS', '$in'] - description = 'Compiling Swift source $in.' + description = 'Compiling Swift source $in' self.add_rule(NinjaRule(rule, command, [], description)) - def generate_fortran_dep_hack(self, crstr): - rule = 'FORTRAN_DEP_HACK%s' % (crstr) + def use_dyndeps_for_fortran(self) -> bool: + '''Use the new Ninja feature for scanning dependencies during build, + rather than up front. Remove this and all old scanning code once Ninja + minimum version is bumped to 1.10.''' + return mesonlib.version_compare(self.ninja_version, '>=1.10.0') + + def generate_fortran_dep_hack(self, crstr: str) -> None: + if self.use_dyndeps_for_fortran(): + return + rule = f'FORTRAN_DEP_HACK{crstr}' if mesonlib.is_windows(): cmd = ['cmd', '/C'] else: @@ -1652,17 +2094,18 @@ if self.created_llvm_ir_rule[compiler.for_machine]: return rule = self.get_compiler_rule_name('llvm_ir', compiler.for_machine) - command = [ninja_quote(i) for i in compiler.get_exelist()] - args = ['$ARGS'] + compiler.get_output_args('$out') + compiler.get_compile_only_args() + ['$in'] - description = 'Compiling LLVM IR object $in.' - self.add_rule(NinjaRule(rule, command, args, description, - rspable=compiler.can_linker_accept_rsp())) + command = compiler.get_exelist() + args = ['$ARGS'] + NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + compiler.get_compile_only_args() + ['$in'] + description = 'Compiling LLVM IR object $in' + + options = self._rsp_options(compiler) + + self.add_rule(NinjaRule(rule, command, args, description, **options)) self.created_llvm_ir_rule[compiler.for_machine] = True def generate_compile_rule_for(self, langname, compiler): if langname == 'java': - if self.environment.machines.matches_build_machine(compiler.for_machine): - self.generate_java_compile_rule(compiler) + self.generate_java_compile_rule(compiler) return if langname == 'cs': if self.environment.machines.matches_build_machine(compiler.for_machine): @@ -1678,28 +2121,25 @@ if self.environment.machines.matches_build_machine(compiler.for_machine): self.generate_swift_compile_rules(compiler) return + if langname == 'cython': + self.generate_cython_compile_rules(compiler) + return crstr = self.get_rule_suffix(compiler.for_machine) if langname == 'fortran': self.generate_fortran_dep_hack(crstr) rule = self.get_compiler_rule_name(langname, compiler.for_machine) - depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') - quoted_depargs = [] - for d in depargs: - if d != '$out' and d != '$in': - d = quote_func(d) - quoted_depargs.append(d) - - command = [ninja_quote(i) for i in compiler.get_exelist()] - args = ['$ARGS'] + quoted_depargs + compiler.get_output_args('$out') + compiler.get_compile_only_args() + ['$in'] - description = 'Compiling %s object $out.' % compiler.get_display_language() + depargs = NinjaCommandArg.list(compiler.get_dependency_gen_args('$out', '$DEPFILE'), Quoting.none) + command = compiler.get_exelist() + args = ['$ARGS'] + depargs + NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + compiler.get_compile_only_args() + ['$in'] + description = f'Compiling {compiler.get_display_language()} object $out' if isinstance(compiler, VisualStudioLikeCompiler): deps = 'msvc' depfile = None else: deps = 'gcc' depfile = '$DEPFILE' - self.add_rule(NinjaRule(rule, command, args, description, - rspable=compiler.can_linker_accept_rsp(), + options = self._rsp_options(compiler) + self.add_rule(NinjaRule(rule, command, args, description, **options, deps=deps, depfile=depfile)) def generate_pch_rule_for(self, langname, compiler): @@ -1708,17 +2148,12 @@ rule = self.compiler_to_pch_rule_name(compiler) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') - quoted_depargs = [] - for d in depargs: - if d != '$out' and d != '$in': - d = quote_func(d) - quoted_depargs.append(d) if isinstance(compiler, VisualStudioLikeCompiler): output = [] else: - output = compiler.get_output_args('$out') - command = compiler.get_exelist() + ['$ARGS'] + quoted_depargs + output + compiler.get_compile_only_args() + ['$in'] - description = 'Precompiling header $in.' + output = NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + command = compiler.get_exelist() + ['$ARGS'] + depargs + output + compiler.get_compile_only_args() + ['$in'] + description = 'Precompiling header $in' if isinstance(compiler, VisualStudioLikeCompiler): deps = 'msvc' depfile = None @@ -1728,6 +2163,18 @@ self.add_rule(NinjaRule(rule, command, [], description, deps=deps, depfile=depfile)) + def generate_scanner_rules(self): + rulename = 'depscan' + if rulename in self.ruledict: + # Scanning command is the same for native and cross compilation. + return + command = self.environment.get_build_command() + \ + ['--internal', 'depscan'] + args = ['$picklefile', '$out', '$in'] + description = 'Module scanner.' + rule = NinjaRule(rulename, command, args, description) + self.add_rule(rule) + def generate_compile_rules(self): for for_machine in MachineChoice: clist = self.environment.coredata.compilers[for_machine] @@ -1764,16 +2211,15 @@ generator = genlist.get_generator() subdir = genlist.subdir exe = generator.get_exe() - exe_arr = self.exe_object_to_cmd_array(exe) + exe_arr = self.build_target_to_cmd_array(exe) infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() extra_dependencies = self.get_custom_target_depend_files(genlist) - for i in range(len(infilelist)): - curfile = infilelist[i] + for i, curfile in enumerate(infilelist): if len(generator.outputs) == 1: sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i]) else: - sole_output = '{}'.format(curfile) + sole_output = f'{curfile}' infilename = curfile.rel_to_builddir(self.build_to_src) base_args = generator.get_arglist(infilename) outfiles = genlist.get_outputs_for(curfile) @@ -1794,11 +2240,8 @@ outfilelist = outfilelist[len(generator.outputs):] args = self.replace_paths(target, args, override_subdir=subdir) cmdlist = exe_arr + self.replace_extra_args(args, genlist) - meson_exe_cmd = self.as_meson_exe_cmdline('generator ' + cmdlist[0], - cmdlist[0], cmdlist[1:], - capture=outfiles[0] if generator.capture else None) - if meson_exe_cmd: - cmdlist = meson_exe_cmd + cmdlist, reason = self.as_meson_exe_cmdline(cmdlist[0], cmdlist[1:], + capture=outfiles[0] if generator.capture else None) abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) os.makedirs(abs_pdir, exist_ok=True) @@ -1808,11 +2251,16 @@ elem.add_item('DEPFILE', depfile) if len(extra_dependencies) > 0: elem.add_dep(extra_dependencies) + if len(generator.outputs) == 1: - elem.add_item('DESC', 'Generating {!r}.'.format(sole_output)) + what = f'{sole_output!r}' else: # since there are multiple outputs, we log the source that caused the rebuild - elem.add_item('DESC', 'Generating source from {!r}.'.format(sole_output)) + what = f'from {sole_output!r}.' + if reason: + reason = f' (wrapped by meson {reason})' + elem.add_item('DESC', f'Generating {what}{reason}.') + if isinstance(exe, build.BuildTarget): elem.add_dep(self.get_target_filename(exe)) elem.add_item('COMMAND', cmdlist) @@ -1822,6 +2270,8 @@ """ Find all module and submodule made available in a Fortran code file. """ + if self.use_dyndeps_for_fortran(): + return compiler = None # TODO other compilers for lang, c in self.environment.coredata.compilers.host.items(): @@ -1852,9 +2302,8 @@ modname = modmatch.group(1).lower() if modname in module_files: raise InvalidArguments( - 'Namespace collision: module %s defined in ' - 'two files %s and %s.' % - (modname, module_files[modname], s)) + f'Namespace collision: module {modname} defined in ' + 'two files {module_files[modname]} and {s}.') module_files[modname] = s else: submodmatch = submodre.match(line) @@ -1865,9 +2314,8 @@ if submodname in submodule_files: raise InvalidArguments( - 'Namespace collision: submodule %s defined in ' - 'two files %s and %s.' % - (submodname, submodule_files[submodname], s)) + 'Namespace collision: submodule {submodname} defined in ' + 'two files {submodule_files[submodname]} and {s}.') submodule_files[submodname] = s self.fortran_deps[target.get_basename()] = {**module_files, **submodule_files} @@ -1876,6 +2324,8 @@ """ Find all module and submodule needed by a Fortran target """ + if self.use_dyndeps_for_fortran(): + return [] dirname = Path(self.get_target_private_dir(target)) tdeps = self.fortran_deps[target.get_basename()] @@ -1884,12 +2334,10 @@ mod_files = _scan_fortran_file_deps(src, srcdir, dirname, tdeps, compiler) return mod_files - def get_cross_stdlib_args(self, target, compiler): - if self.environment.machines.matches_build_machine(target.for_machine): - return [] - if not self.environment.properties.host.has_stdlib(compiler.language): - return [] - return compiler.get_no_stdinc_args() + def get_no_stdlib_link_args(self, target, linker): + if hasattr(linker, 'language') and linker.language in self.build.stdlibs[target.for_machine]: + return linker.get_no_stdlib_link_args() + return [] def get_compile_debugfile_args(self, compiler, target, objfile): # The way MSVC uses PDB files is documented exactly nowhere so @@ -1946,15 +2394,18 @@ else: return compiler.get_compile_debugfile_args(objfile, pch=False) + def get_link_debugfile_name(self, linker, target, outname): + return linker.get_link_debugfile_name(outname) + def get_link_debugfile_args(self, linker, target, outname): return linker.get_link_debugfile_args(outname) def generate_llvm_ir_compile(self, target, src): + base_proxy = self.get_base_options_for_target(target) compiler = get_compiler_for_source(target.compilers.values(), src) - commands = CompilerArgs(compiler) + commands = compiler.compiler_args() # Compiler args for compiling this target - commands += compilers.get_base_compile_args(self.environment.coredata.base_options, - compiler) + commands += compilers.get_base_compile_args(base_proxy, compiler) if isinstance(src, File): if src.is_built: src_filename = os.path.join(src.subdir, src.fname) @@ -1964,7 +2415,7 @@ src_filename = os.path.basename(src) else: src_filename = src - obj_basename = src_filename.replace('/', '_').replace('\\', '_') + obj_basename = self.canonicalize_filename(src_filename) rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) rel_obj += '.' + self.environment.machines[target.for_machine].get_object_suffix() commands += self.get_compile_debugfile_args(compiler, target, rel_obj) @@ -1973,54 +2424,23 @@ elif isinstance(src, File): rel_src = src.rel_to_builddir(self.build_to_src) else: - raise InvalidArguments('Invalid source type: {!r}'.format(src)) + raise InvalidArguments(f'Invalid source type: {src!r}') # Write the Ninja build command compiler_name = self.get_compiler_rule_name('llvm_ir', compiler.for_machine) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) - # Convert from GCC-style link argument naming to the naming used by the - # current compiler. - commands = commands.to_native() element.add_item('ARGS', commands) self.add_build(element) - return rel_obj - - def get_source_dir_include_args(self, target, compiler): - curdir = target.get_subdir() - tmppath = os.path.normpath(os.path.join(self.build_to_src, curdir)) - return compiler.get_include_args(tmppath, False) - - def get_build_dir_include_args(self, target, compiler): - curdir = target.get_subdir() - if curdir == '': - curdir = '.' - return compiler.get_include_args(curdir, False) - - def get_custom_target_dir_include_args(self, target, compiler): - custom_target_include_dirs = [] - for i in target.get_generated_sources(): - # Generator output goes into the target private dir which is - # already in the include paths list. Only custom targets have their - # own target build dir. - if not isinstance(i, (build.CustomTarget, build.CustomTargetIndex)): - continue - idir = self.get_target_dir(i) - if not idir: - idir = '.' - if idir not in custom_target_include_dirs: - custom_target_include_dirs.append(idir) - incs = [] - for i in custom_target_include_dirs: - incs += compiler.get_include_args(i, False) - return incs + return (rel_obj, rel_src) @lru_cache(maxsize=None) - def generate_inc_dir(self, compiler, d, basedir, is_system): + def generate_inc_dir(self, compiler: 'Compiler', d: str, basedir: str, is_system: bool) -> \ + T.Tuple['ImmutableListProtocol[str]', 'ImmutableListProtocol[str]']: # Avoid superfluous '/.' at the end of paths when d is '.' if d not in ('', '.'): - expdir = os.path.join(basedir, d) + expdir = os.path.normpath(os.path.join(basedir, d)) else: expdir = basedir - srctreedir = os.path.join(self.build_to_src, expdir) + srctreedir = os.path.normpath(os.path.join(self.build_to_src, expdir)) sargs = compiler.get_include_args(srctreedir, is_system) # There may be include dirs where a build directory has not been # created for some source dir. For example if someone does this: @@ -2034,12 +2454,17 @@ bargs = [] return (sargs, bargs) - @lru_cache(maxsize=None) - def _generate_single_compile(self, target, compiler, is_generated=False): + def _generate_single_compile(self, target: build.BuildTarget, compiler: 'Compiler', + is_generated: bool = False) -> 'CompilerArgs': + commands = self._generate_single_compile_base_args(target, compiler) + commands += self._generate_single_compile_target_args(target, compiler, is_generated) + return commands + + def _generate_single_compile_base_args(self, target: build.BuildTarget, compiler: 'Compiler') -> 'CompilerArgs': base_proxy = self.get_base_options_for_target(target) # Create an empty commands list, and start adding arguments from # various sources in the order in which they must override each other - commands = CompilerArgs(compiler) + commands = compiler.compiler_args() # Start with symbol visibility. commands += compiler.gnu_symbol_visibility_args(target.gnu_symbol_visibility) # Add compiler args for compiling this target derived from 'base' build @@ -2047,18 +2472,21 @@ # These have the lowest priority. commands += compilers.get_base_compile_args(base_proxy, compiler) + return commands + + @lru_cache(maxsize=None) + def _generate_single_compile_target_args(self, target: build.BuildTarget, compiler: 'Compiler', + is_generated: bool = False) -> 'ImmutableListProtocol[str]': # The code generated by valac is usually crap and has tons of unused # variables and such, so disable warnings for Vala C sources. no_warn_args = (is_generated == 'vala') # Add compiler args and include paths from several sources; defaults, # build options, external dependencies, etc. - commands += self.generate_basic_compiler_args(target, compiler, no_warn_args) + commands = self.generate_basic_compiler_args(target, compiler, no_warn_args) # Add custom target dirs as includes automatically, but before # target-specific include directories. - # XXX: Not sure if anyone actually uses this? It can cause problems in - # situations which increase the likelihood for a header name collision, - # such as in subprojects. - commands += self.get_custom_target_dir_include_args(target, compiler) + if target.implicit_include_directories: + commands += self.get_custom_target_dir_include_args(target, compiler) # Add include dirs from the `include_directories:` kwarg on the target # and from `include_directories:` of internal deps of the target. # @@ -2082,8 +2510,7 @@ commands += compiler.get_include_args(d, i.is_system) # Add per-target compile args, f.ex, `c_args : ['-DFOO']`. We set these # near the end since these are supposed to override everything else. - commands += self.escape_extra_args(compiler, - target.get_extra_args(compiler.get_language())) + commands += self.escape_extra_args(target.get_extra_args(compiler.get_language())) # D specific additional flags if compiler.language == 'd': @@ -2115,11 +2542,18 @@ order_deps = order_deps if order_deps is not None else [] if isinstance(src, str) and src.endswith('.h'): - raise AssertionError('BUG: sources should not contain headers {!r}'.format(src)) + raise AssertionError(f'BUG: sources should not contain headers {src!r}') compiler = get_compiler_for_source(target.compilers.values(), src) - commands = self._generate_single_compile(target, compiler, is_generated) - commands = CompilerArgs(commands.compiler, commands) + commands = self._generate_single_compile_base_args(target, compiler) + + # Include PCH header as first thing as it must be the first one or it will be + # ignored by gcc https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100462 + if self.environment.coredata.options.get(OptionKey('b_pch')) and is_generated != 'pch': + commands += self.get_pch_include_args(compiler, target) + + commands += self._generate_single_compile_target_args(target, compiler, is_generated) + commands = commands.compiler.compiler_args(commands) # Create introspection information if is_generated is False: @@ -2137,9 +2571,9 @@ assert rel_src.startswith(build_dir) rel_src = rel_src[len(build_dir) + 1:] elif is_generated: - raise AssertionError('BUG: broken generated source file handling for {!r}'.format(src)) + raise AssertionError(f'BUG: broken generated source file handling for {src!r}') else: - raise InvalidArguments('Invalid source type: {!r}'.format(src)) + raise InvalidArguments(f'Invalid source type: {src!r}') obj_basename = self.object_filename_from_source(target, src) rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) dep_file = compiler.depfile_for_object(rel_obj) @@ -2148,8 +2582,7 @@ commands += self.get_compile_debugfile_args(compiler, target, rel_obj) # PCH handling - if self.environment.coredata.base_options.get('b_pch', False): - commands += self.get_pch_include_args(compiler, target) + if self.environment.coredata.options.get(OptionKey('b_pch')): pchlist = target.get_pch(compiler.language) else: pchlist = [] @@ -2173,16 +2606,20 @@ if not is_generated: abs_src = Path(build_dir) / rel_src extra_deps += self.get_fortran_deps(compiler, abs_src, target) - # Dependency hack. Remove once multiple outputs in Ninja is fixed: - # https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 - for modname, srcfile in self.fortran_deps[target.get_basename()].items(): - modfile = os.path.join(self.get_target_private_dir(target), - compiler.module_name_to_filename(modname)) - - if srcfile == src: - crstr = self.get_rule_suffix(target.for_machine) - depelem = NinjaBuildElement(self.all_outputs, modfile, 'FORTRAN_DEP_HACK' + crstr, rel_obj) - self.add_build(depelem) + if not self.use_dyndeps_for_fortran(): + # Dependency hack. Remove once multiple outputs in Ninja is fixed: + # https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 + for modname, srcfile in self.fortran_deps[target.get_basename()].items(): + modfile = os.path.join(self.get_target_private_dir(target), + compiler.module_name_to_filename(modname)) + + if srcfile == src: + crstr = self.get_rule_suffix(target.for_machine) + depelem = NinjaBuildElement(self.all_outputs, + modfile, + 'FORTRAN_DEP_HACK' + crstr, + rel_obj) + self.add_build(depelem) commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) @@ -2196,15 +2633,29 @@ d = os.path.join(self.get_target_private_dir(target), d) element.add_orderdep(d) element.add_dep(pch_dep) - # Convert from GCC-style link argument naming to the naming used by the - # current compiler. - commands = commands.to_native() for i in self.get_fortran_orderdeps(target, compiler): element.add_orderdep(i) element.add_item('DEPFILE', dep_file) element.add_item('ARGS', commands) + + self.add_dependency_scanner_entries_to_element(target, compiler, element, src) self.add_build(element) - return rel_obj + assert isinstance(rel_obj, str) + assert isinstance(rel_src, str) + return (rel_obj, rel_src.replace('\\', '/')) + + def add_dependency_scanner_entries_to_element(self, target, compiler, element, src): + if not self.should_use_dyndeps_for_target(target): + return + extension = os.path.splitext(src.fname)[1][1:] + if not (extension.lower() in compilers.lang_suffixes['fortran'] or extension in compilers.lang_suffixes['cpp']): + return + dep_scan_file = self.get_dep_scan_file_for(target) + element.add_item('dyndep', dep_scan_file) + element.add_orderdep(dep_scan_file) + + def get_dep_scan_file_for(self, target): + return os.path.join(self.get_target_private_dir(target), 'depscan.dd') def add_header_deps(self, target, ninja_element, header_deps): for d in header_deps: @@ -2229,7 +2680,10 @@ def get_fortran_orderdeps(self, target, compiler): if compiler.language != 'fortran': return [] - return [os.path.join(self.get_target_dir(lt), lt.get_filename()) for lt in target.link_targets] + return [ + os.path.join(self.get_target_dir(lt), lt.get_filename()) + for lt in itertools.chain(target.link_targets, target.link_whole_targets) + ] def generate_msvc_pch_command(self, target, compiler, pch): header = pch[0] @@ -2274,9 +2728,8 @@ if not pch: continue if not has_path_sep(pch[0]) or not has_path_sep(pch[-1]): - msg = 'Precompiled header of {!r} must not be in the same ' \ - 'directory as source, please put it in a subdirectory.' \ - ''.format(target.get_basename()) + msg = f'Precompiled header of {target.get_basename()!r} must not be in the same ' \ + 'directory as source, please put it in a subdirectory.' raise InvalidArguments(msg) compiler = target.compilers[lang] if isinstance(compiler, VisualStudioLikeCompiler): @@ -2300,23 +2753,23 @@ self.add_build(elem) return pch_objects + def get_target_shsym_filename(self, target): + # Always name the .symbols file after the primary build output because it always exists + targetdir = self.get_target_private_dir(target) + return os.path.join(targetdir, target.get_filename() + '.symbols') + def generate_shsym(self, target): - target_name = target.get_filename() target_file = self.get_target_filename(target) - targetdir = self.get_target_private_dir(target) - symname = os.path.join(targetdir, target_name + '.symbols') + symname = self.get_target_shsym_filename(target) elem = NinjaBuildElement(self.all_outputs, symname, 'SHSYM', target_file) + # The library we will actually link to, which is an import library on Windows (not the DLL) + elem.add_item('IMPLIB', self.get_target_filename_for_linking(target)) if self.environment.is_cross_build(): elem.add_item('CROSS', '--cross-host=' + self.environment.machines[target.for_machine].system) self.add_build(elem) - def get_cross_stdlib_link_args(self, target, linker): - if isinstance(target, build.StaticLibrary) or \ - self.environment.machines.matches_build_machine(target.for_machine): - return [] - if not self.environment.properties.host.has_stdlib(linker.language): - return [] - return linker.get_no_stdlib_link_args() + def get_import_filename(self, target): + return os.path.join(self.get_target_dir(target), target.import_filename) def get_target_type_link_args(self, target, linker): commands = [] @@ -2328,30 +2781,30 @@ commands += linker.gen_export_dynamic_link_args(self.environment) # If implib, and that's significant on this platform (i.e. Windows using either GCC or Visual Studio) if target.import_filename: - commands += linker.gen_import_library_args(os.path.join(self.get_target_dir(target), target.import_filename)) + commands += linker.gen_import_library_args(self.get_import_filename(target)) if target.pie: commands += linker.get_pie_link_args() elif isinstance(target, build.SharedLibrary): if isinstance(target, build.SharedModule): - options = self.environment.coredata.base_options + options = self.environment.coredata.options commands += linker.get_std_shared_module_link_args(options) else: commands += linker.get_std_shared_lib_link_args() # All shared libraries are PIC commands += linker.get_pic_args() - # Add -Wl,-soname arguments on Linux, -install_name on OS X - commands += linker.get_soname_args( - self.environment, target.prefix, target.name, target.suffix, - target.soversion, target.darwin_versions, - isinstance(target, build.SharedModule)) + if not isinstance(target, build.SharedModule) or target.backwards_compat_want_soname: + # Add -Wl,-soname arguments on Linux, -install_name on OS X + commands += linker.get_soname_args( + self.environment, target.prefix, target.name, target.suffix, + target.soversion, target.darwin_versions) # This is only visited when building for Windows using either GCC or Visual Studio if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'): commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) # This is only visited when building for Windows using either GCC or Visual Studio if target.import_filename: - commands += linker.gen_import_library_args(os.path.join(self.get_target_dir(target), target.import_filename)) + commands += linker.gen_import_library_args(self.get_import_filename(target)) elif isinstance(target, build.StaticLibrary): - commands += linker.get_std_link_args() + commands += linker.get_std_link_args(not target.should_install()) else: raise RuntimeError('Unknown build target type.') return commands @@ -2362,15 +2815,37 @@ # If gui_app is significant on this platform, add the appropriate linker arguments. # Unfortunately this can't be done in get_target_type_link_args, because some misguided # libraries (such as SDL2) add -mwindows to their link flags. - commands += linker.get_gui_app_args(target.gui_app) + m = self.environment.machines[target.for_machine] + + if m.is_windows() or m.is_cygwin(): + if target.gui_app is not None: + commands += linker.get_gui_app_args(target.gui_app) + else: + commands += linker.get_win_subsystem_args(target.win_subsystem) return commands def get_link_whole_args(self, linker, target): - target_args = self.build_target_link_arguments(linker, target.link_whole_targets) - return linker.get_link_whole_for(target_args) if len(target_args) else [] + use_custom = False + if isinstance(linker, mixins.visualstudio.MSVCCompiler): + # Expand our object lists manually if we are on pre-Visual Studio 2015 Update 2 + # (incidentally, the "linker" here actually refers to cl.exe) + if mesonlib.version_compare(linker.version, '<19.00.23918'): + use_custom = True + + if use_custom: + objects_from_static_libs: T.List[ExtractedObjects] = [] + for dep in target.link_whole_targets: + l = dep.extract_all_objects(False) + objects_from_static_libs += self.determine_ext_objs(l, '') + objects_from_static_libs.extend(self.flatten_object_list(dep)) + + return objects_from_static_libs + else: + target_args = self.build_target_link_arguments(linker, target.link_whole_targets) + return linker.get_link_whole_for(target_args) if target_args else [] @lru_cache(maxsize=None) - def guess_library_absolute_path(self, linker, libname, search_dirs, patterns): + def guess_library_absolute_path(self, linker, libname, search_dirs, patterns) -> Path: for d in search_dirs: for p in patterns: trial = CCompiler._get_trials_from_pattern(p, d, libname) @@ -2427,10 +2902,10 @@ guessed_dependencies = [] # TODO The get_library_naming requirement currently excludes link targets that use d or fortran as their main linker - if hasattr(linker, 'get_library_naming'): - search_dirs = tuple(search_dirs) + tuple(linker.get_library_dirs(self.environment)) + try: static_patterns = linker.get_library_naming(self.environment, LibType.STATIC, strict=True) shared_patterns = linker.get_library_naming(self.environment, LibType.SHARED, strict=True) + search_dirs = tuple(search_dirs) + tuple(linker.get_library_dirs(self.environment)) for libname in libs: # be conservative and record most likely shared and static resolution, because we don't know exactly # which one the linker will prefer @@ -2442,12 +2917,31 @@ guessed_dependencies.append(staticlibs.resolve().as_posix()) if sharedlibs: guessed_dependencies.append(sharedlibs.resolve().as_posix()) + except (mesonlib.MesonException, AttributeError) as e: + if 'get_library_naming' not in str(e): + raise return guessed_dependencies + absolute_libs - def generate_link(self, target, outname, obj_list, linker, extra_args=None, stdlib_args=None): + def generate_prelink(self, target, obj_list): + assert isinstance(target, build.StaticLibrary) + prelink_name = os.path.join(self.get_target_private_dir(target), target.name + '-prelink.o') + elem = NinjaBuildElement(self.all_outputs, [prelink_name], 'CUSTOM_COMMAND', obj_list) + + prelinker = target.get_prelinker() + cmd = prelinker.exelist[:] + cmd += prelinker.get_prelink_args(prelink_name, obj_list) + + cmd = self.replace_paths(target, cmd) + elem.add_item('COMMAND', cmd) + elem.add_item('description', f'Prelinking {prelink_name}.') + self.add_build(elem) + return [prelink_name] + + def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T.Union['Compiler', 'StaticLinker'], extra_args=None, stdlib_args=None): extra_args = extra_args if extra_args is not None else [] stdlib_args = stdlib_args if stdlib_args is not None else [] + implicit_outs = [] if isinstance(target, build.StaticLibrary): linker_base = 'STATIC' else: @@ -2462,7 +2956,7 @@ # # Once all the linker options have been passed, we will start passing # libraries and library paths from internal and external sources. - commands = CompilerArgs(linker) + commands = linker.compiler_args() # First, the trivial ones that are impossible to override. # # Add linker args for linking this target derived from 'base' build @@ -2475,14 +2969,17 @@ linker, isinstance(target, build.SharedModule)) # Add -nostdlib if needed; can't be overridden - commands += self.get_cross_stdlib_link_args(target, linker) + commands += self.get_no_stdlib_link_args(target, linker) # Add things like /NOLOGO; usually can't be overridden commands += linker.get_linker_always_args() # Add buildtype linker args: optimization level, etc. - commands += linker.get_buildtype_linker_args(self.get_option_for_target('buildtype', target)) + commands += linker.get_buildtype_linker_args(self.get_option_for_target(OptionKey('buildtype'), target)) # Add /DEBUG and the pdb filename when using MSVC - if self.get_option_for_target('debug', target): + if self.get_option_for_target(OptionKey('debug'), target): commands += self.get_link_debugfile_args(linker, target, outname) + debugfile = self.get_link_debugfile_name(linker, target, outname) + if debugfile is not None: + implicit_outs += [debugfile] # Add link args specific to this BuildTarget type, such as soname args, # PIC, import library generation, etc. commands += self.get_target_type_link_args(target, linker) @@ -2503,6 +3000,26 @@ # Now we will add libraries and library paths from various sources + # Set runtime-paths so we can run executables without needing to set + # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows. + if has_path_sep(target.name): + # Target names really should not have slashes in them, but + # unfortunately we did not check for that and some downstream projects + # now have them. Once slashes are forbidden, remove this bit. + target_slashname_workaround_dir = os.path.join( + os.path.dirname(target.name), + self.get_target_dir(target)) + else: + target_slashname_workaround_dir = self.get_target_dir(target) + (rpath_args, target.rpath_dirs_to_remove) = ( + linker.build_rpath_args(self.environment, + self.environment.get_build_dir(), + target_slashname_workaround_dir, + self.determine_rpath_dirs(target), + target.build_rpath, + target.install_rpath)) + commands += rpath_args + # Add link args to link to all internal libraries (link_with:) and # internal dependencies needed by this target. if linker_base == 'STATIC': @@ -2538,47 +3055,34 @@ # to be after all internal and external libraries so that unresolved # symbols from those can be found here. This is needed when the # *_winlibs that we want to link to are static mingw64 libraries. - commands += linker.get_option_link_args(self.environment.coredata.compiler_options[target.for_machine]) + if isinstance(linker, Compiler): + # The static linker doesn't know what language it is building, so we + # don't know what option. Fortunately, it doesn't care to see the + # language-specific options either. + # + # We shouldn't check whether we are making a static library, because + # in the LTO case we do use a real compiler here. + commands += linker.get_option_link_args(self.environment.coredata.options) dep_targets = [] dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal)) - # Set runtime-paths so we can run executables without needing to set - # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows. - if has_path_sep(target.name): - # Target names really should not have slashes in them, but - # unfortunately we did not check for that and some downstream projects - # now have them. Once slashes are forbidden, remove this bit. - target_slashname_workaround_dir = os.path.join( - os.path.dirname(target.name), - self.get_target_dir(target)) - else: - target_slashname_workaround_dir = self.get_target_dir(target) - commands += linker.build_rpath_args(self.environment, - self.environment.get_build_dir(), - target_slashname_workaround_dir, - self.determine_rpath_dirs(target), - target.build_rpath, - target.install_rpath) # Add libraries generated by custom targets custom_target_libraries = self.get_custom_target_provided_libraries(target) commands += extra_args commands += custom_target_libraries commands += stdlib_args # Standard library arguments go last, because they never depend on anything. - # Convert from GCC-style link argument naming to the naming used by the - # current compiler. - commands = commands.to_native() dep_targets.extend([self.get_dependency_filename(t) for t in dependencies]) dep_targets.extend([self.get_dependency_filename(t) for t in target.link_depends]) - elem = NinjaBuildElement(self.all_outputs, outname, linker_rule, obj_list) + elem = NinjaBuildElement(self.all_outputs, outname, linker_rule, obj_list, implicit_outs=implicit_outs) elem.add_dep(dep_targets + custom_target_libraries) elem.add_item('LINK_ARGS', commands) return elem def get_dependency_filename(self, t): if isinstance(t, build.SharedLibrary): - return os.path.join(self.get_target_private_dir(t), t.get_filename() + '.symbols') + return self.get_target_shsym_filename(t) elif isinstance(t, mesonlib.File): if t.is_built: return t.relative_name() @@ -2602,12 +3106,12 @@ except OSError: mlog.debug("Library versioning disabled because we do not have symlink creation privileges.") - def generate_custom_target_clean(self, trees): + def generate_custom_target_clean(self, trees: T.List[str]) -> str: e = NinjaBuildElement(self.all_outputs, 'meson-clean-ctlist', 'CUSTOM_COMMAND', 'PHONY') d = CleanTrees(self.environment.get_build_dir(), trees) d_file = os.path.join(self.environment.get_scratch_dir(), 'cleantrees.dat') e.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'cleantrees', d_file]) - e.add_item('description', 'Cleaning custom target directories.') + e.add_item('description', 'Cleaning custom target directories') self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-clean-ctlist') @@ -2618,27 +3122,24 @@ def generate_gcov_clean(self): gcno_elem = NinjaBuildElement(self.all_outputs, 'meson-clean-gcno', 'CUSTOM_COMMAND', 'PHONY') - script_root = self.environment.get_script_dir() - clean_script = os.path.join(script_root, 'delwithsuffix.py') - gcno_elem.add_item('COMMAND', mesonlib.python_command + [clean_script, '.', 'gcno']) - gcno_elem.add_item('description', 'Deleting gcno files.') + gcno_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcno']) + gcno_elem.add_item('description', 'Deleting gcno files') self.add_build(gcno_elem) # Alias that runs the target defined above self.create_target_alias('meson-clean-gcno') gcda_elem = NinjaBuildElement(self.all_outputs, 'meson-clean-gcda', 'CUSTOM_COMMAND', 'PHONY') - script_root = self.environment.get_script_dir() - clean_script = os.path.join(script_root, 'delwithsuffix.py') - gcda_elem.add_item('COMMAND', mesonlib.python_command + [clean_script, '.', 'gcda']) - gcda_elem.add_item('description', 'Deleting gcda files.') + gcda_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcda']) + gcda_elem.add_item('description', 'Deleting gcda files') self.add_build(gcda_elem) # Alias that runs the target defined above self.create_target_alias('meson-clean-gcda') def get_user_option_args(self): cmds = [] - for (k, v) in self.environment.coredata.user_options.items(): - cmds.append('-D' + k + '=' + (v.value if isinstance(v.value, str) else str(v.value).lower())) + for (k, v) in self.environment.coredata.options.items(): + if k.is_project(): + cmds.append('-D' + str(k) + '=' + (v.value if isinstance(v.value, str) else str(v.value).lower())) # The order of these arguments must be the same between runs of Meson # to ensure reproducible output. The order we pass them shouldn't # affect behavior in any other way. @@ -2668,8 +3169,12 @@ # Alias that runs the target defined above self.create_target_alias('meson-scan-build') - def generate_clangtool(self, name): + def generate_clangtool(self, name, extra_arg=None): target_name = 'clang-' + name + extra_args = [] + if extra_arg: + target_name += f'-{extra_arg}' + extra_args.append(f'--{extra_arg}') if not os.path.exists(os.path.join(self.environment.source_dir, '.clang-' + name)) and \ not os.path.exists(os.path.join(self.environment.source_dir, '_clang-' + name)): return @@ -2678,7 +3183,8 @@ if ('', target_name) in self.build.run_target_names: return cmd = self.environment.get_build_command() + \ - ['--internal', 'clang' + name, self.environment.source_dir, self.environment.build_dir] + ['--internal', 'clang' + name, self.environment.source_dir, self.environment.build_dir] + \ + extra_args elem = NinjaBuildElement(self.all_outputs, 'meson-' + target_name, 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') @@ -2689,6 +3195,7 @@ if not environment.detect_clangformat(): return self.generate_clangtool('format') + self.generate_clangtool('format', 'check') def generate_clangtidy(self): import shutil @@ -2740,8 +3247,8 @@ self.add_build(elem) elem = NinjaBuildElement(self.all_outputs, 'meson-clean', 'CUSTOM_COMMAND', 'PHONY') - elem.add_item('COMMAND', [self.ninja_command, '-t', 'clean']) - elem.add_item('description', 'Cleaning.') + elem.add_item('COMMAND', self.ninja_command + ['-t', 'clean']) + elem.add_item('description', 'Cleaning') # Alias that runs the above-defined meson-clean target self.create_target_alias('meson-clean') @@ -2760,8 +3267,8 @@ if ctlist: elem.add_dep(self.generate_custom_target_clean(ctlist)) - if 'b_coverage' in self.environment.coredata.base_options and \ - self.environment.coredata.base_options['b_coverage'].value: + if OptionKey('b_coverage') in self.environment.coredata.options and \ + self.environment.coredata.options[OptionKey('b_coverage')].value: self.generate_gcov_clean() elem.add_dep('clean-gcda') elem.add_dep('clean-gcno') @@ -2779,7 +3286,7 @@ elem = NinjaBuildElement(self.all_outputs, deps, 'phony', '') self.add_build(elem) - def get_introspection_data(self, target_id, target): + def get_introspection_data(self, target_id: str, target: build.Target) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]: if target_id not in self.introspection_data or len(self.introspection_data[target_id]) == 0: return super().get_introspection_data(target_id, target) @@ -2788,12 +3295,6 @@ result += [i] return result -def load(build_dir): - filename = os.path.join(build_dir, 'meson-private', 'install.dat') - with open(filename, 'rb') as f: - obj = pickle.load(f) - return obj - def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compiler) -> T.List[str]: """ @@ -2823,7 +3324,9 @@ # included files incmatch = incre.match(line) if incmatch is not None: - incfile = srcdir / incmatch.group(1) + incfile = src.parent / incmatch.group(1) + # NOTE: src.parent is most general, in particular for CMake subproject with Fortran file + # having an `include 'foo.f'` statement. if incfile.suffix.lower()[1:] in compiler.file_suffixes: mod_files.extend(_scan_fortran_file_deps(incfile, srcdir, dirname, tdeps, compiler)) # modules @@ -2861,7 +3364,7 @@ parents = submodmatch.group(1).lower().split(':') assert len(parents) in (1, 2), ( 'submodule ancestry must be specified as' - ' ancestor:parent but Meson found {}'.format(parents)) + f' ancestor:parent but Meson found {parents}') ancestor_child = '_'.join(parents) if ancestor_child not in tdeps: diff -Nru meson-0.53.2/mesonbuild/backend/vs2010backend.py meson-0.61.2/mesonbuild/backend/vs2010backend.py --- meson-0.53.2/mesonbuild/backend/vs2010backend.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/vs2010backend.py 2021-12-26 16:24:25.000000000 +0000 @@ -14,10 +14,10 @@ import copy import os -import pickle import xml.dom.minidom import xml.etree.ElementTree as ET import uuid +import typing as T from pathlib import Path, PurePath from . import backends @@ -25,36 +25,48 @@ from .. import dependencies from .. import mlog from .. import compilers -from ..compilers import CompilerArgs +from ..interpreter import Interpreter from ..mesonlib import ( - MesonException, File, python_command, replace_if_different + File, MesonException, replace_if_different, OptionKey, version_compare, MachineChoice ) from ..environment import Environment, build_filename -def autodetect_vs_version(build): + +def autodetect_vs_version(build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]) -> backends.Backend: vs_version = os.getenv('VisualStudioVersion', None) vs_install_dir = os.getenv('VSINSTALLDIR', None) if not vs_install_dir: raise MesonException('Could not detect Visual Studio: Environment variable VSINSTALLDIR is not set!\n' 'Are you running meson from the Visual Studio Developer Command Prompt?') - # VisualStudioVersion is set since Visual Studio 12.0, but sometimes + # VisualStudioVersion is set since Visual Studio 11.0, but sometimes # vcvarsall.bat doesn't set it, so also use VSINSTALLDIR + if vs_version == '11.0' or 'Visual Studio 11' in vs_install_dir: + from mesonbuild.backend.vs2012backend import Vs2012Backend + return Vs2012Backend(build, interpreter) + if vs_version == '12.0' or 'Visual Studio 12' in vs_install_dir: + from mesonbuild.backend.vs2013backend import Vs2013Backend + return Vs2013Backend(build, interpreter) if vs_version == '14.0' or 'Visual Studio 14' in vs_install_dir: from mesonbuild.backend.vs2015backend import Vs2015Backend - return Vs2015Backend(build) + return Vs2015Backend(build, interpreter) if vs_version == '15.0' or 'Visual Studio 17' in vs_install_dir or \ 'Visual Studio\\2017' in vs_install_dir: from mesonbuild.backend.vs2017backend import Vs2017Backend - return Vs2017Backend(build) + return Vs2017Backend(build, interpreter) if vs_version == '16.0' or 'Visual Studio 19' in vs_install_dir or \ 'Visual Studio\\2019' in vs_install_dir: from mesonbuild.backend.vs2019backend import Vs2019Backend - return Vs2019Backend(build) + return Vs2019Backend(build, interpreter) + if vs_version == '17.0' or 'Visual Studio 22' in vs_install_dir or \ + 'Visual Studio\\2022' in vs_install_dir: + from mesonbuild.backend.vs2022backend import Vs2022Backend + return Vs2022Backend(build, interpreter) if 'Visual Studio 10.0' in vs_install_dir: - return Vs2010Backend(build) + return Vs2010Backend(build, interpreter) raise MesonException('Could not detect Visual Studio using VisualStudioVersion: {!r} or VSINSTALLDIR: {!r}!\n' 'Please specify the exact backend to use.'.format(vs_version, vs_install_dir)) + def split_o_flags_args(args): """ Splits any /O args and returns them. Does not take care of flags overriding @@ -76,26 +88,27 @@ o_flags += ['/O' + f for f in flags] return o_flags + def generate_guid_from_path(path, path_type): return str(uuid.uuid5(uuid.NAMESPACE_URL, 'meson-vs-' + path_type + ':' + str(path))).upper() -class RegenInfo: - def __init__(self, source_dir, build_dir, depfiles): - self.source_dir = source_dir - self.build_dir = build_dir - self.depfiles = depfiles class Vs2010Backend(backends.Backend): - def __init__(self, build): - super().__init__(build) + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) self.name = 'vs2010' self.project_file_version = '10.0.30319.1' + self.sln_file_version = '11.00' + self.sln_version_comment = '2010' self.platform_toolset = None self.vs_version = '2010' self.windows_target_platform_version = None self.subdirs = {} self.handled_target_deps = {} + def get_target_private_dir(self, target): + return os.path.join(self.get_target_dir(target), target.get_id()) + def generate_custom_generator_commands(self, target, parent_node): generator_output_files = [] custom_target_include_dirs = [] @@ -117,14 +130,13 @@ infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() source_dir = os.path.join(down, self.build_to_src, genlist.subdir) - exe_arr = self.exe_object_to_cmd_array(exe) + exe_arr = self.build_target_to_cmd_array(exe) idgroup = ET.SubElement(parent_node, 'ItemGroup') - for i in range(len(infilelist)): + for i, curfile in enumerate(infilelist): if len(infilelist) == len(outfilelist): sole_output = os.path.join(target_private_dir, outfilelist[i]) else: sole_output = '' - curfile = infilelist[i] infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src)) deps = self.get_custom_target_depend_files(genlist, True) base_args = generator.get_arglist(infilename) @@ -146,8 +158,7 @@ # Always use a wrapper because MSBuild eats random characters when # there are many arguments. tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) - cmd = self.as_meson_exe_cmdline( - 'generator ' + cmd[0], + cmd, _ = self.as_meson_exe_cmdline( cmd[0], cmd[1:], workdir=tdir_abs, @@ -163,20 +174,50 @@ ET.SubElement(cbs, 'AdditionalInputs').text = ';'.join(deps) return generator_output_files, custom_target_output_files, custom_target_include_dirs - def generate(self, interp): - self.interpreter = interp + def generate(self): target_machine = self.interpreter.builtin['target_machine'].cpu_family_method(None, None) - if target_machine.endswith('64'): + if target_machine == '64' or target_machine == 'x86_64': # amd64 or x86_64 self.platform = 'x64' elif target_machine == 'x86': # x86 self.platform = 'Win32' + elif target_machine == 'aarch64' or target_machine == 'arm64': + target_cpu = self.interpreter.builtin['target_machine'].cpu_method(None, None) + if target_cpu == 'arm64ec': + self.platform = 'arm64ec' + else: + self.platform = 'arm64' elif 'arm' in target_machine.lower(): self.platform = 'ARM' else: raise MesonException('Unsupported Visual Studio platform: ' + target_machine) - self.buildtype = self.environment.coredata.get_builtin_option('buildtype') + + build_machine = self.interpreter.builtin['build_machine'].cpu_family_method(None, None) + if build_machine == '64' or build_machine == 'x86_64': + # amd64 or x86_64 + self.build_platform = 'x64' + elif build_machine == 'x86': + # x86 + self.build_platform = 'Win32' + elif build_machine == 'aarch64' or build_machine == 'arm64': + target_cpu = self.interpreter.builtin['build_machine'].cpu_method(None, None) + if target_cpu == 'arm64ec': + self.build_platform = 'arm64ec' + else: + self.build_platform = 'arm64' + elif 'arm' in build_machine.lower(): + self.build_platform = 'ARM' + else: + raise MesonException('Unsupported Visual Studio platform: ' + build_machine) + + self.buildtype = self.environment.coredata.get_option(OptionKey('buildtype')) + self.optimization = self.environment.coredata.get_option(OptionKey('optimization')) + self.debug = self.environment.coredata.get_option(OptionKey('debug')) + try: + self.sanitize = self.environment.coredata.get_option(OptionKey('b_sanitize')) + except MesonException: + self.sanitize = 'none' sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln') projlist = self.generate_projects() self.gen_testproj('RUN_TESTS', os.path.join(self.environment.get_build_dir(), 'RUN_TESTS.vcxproj')) @@ -187,24 +228,14 @@ Vs2010Backend.touch_regen_timestamp(self.environment.get_build_dir()) @staticmethod - def get_regen_stampfile(build_dir): + def get_regen_stampfile(build_dir: str) -> None: return os.path.join(os.path.join(build_dir, Environment.private_dir), 'regen.stamp') @staticmethod - def touch_regen_timestamp(build_dir): - with open(Vs2010Backend.get_regen_stampfile(build_dir), 'w'): + def touch_regen_timestamp(build_dir: str) -> None: + with open(Vs2010Backend.get_regen_stampfile(build_dir), 'w', encoding='utf-8'): pass - def generate_regen_info(self): - deps = self.get_regen_filelist() - regeninfo = RegenInfo(self.environment.get_source_dir(), - self.environment.get_build_dir(), - deps) - filename = os.path.join(self.environment.get_scratch_dir(), - 'regeninfo.dump') - with open(filename, 'wb') as f: - pickle.dump(regeninfo, f) - def get_vcvars_command(self): has_arch_values = 'VSCMD_ARG_TGT_ARCH' in os.environ and 'VSCMD_ARG_HOST_ARCH' in os.environ @@ -212,7 +243,7 @@ if 'VCINSTALLDIR' in os.environ: vs_version = os.environ['VisualStudioVersion'] \ if 'VisualStudioVersion' in os.environ else None - relative_path = 'Auxiliary\\Build\\' if vs_version >= '15.0' else '' + relative_path = 'Auxiliary\\Build\\' if vs_version is not None and vs_version >= '15.0' else '' script_path = os.environ['VCINSTALLDIR'] + relative_path + 'vcvarsall.bat' if os.path.exists(script_path): if has_arch_values: @@ -222,7 +253,7 @@ target_arch = os.environ.get('Platform', 'x86') host_arch = target_arch arch = host_arch + '_' + target_arch if host_arch != target_arch else target_arch - return '"%s" %s' % (script_path, arch) + return f'"{script_path}" {arch}' # Otherwise try the VS2017 Developer Command Prompt. if 'VS150COMNTOOLS' in os.environ and has_arch_values: @@ -246,9 +277,8 @@ for d in target.get_target_dependencies(): all_deps[d.get_id()] = d elif isinstance(target, build.RunTarget): - for d in [target.command] + target.args: - if isinstance(d, (build.BuildTarget, build.CustomTarget)): - all_deps[d.get_id()] = d + for d in target.get_dependencies(): + all_deps[d.get_id()] = d elif isinstance(target, build.BuildTarget): for ldep in target.link_targets: if isinstance(ldep, build.CustomTargetIndex): @@ -260,19 +290,37 @@ all_deps[ldep.get_id()] = ldep.target else: all_deps[ldep.get_id()] = ldep + + for ldep in target.link_depends: + if isinstance(ldep, build.CustomTargetIndex): + all_deps[ldep.get_id()] = ldep.target + elif isinstance(ldep, File): + # Already built, no target references needed + pass + else: + all_deps[ldep.get_id()] = ldep + for obj_id, objdep in self.get_obj_target_deps(target.objects): all_deps[obj_id] = objdep - for gendep in target.get_generated_sources(): - if isinstance(gendep, build.CustomTarget): - all_deps[gendep.get_id()] = gendep - elif isinstance(gendep, build.CustomTargetIndex): - all_deps[gendep.target.get_id()] = gendep.target - else: - gen_exe = gendep.generator.get_exe() - if isinstance(gen_exe, build.Executable): - all_deps[gen_exe.get_id()] = gen_exe else: - raise MesonException('Unknown target type for target %s' % target) + raise MesonException(f'Unknown target type for target {target}') + + for gendep in target.get_generated_sources(): + if isinstance(gendep, build.CustomTarget): + all_deps[gendep.get_id()] = gendep + elif isinstance(gendep, build.CustomTargetIndex): + all_deps[gendep.target.get_id()] = gendep.target + else: + generator = gendep.get_generator() + gen_exe = generator.get_exe() + if isinstance(gen_exe, build.Executable): + all_deps[gen_exe.get_id()] = gen_exe + for d in generator.depends: + if isinstance(d, build.CustomTargetIndex): + all_deps[d.get_id()] = d.target + else: + all_deps[d.get_id()] = d + if not t or not recursive: return all_deps ret = self.get_target_deps(all_deps, recursive) @@ -302,14 +350,15 @@ def generate_solution(self, sln_filename, projlist): default_projlist = self.get_build_by_default_targets() sln_filename_tmp = sln_filename + '~' - with open(sln_filename_tmp, 'w', encoding='utf-8') as ofile: - ofile.write('Microsoft Visual Studio Solution File, Format ' - 'Version 11.00\n') - ofile.write('# Visual Studio ' + self.vs_version + '\n') + # Note using the utf-8 BOM requires the blank line, otherwise Visual Studio Version Selector fails. + # Without the BOM, VSVS fails if there is a blank line. + with open(sln_filename_tmp, 'w', encoding='utf-8-sig') as ofile: + ofile.write('\nMicrosoft Visual Studio Solution File, Format Version %s\n' % self.sln_file_version) + ofile.write('# Visual Studio %s\n' % self.sln_version_comment) prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n' for prj in projlist: coredata = self.environment.coredata - if coredata.get_builtin_option('layout') == 'mirror': + if coredata.get_option(OptionKey('layout')) == 'mirror': self.generate_solution_dirs(ofile, prj[1].parents) target = self.build.targets[prj[0]] lang = 'default' @@ -362,16 +411,20 @@ self.platform, self.buildtype, self.platform)) # Create the solution configuration for p in projlist: + if p[3] is MachineChoice.BUILD: + config_platform = self.build_platform + else: + config_platform = self.platform # Add to the list of projects in this solution ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % (p[2], self.buildtype, self.platform, - self.buildtype, self.platform)) + self.buildtype, config_platform)) if p[0] in default_projlist and \ not isinstance(self.build.targets[p[0]], build.RunTarget): # Add to the list of projects to be built ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % (p[2], self.buildtype, self.platform, - self.buildtype, self.platform)) + self.buildtype, config_platform)) ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % (self.environment.coredata.test_guid, self.buildtype, self.platform, self.buildtype, self.platform)) @@ -387,16 +440,16 @@ 'preSolution\n') for p in projlist: if p[1].parent != PurePath('.'): - ofile.write("\t\t{%s} = {%s}\n" % (p[2], self.subdirs[p[1].parent][0])) + ofile.write("\t\t{{{}}} = {{{}}}\n".format(p[2], self.subdirs[p[1].parent][0])) for subdir in self.subdirs.values(): if subdir[1]: - ofile.write("\t\t{%s} = {%s}\n" % (subdir[0], subdir[1])) + ofile.write("\t\t{{{}}} = {{{}}}\n".format(subdir[0], subdir[1])) ofile.write('\tEndGlobalSection\n') ofile.write('EndGlobal\n') replace_if_different(sln_filename, sln_filename_tmp) def generate_projects(self): - startup_project = self.environment.coredata.backend_options['backend_startup_project'].value + startup_project = self.environment.coredata.options[OptionKey('backend_startup_project')].value projlist = [] startup_idx = 0 for (i, (name, target)) in enumerate(self.build.targets.items()): @@ -413,11 +466,11 @@ projfile_path = outdir / fname proj_uuid = self.environment.coredata.target_guids[name] self.gen_vcxproj(target, str(projfile_path), proj_uuid) - projlist.append((name, relname, proj_uuid)) + projlist.append((name, relname, proj_uuid, target.for_machine)) # Put the startup project first in the project list if startup_idx: - projlist = [projlist[startup_idx]] + projlist[0:startup_idx] + projlist[startup_idx + 1:-1] + projlist.insert(0, projlist.pop(startup_idx)) return projlist @@ -474,83 +527,114 @@ tid = self.environment.coredata.target_guids[dep.get_id()] self.add_project_reference(root, vcxproj, tid) - def create_basic_crap(self, target, guid): - project_name = target.name + def create_basic_project(self, target_name, *, + temp_dir, + guid, + conftype='Utility', + target_ext=None, + target_platform=None): root = ET.Element('Project', {'DefaultTargets': "Build", 'ToolsVersion': '4.0', 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) + confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) + if not target_platform: + target_platform = self.platform prjconf = ET.SubElement(confitems, 'ProjectConfiguration', - {'Include': self.buildtype + '|' + self.platform}) + {'Include': self.buildtype + '|' + target_platform}) p = ET.SubElement(prjconf, 'Configuration') p.text = self.buildtype pl = ET.SubElement(prjconf, 'Platform') - pl.text = self.platform + pl.text = target_platform + + # Globals globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') guidelem = ET.SubElement(globalgroup, 'ProjectGuid') guidelem.text = '{%s}' % guid kw = ET.SubElement(globalgroup, 'Keyword') kw.text = self.platform + 'Proj' + # XXX Wasn't here before for anything but gen_vcxproj , but seems fine? + ns = ET.SubElement(globalgroup, 'RootNamespace') + ns.text = target_name + p = ET.SubElement(globalgroup, 'Platform') - p.text = self.platform + p.text = target_platform pname = ET.SubElement(globalgroup, 'ProjectName') - pname.text = project_name + pname.text = target_name if self.windows_target_platform_version: ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version + ET.SubElement(globalgroup, 'UseMultiToolTask').text = 'true' + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.Default.props') + + # Start configuration type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') - ET.SubElement(type_config, 'ConfigurationType') + ET.SubElement(type_config, 'ConfigurationType').text = conftype ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' + # Fixme: wasn't here before for gen_vcxproj() ET.SubElement(type_config, 'UseOfMfc').text = 'false' if self.platform_toolset: ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset + + # End configuration section (but it can be added to further via type_config) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.props') + + # Project information direlem = ET.SubElement(root, 'PropertyGroup') fver = ET.SubElement(direlem, '_ProjectFileVersion') fver.text = self.project_file_version outdir = ET.SubElement(direlem, 'OutDir') outdir.text = '.\\' intdir = ET.SubElement(direlem, 'IntDir') - intdir.text = target.get_id() + '\\' + intdir.text = temp_dir + '\\' + tname = ET.SubElement(direlem, 'TargetName') - tname.text = target.name - return root + tname.text = target_name + + if target_ext: + ET.SubElement(direlem, 'TargetExt').text = target_ext + + return (root, type_config) def gen_run_target_vcxproj(self, target, ofname, guid): - root = self.create_basic_crap(target, guid) + (root, type_config) = self.create_basic_project(target.name, + temp_dir=target.get_id(), + guid=guid) + depend_files = self.get_custom_target_depend_files(target) + if not target.command: - # FIXME: This is an alias target that doesn't run any command, there - # is probably a better way than running a this dummy command. - cmd_raw = python_command + ['-c', 'exit'] + # This is an alias target and thus doesn't run any command. It's + # enough to emit the references to the other projects for them to + # be built/run/..., if necessary. + assert isinstance(target, build.AliasTarget) + assert len(depend_files) == 0 else: - cmd_raw = [target.command] + target.args - cmd = python_command + \ - [os.path.join(self.environment.get_script_dir(), 'commandrunner.py'), - self.environment.get_source_dir(), - self.environment.get_build_dir(), - self.get_target_dir(target)] + self.environment.get_build_command() - for i in cmd_raw: - if isinstance(i, build.BuildTarget): - cmd.append(os.path.join(self.environment.get_build_dir(), self.get_target_filename(i))) - elif isinstance(i, dependencies.ExternalProgram): - cmd += i.get_command() - elif isinstance(i, File): - relfname = i.rel_to_builddir(self.build_to_src) - cmd.append(os.path.join(self.environment.get_build_dir(), relfname)) - elif isinstance(i, str): - # Escape embedded quotes, because we quote the entire argument below. - cmd.append(i.replace('"', '\\"')) - else: - cmd.append(i) - cmd_templ = '''"%s" ''' * len(cmd) - self.add_custom_build(root, 'run_target', cmd_templ % tuple(cmd)) + assert not isinstance(target, build.AliasTarget) + + target_env = self.get_run_target_env(target) + _, _, cmd_raw = self.eval_custom_target_command(target) + wrapper_cmd, _ = self.as_meson_exe_cmdline(target.command[0], cmd_raw[1:], + force_serialize=True, env=target_env, + verbose=True) + self.add_custom_build(root, 'run_target', ' '.join(self.quote_arguments(wrapper_cmd)), + deps=depend_files) + + # The import is needed even for alias targets, otherwise the build + # target isn't defined ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') self.add_regen_dependency(root) self.add_target_deps(root, target) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_custom_target_vcxproj(self, target, ofname, guid): - root = self.create_basic_crap(target, guid) + if target.for_machine is MachineChoice.BUILD: + platform = self.build_platform + else: + platform = self.platform + (root, type_config) = self.create_basic_project(target.name, + temp_dir=target.get_id(), + guid=guid, + target_platform=platform) # We need to always use absolute paths because our invocation is always # from the target dir, not the build root. target.absolute_paths = True @@ -560,18 +644,21 @@ # there are many arguments. tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) extra_bdeps = target.get_transitive_build_target_deps() - wrapper_cmd = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:], - # All targets run from the target dir - workdir=tdir_abs, - extra_bdeps=extra_bdeps, - capture=ofilenames[0] if target.capture else None, - force_serialize=True) + wrapper_cmd, _ = self.as_meson_exe_cmdline(target.command[0], cmd[1:], + # All targets run from the target dir + workdir=tdir_abs, + extra_bdeps=extra_bdeps, + capture=ofilenames[0] if target.capture else None, + feed=srcs[0] if target.feed else None, + force_serialize=True, + env=target.env) if target.build_always_stale: # Use a nonexistent file to always consider the target out-of-date. ofilenames += [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(), 'outofdate.file'))] self.add_custom_build(root, 'custom_target', ' '.join(self.quote_arguments(wrapper_cmd)), - deps=wrapper_cmd[-1:] + srcs + depend_files, outputs=ofilenames) + deps=wrapper_cmd[-1:] + srcs + depend_files, outputs=ofilenames, + verify_files=not target.build_always_stale) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') self.generate_custom_generator_commands(target, root) self.add_regen_dependency(root) @@ -585,13 +672,11 @@ return 'c' if ext in compilers.cpp_suffixes: return 'cpp' - raise MesonException('Could not guess language from source file %s.' % src) + raise MesonException(f'Could not guess language from source file {src}.') def add_pch(self, pch_sources, lang, inc_cl): - if len(pch_sources) <= 1: - # We only need per file precompiled headers if we have more than 1 language. - return - self.use_pch(pch_sources, lang, inc_cl) + if lang in pch_sources: + self.use_pch(pch_sources, lang, inc_cl) def create_pch(self, pch_sources, lang, inc_cl): pch = ET.SubElement(inc_cl, 'PrecompiledHeader') @@ -599,6 +684,8 @@ self.add_pch_files(pch_sources, lang, inc_cl) def use_pch(self, pch_sources, lang, inc_cl): + pch = ET.SubElement(inc_cl, 'PrecompiledHeader') + pch.text = 'Use' header = self.add_pch_files(pch_sources, lang, inc_cl) pch_include = ET.SubElement(inc_cl, 'ForcedIncludeFiles') pch_include.text = header + ';%(ForcedIncludeFiles)' @@ -616,13 +703,22 @@ # or be in the same directory as the PCH implementation. pch_file.text = header pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile') - pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % lang + pch_out.text = f'$(IntDir)$(TargetName)-{lang}.pch' + + # Need to set the name for the pdb, as cl otherwise gives it a static + # name. Which leads to problems when there is more than one pch + # (e.g. for different languages). + pch_pdb = ET.SubElement(inc_cl, 'ProgramDataBaseFileName') + pch_pdb.text = f'$(IntDir)$(TargetName)-{lang}.pdb' + return header def is_argument_with_msbuild_xml_entry(self, entry): # Remove arguments that have a top level XML entry so # they are not used twice. # FIXME add args as needed. + if entry[1:].startswith('fsanitize'): + return True return entry[1:].startswith('M') def add_additional_options(self, lang, parent_node, file_args): @@ -684,7 +780,7 @@ # kidding, this is how escaping works for process args on Windows. if option.endswith('\\'): option += '\\' - return '"{}"'.format(option) + return f'"{option}"' @staticmethod def split_link_args(args): @@ -742,26 +838,28 @@ replace_if_different(ofname, ofname_tmp) def gen_vcxproj(self, target, ofname, guid): - mlog.debug('Generating vcxproj %s.' % target.name) - entrypoint = 'WinMainCRTStartup' + mlog.debug(f'Generating vcxproj {target.name}.') subsystem = 'Windows' self.handled_target_deps[target.get_id()] = [] if isinstance(target, build.Executable): conftype = 'Application' - if not target.gui_app: - subsystem = 'Console' - entrypoint = 'mainCRTStartup' + if target.gui_app is not None: + if not target.gui_app: + subsystem = 'Console' + else: + # If someone knows how to set the version properly, + # please send a patch. + subsystem = target.win_subsystem.split(',')[0] elif isinstance(target, build.StaticLibrary): conftype = 'StaticLibrary' elif isinstance(target, build.SharedLibrary): conftype = 'DynamicLibrary' - entrypoint = '_DllMainCrtStartup' elif isinstance(target, build.CustomTarget): return self.gen_custom_target_vcxproj(target, ofname, guid) elif isinstance(target, build.RunTarget): return self.gen_run_target_vcxproj(target, ofname, guid) else: - raise MesonException('Unknown target type for %s' % target.get_basename()) + raise MesonException(f'Unknown target type for {target.get_basename()}') # Prefix to use to access the build root from the vcxproj dir down = self.target_to_build_root(target) # Prefix to use to access the source tree's root from the vcxproj dir @@ -772,42 +870,30 @@ if self.is_unity(target): sources = self.generate_unity_files(target, sources) compiler = self._get_cl_compiler(target) - buildtype_args = compiler.get_buildtype_args(self.buildtype) + build_args = compiler.get_buildtype_args(self.buildtype) + build_args += compiler.get_optimization_args(self.optimization) + build_args += compiler.get_debug_args(self.debug) + build_args += compiler.sanitizer_compile_args(self.sanitize) buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype) - vscrt_type = self.environment.coredata.base_options['b_vscrt'] - project_name = target.name + vscrt_type = self.environment.coredata.options[OptionKey('b_vscrt')] target_name = target.name - root = ET.Element('Project', {'DefaultTargets': "Build", - 'ToolsVersion': '4.0', - 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) - confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) - prjconf = ET.SubElement(confitems, 'ProjectConfiguration', - {'Include': self.buildtype + '|' + self.platform}) - p = ET.SubElement(prjconf, 'Configuration') - p.text = self.buildtype - pl = ET.SubElement(prjconf, 'Platform') - pl.text = self.platform - # Globals - globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') - guidelem = ET.SubElement(globalgroup, 'ProjectGuid') - guidelem.text = '{%s}' % guid - kw = ET.SubElement(globalgroup, 'Keyword') - kw.text = self.platform + 'Proj' - ns = ET.SubElement(globalgroup, 'RootNamespace') - ns.text = target_name - p = ET.SubElement(globalgroup, 'Platform') - p.text = self.platform - pname = ET.SubElement(globalgroup, 'ProjectName') - pname.text = project_name - if self.windows_target_platform_version: - ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version - ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.Default.props') - # Start configuration - type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') - ET.SubElement(type_config, 'ConfigurationType').text = conftype - ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' - if self.platform_toolset: - ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset + if target.for_machine is MachineChoice.BUILD: + platform = self.build_platform + else: + platform = self.platform + + tfilename = os.path.splitext(target.get_filename()) + + (root, type_config) = self.create_basic_project(tfilename[0], + temp_dir=target.get_id(), + guid=guid, + conftype=conftype, + target_ext=tfilename[1], + target_platform=platform) + + # FIXME: Should these just be set in create_basic_project(), even if + # irrelevant for current target? + # FIXME: Meson's LTO support needs to be integrated here ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false' # Let VS auto-set the RTC level @@ -821,11 +907,18 @@ clconf = ET.SubElement(compiles, 'ClCompile') # CRT type; debug or release if vscrt_type.value == 'from_buildtype': - if self.buildtype == 'debug' or self.buildtype == 'debugoptimized': + if self.buildtype == 'debug': ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL' else: ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDLL' + elif vscrt_type.value == 'static_from_buildtype': + if self.buildtype == 'debug': + ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebug' + else: + ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded' elif vscrt_type.value == 'mdd': ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' @@ -841,39 +934,44 @@ else: ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDLL' + # Sanitizers + if '/fsanitize=address' in build_args: + ET.SubElement(type_config, 'EnableASAN').text = 'true' # Debug format - if '/ZI' in buildtype_args: - ET.SubElement(type_config, 'DebugInformationFormat').text = 'EditAndContinue' - elif '/Zi' in buildtype_args: - ET.SubElement(type_config, 'DebugInformationFormat').text = 'ProgramDatabase' - elif '/Z7' in buildtype_args: - ET.SubElement(type_config, 'DebugInformationFormat').text = 'OldStyle' + if '/ZI' in build_args: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'EditAndContinue' + elif '/Zi' in build_args: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'ProgramDatabase' + elif '/Z7' in build_args: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'OldStyle' + else: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'None' # Runtime checks - if '/RTC1' in buildtype_args: - ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'EnableFastChecks' - elif '/RTCu' in buildtype_args: - ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'UninitializedLocalUsageCheck' - elif '/RTCs' in buildtype_args: - ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'StackFrameRuntimeCheck' - # End configuration - ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.props') - generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands(target, root) + if '/RTC1' in build_args: + ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'EnableFastChecks' + elif '/RTCu' in build_args: + ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'UninitializedLocalUsageCheck' + elif '/RTCs' in build_args: + ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'StackFrameRuntimeCheck' + # Exception handling has to be set in the xml in addition to the "AdditionalOptions" because otherwise + # cl will give warning D9025: overriding '/Ehs' with cpp_eh value + if 'cpp' in target.compilers: + eh = self.environment.coredata.options[OptionKey('eh', machine=target.for_machine, lang='cpp')] + if eh.value == 'a': + ET.SubElement(clconf, 'ExceptionHandling').text = 'Async' + elif eh.value == 's': + ET.SubElement(clconf, 'ExceptionHandling').text = 'SyncCThrow' + elif eh.value == 'none': + ET.SubElement(clconf, 'ExceptionHandling').text = 'false' + else: # 'sc' or 'default' + ET.SubElement(clconf, 'ExceptionHandling').text = 'Sync' + generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands( + target, root) (gen_src, gen_hdrs, gen_objs, gen_langs) = self.split_sources(generated_files) (custom_src, custom_hdrs, custom_objs, custom_langs) = self.split_sources(custom_target_output_files) gen_src += custom_src gen_hdrs += custom_hdrs gen_langs += custom_langs - # Project information - direlem = ET.SubElement(root, 'PropertyGroup') - fver = ET.SubElement(direlem, '_ProjectFileVersion') - fver.text = self.project_file_version - outdir = ET.SubElement(direlem, 'OutDir') - outdir.text = '.\\' - intdir = ET.SubElement(direlem, 'IntDir') - intdir.text = target.get_id() + '\\' - tfilename = os.path.splitext(target.get_filename()) - ET.SubElement(direlem, 'TargetName').text = tfilename[0] - ET.SubElement(direlem, 'TargetExt').text = tfilename[1] # Arguments, include dirs, defines for all files in the current target target_args = [] @@ -884,15 +982,17 @@ # # file_args is also later split out into defines and include_dirs in # case someone passed those in there - file_args = dict((lang, CompilerArgs(comp)) for lang, comp in target.compilers.items()) - file_defines = dict((lang, []) for lang in target.compilers) - file_inc_dirs = dict((lang, []) for lang in target.compilers) + file_args = {l: c.compiler_args() for l, c in target.compilers.items()} + file_defines = {l: [] for l in target.compilers} + file_inc_dirs = {l: [] for l in target.compilers} # The order in which these compile args are added must match # generate_single_compile() and generate_basic_compiler_args() for l, comp in target.compilers.items(): if l in file_args: - file_args[l] += compilers.get_base_compile_args(self.get_base_options_for_target(target), comp) - file_args[l] += comp.get_option_compile_args(self.environment.coredata.compiler_options[target.for_machine]) + file_args[l] += compilers.get_base_compile_args( + self.get_base_options_for_target(target), comp) + file_args[l] += comp.get_option_compile_args( + self.environment.coredata.options) # Add compile args added using add_project_arguments() for l, args in self.build.projects_args[target.for_machine].get(target.subproject, {}).items(): @@ -905,10 +1005,9 @@ file_args[l] += args # Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these # to override all the defaults, but not the per-target compile args. - for key, opt in self.environment.coredata.compiler_options[target.for_machine].items(): - l, suffix = key.split('_', 1) - if suffix == 'args' and l in file_args: - file_args[l] += opt.value + for l in file_args.keys(): + opts = self.environment.coredata.options[OptionKey('args', machine=target.for_machine, lang=l)] + file_args[l] += opts.value for args in file_args.values(): # This is where Visual Studio will insert target_args, target_defines, # etc, which are added later from external deps (see below). @@ -933,8 +1032,8 @@ # reversed is used to keep order of includes for i in reversed(d.get_incdirs()): curdir = os.path.join(d.get_curdir(), i) - args.append('-I' + self.relpath(curdir, target.subdir)) # build dir - args.append('-I' + os.path.join(proj_to_src_root, curdir)) # src dir + args.append('-I' + self.relpath(curdir, target.subdir)) # build dir + args.append('-I' + os.path.join(proj_to_src_root, curdir)) # src dir for i in d.get_extra_build_dirs(): curdir = os.path.join(d.get_curdir(), i) args.append('-I' + self.relpath(curdir, target.subdir)) # build dir @@ -949,9 +1048,7 @@ t_inc_dirs = [self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))] if target.implicit_include_directories: - t_inc_dirs += ['.'] - if target.implicit_include_directories: - t_inc_dirs += [proj_to_src_dir] + t_inc_dirs += ['.', proj_to_src_dir] args += ['-I' + arg for arg in t_inc_dirs] # Split preprocessor defines and include directories out of the list of @@ -966,9 +1063,8 @@ else: define = arg[2:] # De-dup - if define in file_defines[l]: - file_defines[l].remove(define) - file_defines[l].append(define) + if define not in file_defines[l]: + file_defines[l].append(define) elif arg.startswith(('-I', '/I')) or arg == '%(AdditionalIncludeDirectories)': file_args[l].remove(arg) # Don't escape the marker @@ -979,6 +1075,9 @@ # De-dup if inc_dir not in file_inc_dirs[l]: file_inc_dirs[l].append(inc_dir) + # Add include dirs to target as well so that "Go to Document" works in headers + if inc_dir not in target_inc_dirs: + target_inc_dirs.append(inc_dir) # Split compile args needed to find external dependencies # Link args are added while generating the link command @@ -986,41 +1085,41 @@ # Cflags required by external deps might have UNIX-specific flags, # so filter them out if needed if isinstance(d, dependencies.OpenMPDependency): - d_compile_args = compiler.openmp_flags() + ET.SubElement(clconf, 'OpenMPSupport').text = 'true' else: d_compile_args = compiler.unix_args_to_native(d.get_compile_args()) - for arg in d_compile_args: - if arg.startswith(('-D', '/D')): - define = arg[2:] - # De-dup - if define in target_defines: - target_defines.remove(define) - target_defines.append(define) - elif arg.startswith(('-I', '/I')): - inc_dir = arg[2:] - # De-dup - if inc_dir not in target_inc_dirs: - target_inc_dirs.append(inc_dir) - else: - target_args.append(arg) + for arg in d_compile_args: + if arg.startswith(('-D', '/D')): + define = arg[2:] + # De-dup + if define in target_defines: + target_defines.remove(define) + target_defines.append(define) + elif arg.startswith(('-I', '/I')): + inc_dir = arg[2:] + # De-dup + if inc_dir not in target_inc_dirs: + target_inc_dirs.append(inc_dir) + else: + target_args.append(arg) languages += gen_langs + if '/Gw' in build_args: + target_args.append('/Gw') if len(target_args) > 0: target_args.append('%(AdditionalOptions)') ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(target_args) - - target_inc_dirs.append('%(AdditionalIncludeDirectories)') ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(target_inc_dirs) target_defines.append('%(PreprocessorDefinitions)') ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines) ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true' # Warning level - warning_level = self.get_option_for_target('warning_level', target) + warning_level = self.get_option_for_target(OptionKey('warning_level'), target) ET.SubElement(clconf, 'WarningLevel').text = 'Level' + str(1 + int(warning_level)) - if self.get_option_for_target('werror', target): + if self.get_option_for_target(OptionKey('werror'), target): ET.SubElement(clconf, 'TreatWarningAsError').text = 'true' # Optimization flags - o_flags = split_o_flags_args(buildtype_args) + o_flags = split_o_flags_args(build_args) if '/Ox' in o_flags: ET.SubElement(clconf, 'Optimization').text = 'Full' elif '/O2' in o_flags: @@ -1041,14 +1140,13 @@ else: ET.SubElement(clconf, 'FavorSizeOrSpeed').text = 'Speed' # Note: SuppressStartupBanner is /NOLOGO and is 'true' by default + self.generate_lang_standard_info(file_args, clconf) pch_sources = {} - if self.environment.coredata.base_options.get('b_pch', False): - pch_node = ET.SubElement(clconf, 'PrecompiledHeader') + if self.environment.coredata.options.get(OptionKey('b_pch')): for lang in ['c', 'cpp']: pch = target.get_pch(lang) if not pch: continue - pch_node.text = 'Use' if compiler.id == 'msvc': if len(pch) == 1: # Auto generate PCH. @@ -1062,27 +1160,25 @@ # I don't know whether its relevant but let's handle other compilers # used with a vs backend pch_sources[lang] = [pch[0], None, lang, None] - if len(pch_sources) == 1: - # If there is only 1 language with precompiled headers, we can use it for the entire project, which - # is cleaner than specifying it for each source file. - self.use_pch(pch_sources, list(pch_sources)[0], clconf) resourcecompile = ET.SubElement(compiles, 'ResourceCompile') ET.SubElement(resourcecompile, 'PreprocessorDefinitions') # Linker options link = ET.SubElement(compiles, 'Link') - extra_link_args = CompilerArgs(compiler) + extra_link_args = compiler.compiler_args() # FIXME: Can these buildtype linker args be added as tags in the # vcxproj file (similar to buildtype compiler args) instead of in # AdditionalOptions? extra_link_args += compiler.get_buildtype_linker_args(self.buildtype) # Generate Debug info - if self.buildtype.startswith('debug'): + if self.debug: self.generate_debug_information(link) + else: + ET.SubElement(link, 'GenerateDebugInformation').text = 'false' if not isinstance(target, build.StaticLibrary): if isinstance(target, build.SharedModule): - options = self.environment.coredata.base_options + options = self.environment.coredata.options extra_link_args += compiler.get_std_shared_module_link_args(options) # Add link args added using add_project_link_arguments() extra_link_args += self.build.get_project_link_args(compiler, target.subproject, target.for_machine) @@ -1092,7 +1188,8 @@ # Link args added from the env: LDFLAGS, or the cross file. We want # these to override all the defaults but not the per-target link # args. - extra_link_args += self.environment.coredata.get_external_link_args(target.for_machine, compiler.get_language()) + extra_link_args += self.environment.coredata.get_external_link_args( + target.for_machine, compiler.get_language()) # Only non-static built targets need link args and link dependencies extra_link_args += target.link_args # External deps must be last because target link libraries may depend on them. @@ -1100,14 +1197,14 @@ # Extend without reordering or de-dup to preserve `-L -l` sets # https://github.com/mesonbuild/meson/issues/1718 if isinstance(dep, dependencies.OpenMPDependency): - extra_link_args.extend_direct(compiler.openmp_flags()) + ET.SubElement(clconf, 'OpenMPSuppport').text = 'true' else: extra_link_args.extend_direct(dep.get_link_args()) for d in target.get_dependencies(): if isinstance(d, build.StaticLibrary): for dep in d.get_external_deps(): if isinstance(dep, dependencies.OpenMPDependency): - extra_link_args.extend_direct(compiler.openmp_flags()) + ET.SubElement(clconf, 'OpenMPSuppport').text = 'true' else: extra_link_args.extend_direct(dep.get_link_args()) # Add link args for c_* or cpp_* build options. Currently this only @@ -1115,7 +1212,7 @@ # to be after all internal and external libraries so that unresolved # symbols from those can be found here. This is needed when the # *_winlibs that we want to link to are static mingw64 libraries. - extra_link_args += compiler.get_option_link_args(self.environment.coredata.compiler_options[compiler.for_machine]) + extra_link_args += compiler.get_option_link_args(self.environment.coredata.options) (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native()) # Add more libraries to be linked if needed @@ -1127,8 +1224,31 @@ lobj = self.build.targets[t.get_id()] linkname = os.path.join(down, self.get_target_filename_for_linking(lobj)) if t in target.link_whole_targets: - # /WHOLEARCHIVE:foo must go into AdditionalOptions - extra_link_args += compiler.get_link_whole_for(linkname) + if compiler.id == 'msvc' and version_compare(compiler.version, '<19.00.23918'): + # Expand our object lists manually if we are on pre-Visual Studio 2015 Update 2 + l = t.extract_all_objects(False) + + # Unfortunately, we can't use self.object_filename_from_source() + for gen in l.genlist: + for src in gen.get_outputs(): + if self.environment.is_source(src) and not self.environment.is_header(src): + path = self.get_target_generated_dir(t, gen, src) + gen_src_ext = '.' + os.path.splitext(path)[1][1:] + extra_link_args.append(path[:-len(gen_src_ext)] + '.obj') + + for src in l.srclist: + obj_basename = None + if self.environment.is_source(src) and not self.environment.is_header(src): + obj_basename = self.object_filename_from_source(t, src) + target_private_dir = self.relpath(self.get_target_private_dir(t), + self.get_target_dir(t)) + rel_obj = os.path.join(target_private_dir, obj_basename) + extra_link_args.append(rel_obj) + + extra_link_args.extend(self.flatten_object_list(t)) + else: + # /WHOLEARCHIVE:foo must go into AdditionalOptions + extra_link_args += compiler.get_link_whole_for(linkname) # To force Visual Studio to build this project even though it # has no sources, we include a reference to the vcxproj file # that builds this target. Technically we should add this only @@ -1149,7 +1269,7 @@ additional_links.append(self.relpath(lib, self.get_target_dir(target))) additional_objects = [] for o in self.flatten_object_list(target, down): - assert(isinstance(o, str)) + assert isinstance(o, str) additional_objects.append(o) for o in custom_objs: additional_objects.append(o) @@ -1164,7 +1284,7 @@ additional_links.append('%(AdditionalDependencies)') ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links) ofile = ET.SubElement(link, 'OutputFile') - ofile.text = '$(OutDir)%s' % target.get_filename() + ofile.text = f'$(OutDir){target.get_filename()}' subsys = ET.SubElement(link, 'SubSystem') subsys.text = subsystem if (isinstance(target, build.SharedLibrary) or isinstance(target, build.Executable)) and target.get_import_filename(): @@ -1176,25 +1296,31 @@ if target.vs_module_defs: relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src)) ET.SubElement(link, 'ModuleDefinitionFile').text = relpath - if '/ZI' in buildtype_args or '/Zi' in buildtype_args: + if self.debug: pdb = ET.SubElement(link, 'ProgramDataBaseFileName') - pdb.text = '$(OutDir}%s.pdb' % target_name - if isinstance(target, build.Executable): - ET.SubElement(link, 'EntryPointSymbol').text = entrypoint + pdb.text = f'$(OutDir){target_name}.pdb' targetmachine = ET.SubElement(link, 'TargetMachine') - targetplatform = self.platform.lower() + if target.for_machine is MachineChoice.BUILD: + targetplatform = platform + else: + targetplatform = self.platform.lower() if targetplatform == 'win32': targetmachine.text = 'MachineX86' elif targetplatform == 'x64': targetmachine.text = 'MachineX64' elif targetplatform == 'arm': targetmachine.text = 'MachineARM' + elif targetplatform == 'arm64': + targetmachine.text = 'MachineARM64' + elif targetplatform == 'arm64ec': + targetmachine.text = 'MachineARM64EC' else: raise MesonException('Unsupported Visual Studio target machine: ' + targetplatform) # /nologo ET.SubElement(link, 'SuppressStartupBanner').text = 'true' # /release - ET.SubElement(link, 'SetChecksum').text = 'true' + if not self.environment.coredata.get_option(OptionKey('debug')): + ET.SubElement(link, 'SetChecksum').text = 'true' meson_file_group = ET.SubElement(root, 'ItemGroup') ET.SubElement(meson_file_group, 'None', Include=os.path.join(proj_to_src_dir, build_filename)) @@ -1241,7 +1367,8 @@ self.add_additional_options(lang, inc_cl, file_args) self.add_preprocessor_defines(lang, inc_cl, file_defines) self.add_include_dirs(lang, inc_cl, file_inc_dirs) - ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + self.object_filename_from_source(target, s) + ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + \ + self.object_filename_from_source(target, s) for s in gen_src: if path_normalize_add(s, previous_sources): inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s) @@ -1250,6 +1377,9 @@ self.add_additional_options(lang, inc_cl, file_args) self.add_preprocessor_defines(lang, inc_cl, file_defines) self.add_include_dirs(lang, inc_cl, file_inc_dirs) + s = File.from_built_file(target.get_subdir(), s) + ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + \ + self.object_filename_from_source(target, s) for lang in pch_sources: impl = pch_sources[lang][1] if impl and path_normalize_add(impl, previous_sources): @@ -1264,6 +1394,7 @@ else: inc_dirs = file_inc_dirs self.add_include_dirs(lang, inc_cl, inc_dirs) + # XXX: Do we need to set the object file name name here too? previous_objects = [] if self.has_objects(objects, additional_objects, gen_objs): @@ -1283,44 +1414,10 @@ self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_regenproj(self, project_name, ofname): - root = ET.Element('Project', {'DefaultTargets': 'Build', - 'ToolsVersion': '4.0', - 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) - confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) - prjconf = ET.SubElement(confitems, 'ProjectConfiguration', - {'Include': self.buildtype + '|' + self.platform}) - p = ET.SubElement(prjconf, 'Configuration') - p.text = self.buildtype - pl = ET.SubElement(prjconf, 'Platform') - pl.text = self.platform - globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') - guidelem = ET.SubElement(globalgroup, 'ProjectGuid') - guidelem.text = '{%s}' % self.environment.coredata.regen_guid - kw = ET.SubElement(globalgroup, 'Keyword') - kw.text = self.platform + 'Proj' - p = ET.SubElement(globalgroup, 'Platform') - p.text = self.platform - pname = ET.SubElement(globalgroup, 'ProjectName') - pname.text = project_name - if self.windows_target_platform_version: - ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version - ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.Default.props') - type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') - ET.SubElement(type_config, 'ConfigurationType').text = "Utility" - ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' - ET.SubElement(type_config, 'UseOfMfc').text = 'false' - if self.platform_toolset: - ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset - ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.props') - direlem = ET.SubElement(root, 'PropertyGroup') - fver = ET.SubElement(direlem, '_ProjectFileVersion') - fver.text = self.project_file_version - outdir = ET.SubElement(direlem, 'OutDir') - outdir.text = '.\\' - intdir = ET.SubElement(direlem, 'IntDir') - intdir.text = 'regen-temp\\' - tname = ET.SubElement(direlem, 'TargetName') - tname.text = project_name + guid = self.environment.coredata.regen_guid + (root, type_config) = self.create_basic_project(project_name, + temp_dir='regen-temp', + guid=guid) action = ET.SubElement(root, 'ItemDefinitionGroup') midl = ET.SubElement(action, 'Midl') @@ -1343,45 +1440,10 @@ self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_testproj(self, target_name, ofname): - project_name = target_name - root = ET.Element('Project', {'DefaultTargets': "Build", - 'ToolsVersion': '4.0', - 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) - confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) - prjconf = ET.SubElement(confitems, 'ProjectConfiguration', - {'Include': self.buildtype + '|' + self.platform}) - p = ET.SubElement(prjconf, 'Configuration') - p.text = self.buildtype - pl = ET.SubElement(prjconf, 'Platform') - pl.text = self.platform - globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') - guidelem = ET.SubElement(globalgroup, 'ProjectGuid') - guidelem.text = '{%s}' % self.environment.coredata.test_guid - kw = ET.SubElement(globalgroup, 'Keyword') - kw.text = self.platform + 'Proj' - p = ET.SubElement(globalgroup, 'Platform') - p.text = self.platform - pname = ET.SubElement(globalgroup, 'ProjectName') - pname.text = project_name - if self.windows_target_platform_version: - ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version - ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.Default.props') - type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') - ET.SubElement(type_config, 'ConfigurationType') - ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' - ET.SubElement(type_config, 'UseOfMfc').text = 'false' - if self.platform_toolset: - ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset - ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.props') - direlem = ET.SubElement(root, 'PropertyGroup') - fver = ET.SubElement(direlem, '_ProjectFileVersion') - fver.text = self.project_file_version - outdir = ET.SubElement(direlem, 'OutDir') - outdir.text = '.\\' - intdir = ET.SubElement(direlem, 'IntDir') - intdir.text = 'test-temp\\' - tname = ET.SubElement(direlem, 'TargetName') - tname.text = target_name + guid = self.environment.coredata.test_guid + (root, type_config) = self.create_basic_project(target_name, + temp_dir='test-temp', + guid=guid) action = ET.SubElement(root, 'ItemDefinitionGroup') midl = ET.SubElement(action, 'Midl') @@ -1393,9 +1455,9 @@ ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' # FIXME: No benchmarks? test_command = self.environment.get_build_command() + ['test', '--no-rebuild'] - if not self.environment.coredata.get_builtin_option('stdsplit'): + if not self.environment.coredata.get_option(OptionKey('stdsplit')): test_command += ['--no-stdsplit'] - if self.environment.coredata.get_builtin_option('errorlogs'): + if self.environment.coredata.get_option(OptionKey('errorlogs')): test_command += ['--print-errorlogs'] self.serialize_tests() self.add_custom_build(root, 'run_tests', '"%s"' % ('" "'.join(test_command))) @@ -1405,45 +1467,11 @@ def gen_installproj(self, target_name, ofname): self.create_install_data_files() - project_name = target_name - root = ET.Element('Project', {'DefaultTargets': "Build", - 'ToolsVersion': '4.0', - 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) - confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) - prjconf = ET.SubElement(confitems, 'ProjectConfiguration', - {'Include': self.buildtype + '|' + self.platform}) - p = ET.SubElement(prjconf, 'Configuration') - p.text = self.buildtype - pl = ET.SubElement(prjconf, 'Platform') - pl.text = self.platform - globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') - guidelem = ET.SubElement(globalgroup, 'ProjectGuid') - guidelem.text = '{%s}' % self.environment.coredata.install_guid - kw = ET.SubElement(globalgroup, 'Keyword') - kw.text = self.platform + 'Proj' - p = ET.SubElement(globalgroup, 'Platform') - p.text = self.platform - pname = ET.SubElement(globalgroup, 'ProjectName') - pname.text = project_name - if self.windows_target_platform_version: - ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version - ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.Default.props') - type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') - ET.SubElement(type_config, 'ConfigurationType') - ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' - ET.SubElement(type_config, 'UseOfMfc').text = 'false' - if self.platform_toolset: - ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset - ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.props') - direlem = ET.SubElement(root, 'PropertyGroup') - fver = ET.SubElement(direlem, '_ProjectFileVersion') - fver.text = self.project_file_version - outdir = ET.SubElement(direlem, 'OutDir') - outdir.text = '.\\' - intdir = ET.SubElement(direlem, 'IntDir') - intdir.text = 'install-temp\\' - tname = ET.SubElement(direlem, 'TargetName') - tname.text = target_name + + guid = self.environment.coredata.install_guid + (root, type_config) = self.create_basic_project(target_name, + temp_dir='install-temp', + guid=guid) action = ET.SubElement(root, 'ItemDefinitionGroup') midl = ET.SubElement(action, 'Midl') @@ -1459,7 +1487,7 @@ self.add_regen_dependency(root) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) - def add_custom_build(self, node, rulename, command, deps=None, outputs=None, msg=None): + def add_custom_build(self, node, rulename, command, deps=None, outputs=None, msg=None, verify_files=True): igroup = ET.SubElement(node, 'ItemGroup') rulefile = os.path.join(self.environment.get_scratch_dir(), rulename + '.rule') if not os.path.exists(rulefile): @@ -1469,8 +1497,10 @@ if msg: message = ET.SubElement(custombuild, 'Message') message.text = msg - cmd_templ = '''setlocal -%s + if not verify_files: + ET.SubElement(custombuild, 'VerifyInputsAndOutputsExist').text = 'false' + ET.SubElement(custombuild, 'Command').text = f'''setlocal +{command} if %%errorlevel%% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %%errorlevel%% & goto :cmDone @@ -1478,7 +1508,6 @@ exit /b %%1 :cmDone if %%errorlevel%% neq 0 goto :VCEnd''' - ET.SubElement(custombuild, 'Command').text = cmd_templ % command if not outputs: # Use a nonexistent file to always consider the target out-of-date. outputs = [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(), @@ -1502,3 +1531,6 @@ def add_regen_dependency(self, root): regen_vcxproj = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj') self.add_project_reference(root, regen_vcxproj, self.environment.coredata.regen_guid) + + def generate_lang_standard_info(self, file_args, clconf): + pass diff -Nru meson-0.53.2/mesonbuild/backend/vs2012backend.py meson-0.61.2/mesonbuild/backend/vs2012backend.py --- meson-0.53.2/mesonbuild/backend/vs2012backend.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/vs2012backend.py 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,40 @@ +# Copyright 2014-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. + +from .vs2010backend import Vs2010Backend +from ..mesonlib import MesonException +from ..interpreter import Interpreter +from ..build import Build +import typing as T + + +class Vs2012Backend(Vs2010Backend): + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.name = 'vs2012' + self.vs_version = '2012' + self.sln_file_version = '12.00' + self.sln_version_comment = '2012' + if self.environment is not None: + # TODO: we assume host == build + comps = self.environment.coredata.compilers.host + if comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + else: + # We don't have support for versions older than 2019 right now. + raise MesonException('There is currently no support for ICL before 19, patches welcome.') + if self.platform_toolset is None: + self.platform_toolset = 'v110' diff -Nru meson-0.53.2/mesonbuild/backend/vs2013backend.py meson-0.61.2/mesonbuild/backend/vs2013backend.py --- meson-0.53.2/mesonbuild/backend/vs2013backend.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/vs2013backend.py 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,40 @@ +# Copyright 2014-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. + +from .vs2010backend import Vs2010Backend +from ..mesonlib import MesonException +from ..interpreter import Interpreter +from ..build import Build +import typing as T + + +class Vs2013Backend(Vs2010Backend): + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.name = 'vs2013' + self.vs_version = '2013' + self.sln_file_version = '12.00' + self.sln_version_comment = '2013' + if self.environment is not None: + # TODO: we assume host == build + comps = self.environment.coredata.compilers.host + if comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + else: + # We don't have support for versions older than 2019 right now. + raise MesonException('There is currently no support for ICL before 19, patches welcome.') + if self.platform_toolset is None: + self.platform_toolset = 'v120' diff -Nru meson-0.53.2/mesonbuild/backend/vs2015backend.py meson-0.61.2/mesonbuild/backend/vs2015backend.py --- meson-0.53.2/mesonbuild/backend/vs2015backend.py 2019-08-28 17:15:39.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/vs2015backend.py 2021-12-26 16:24:25.000000000 +0000 @@ -14,13 +14,18 @@ from .vs2010backend import Vs2010Backend from ..mesonlib import MesonException +from ..interpreter import Interpreter +from ..build import Build +import typing as T class Vs2015Backend(Vs2010Backend): - def __init__(self, build): - super().__init__(build) + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) self.name = 'vs2015' self.vs_version = '2015' + self.sln_file_version = '12.00' + self.sln_version_comment = '14' if self.environment is not None: # TODO: we assume host == build comps = self.environment.coredata.compilers.host diff -Nru meson-0.53.2/mesonbuild/backend/vs2017backend.py meson-0.61.2/mesonbuild/backend/vs2017backend.py --- meson-0.53.2/mesonbuild/backend/vs2017backend.py 2019-08-28 17:15:39.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/vs2017backend.py 2021-12-26 16:24:25.000000000 +0000 @@ -13,17 +13,22 @@ # limitations under the License. import os +import typing as T import xml.etree.ElementTree as ET from .vs2010backend import Vs2010Backend from ..mesonlib import MesonException +from ..interpreter import Interpreter +from ..build import Build class Vs2017Backend(Vs2010Backend): - def __init__(self, build): - super().__init__(build) + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) self.name = 'vs2017' self.vs_version = '2017' + self.sln_file_version = '12.00' + self.sln_version_comment = '15' # We assume that host == build if self.environment is not None: comps = self.environment.coredata.compilers.host @@ -47,3 +52,13 @@ def generate_debug_information(self, link): # valid values for vs2017 is 'false', 'true', 'DebugFastLink', 'DebugFull' ET.SubElement(link, 'GenerateDebugInformation').text = 'DebugFull' + + def generate_lang_standard_info(self, file_args, clconf): + if 'cpp' in file_args: + optargs = [x for x in file_args['cpp'] if x.startswith('/std:c++')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard').text = optargs[0].replace("/std:c++", "stdcpp") + if 'c' in file_args: + optargs = [x for x in file_args['c'] if x.startswith('/std:c')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard_C').text = optargs[0].replace("/std:c", "stdc") diff -Nru meson-0.53.2/mesonbuild/backend/vs2019backend.py meson-0.61.2/mesonbuild/backend/vs2019backend.py --- meson-0.53.2/mesonbuild/backend/vs2019backend.py 2019-08-28 17:15:39.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/vs2019backend.py 2021-12-26 16:24:25.000000000 +0000 @@ -13,19 +13,24 @@ # limitations under the License. import os +import typing as T import xml.etree.ElementTree as ET from .vs2010backend import Vs2010Backend +from ..interpreter import Interpreter +from ..build import Build class Vs2019Backend(Vs2010Backend): - def __init__(self, build): - super().__init__(build) + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) self.name = 'vs2019' + self.sln_file_version = '12.00' + self.sln_version_comment = 'Version 16' if self.environment is not None: comps = self.environment.coredata.compilers.host if comps and all(c.id == 'clang-cl' for c in comps.values()): - self.platform_toolset = 'llvm' + self.platform_toolset = 'ClangCL' elif comps and all(c.id == 'intel-cl' for c in comps.values()): c = list(comps.values())[0] if c.version.startswith('19'): @@ -42,3 +47,13 @@ def generate_debug_information(self, link): # valid values for vs2019 is 'false', 'true', 'DebugFastLink', 'DebugFull' ET.SubElement(link, 'GenerateDebugInformation').text = 'DebugFull' + + def generate_lang_standard_info(self, file_args, clconf): + if 'cpp' in file_args: + optargs = [x for x in file_args['cpp'] if x.startswith('/std:c++')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard').text = optargs[0].replace("/std:c++", "stdcpp") + if 'c' in file_args: + optargs = [x for x in file_args['c'] if x.startswith('/std:c')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard_C').text = optargs[0].replace("/std:c", "stdc") diff -Nru meson-0.53.2/mesonbuild/backend/vs2022backend.py meson-0.61.2/mesonbuild/backend/vs2022backend.py --- meson-0.53.2/mesonbuild/backend/vs2022backend.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/vs2022backend.py 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,59 @@ +# Copyright 2014-2021 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 typing as T +import xml.etree.ElementTree as ET + +from .vs2010backend import Vs2010Backend +from ..interpreter import Interpreter +from ..build import Build + + +class Vs2022Backend(Vs2010Backend): + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.name = 'vs2022' + self.sln_file_version = '12.00' + self.sln_version_comment = 'Version 17' + if self.environment is not None: + comps = self.environment.coredata.compilers.host + if comps and all(c.id == 'clang-cl' for c in comps.values()): + self.platform_toolset = 'ClangCL' + elif comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + # We don't have support for versions older than 2022 right now. + if not self.platform_toolset: + self.platform_toolset = 'v143' + self.vs_version = '2022' + # WindowsSDKVersion should be set by command prompt. + sdk_version = os.environ.get('WindowsSDKVersion', None) + if sdk_version: + self.windows_target_platform_version = sdk_version.rstrip('\\') + + def generate_debug_information(self, link): + # valid values for vs2022 is 'false', 'true', 'DebugFastLink', 'DebugFull' + ET.SubElement(link, 'GenerateDebugInformation').text = 'DebugFull' + + def generate_lang_standard_info(self, file_args, clconf): + if 'cpp' in file_args: + optargs = [x for x in file_args['cpp'] if x.startswith('/std:c++')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard').text = optargs[0].replace("/std:c++", "stdcpp") + if 'c' in file_args: + optargs = [x for x in file_args['c'] if x.startswith('/std:c')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard_C').text = optargs[0].replace("/std:c", "stdc") diff -Nru meson-0.53.2/mesonbuild/backend/xcodebackend.py meson-0.61.2/mesonbuild/backend/xcodebackend.py --- meson-0.53.2/mesonbuild/backend/xcodebackend.py 2019-12-04 18:45:50.000000000 +0000 +++ meson-0.61.2/mesonbuild/backend/xcodebackend.py 2021-11-02 19:58:13.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright 2014-2016 The Meson development team +# Copyright 2014-2021 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. @@ -18,48 +18,222 @@ from .. import mesonlib from .. import mlog import uuid, os, operator +import typing as T -from ..mesonlib import MesonException +from ..mesonlib import MesonException, OptionKey +from ..interpreter import Interpreter + +INDENT = '\t' +XCODETYPEMAP = {'c': 'sourcecode.c.c', + 'a': 'archive.ar', + 'cc': 'sourcecode.cpp.cpp', + 'cxx': 'sourcecode.cpp.cpp', + 'cpp': 'sourcecode.cpp.cpp', + 'c++': 'sourcecode.cpp.cpp', + 'm': 'sourcecode.c.objc', + 'mm': 'sourcecode.cpp.objcpp', + 'h': 'sourcecode.c.h', + 'hpp': 'sourcecode.cpp.h', + 'hxx': 'sourcecode.cpp.h', + 'hh': 'sourcecode.cpp.hh', + 'inc': 'sourcecode.c.h', + 'swift': 'sourcecode.swift', + 'dylib': 'compiled.mach-o.dylib', + 'o': 'compiled.mach-o.objfile', + 's': 'sourcecode.asm', + 'asm': 'sourcecode.asm', + } +LANGNAMEMAP = {'c': 'C', + 'cpp': 'CPLUSPLUS', + 'objc': 'OBJC', + 'objcpp': 'OBJCPLUSPLUS', + 'swift': 'SWIFT_' + } +OPT2XCODEOPT = {'0': '0', + 'g': '0', + '1': '1', + '2': '2', + '3': '3', + 's': 's', + } +BOOL2XCODEBOOL = {True: 'YES', False: 'NO'} +LINKABLE_EXTENSIONS = {'.o', '.a', '.obj', '.so', '.dylib'} + +class FileTreeEntry: + + def __init__(self): + self.subdirs = {} + self.targets = [] + +class PbxItem: + def __init__(self, value, comment = ''): + self.value = value + self.comment = comment + +class PbxArray: + def __init__(self): + self.items = [] + + def add_item(self, item, comment=''): + if isinstance(item, PbxArrayItem): + self.items.append(item) + else: + self.items.append(PbxArrayItem(item, comment)) + + def write(self, ofile, indent_level): + ofile.write('(\n') + indent_level += 1 + for i in self.items: + if i.comment: + ofile.write(indent_level*INDENT + f'{i.value} {i.comment},\n') + else: + ofile.write(indent_level*INDENT + f'{i.value},\n') + indent_level -= 1 + ofile.write(indent_level*INDENT + ');\n') + +class PbxArrayItem: + def __init__(self, value, comment = ''): + self.value = value + if comment: + if '/*' in comment: + self.comment = comment + else: + self.comment = f'/* {comment} */' + else: + self.comment = comment + +class PbxComment: + def __init__(self, text): + assert isinstance(text, str) + assert '/*' not in text + self.text = f'/* {text} */' + + def write(self, ofile, indent_level): + ofile.write(f'\n{self.text}\n') + +class PbxDictItem: + def __init__(self, key, value, comment = ''): + self.key = key + self.value = value + if comment: + if '/*' in comment: + self.comment = comment + else: + self.comment = f'/* {comment} */' + else: + self.comment = comment + +class PbxDict: + def __init__(self): + # This class is a bit weird, because we want to write PBX dicts in + # defined order _and_ we want to write intermediate comments also in order. + self.keys = set() + self.items = [] + + def add_item(self, key, value, comment=''): + item = PbxDictItem(key, value, comment) + assert key not in self.keys + self.keys.add(key) + self.items.append(item) + + def has_item(self, key): + return key in self.keys + + def add_comment(self, comment): + if isinstance(comment, str): + self.items.append(PbxComment(str)) + else: + assert isinstance(comment, PbxComment) + self.items.append(comment) + + def write(self, ofile, indent_level): + ofile.write('{\n') + indent_level += 1 + for i in self.items: + if isinstance(i, PbxComment): + i.write(ofile, indent_level) + elif isinstance(i, PbxDictItem): + if isinstance(i.value, (str, int)): + if i.comment: + ofile.write(indent_level*INDENT + f'{i.key} = {i.value} {i.comment};\n') + else: + ofile.write(indent_level*INDENT + f'{i.key} = {i.value};\n') + elif isinstance(i.value, PbxDict): + if i.comment: + ofile.write(indent_level*INDENT + f'{i.key} {i.comment} = ') + else: + ofile.write(indent_level*INDENT + f'{i.key} = ') + i.value.write(ofile, indent_level) + elif isinstance(i.value, PbxArray): + if i.comment: + ofile.write(indent_level*INDENT + f'{i.key} {i.comment} = ') + else: + ofile.write(indent_level*INDENT + f'{i.key} = ') + i.value.write(ofile, indent_level) + else: + print(i) + print(i.key) + print(i.value) + raise RuntimeError('missing code') + else: + print(i) + raise RuntimeError('missing code2') + + indent_level -= 1 + ofile.write(indent_level*INDENT + '}') + if indent_level == 0: + ofile.write('\n') + else: + ofile.write(';\n') class XCodeBackend(backends.Backend): - def __init__(self, build): - super().__init__(build) + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) self.name = 'xcode' self.project_uid = self.environment.coredata.lang_guids['default'].replace('-', '')[:24] + self.buildtype = self.environment.coredata.get_option(OptionKey('buildtype')) self.project_conflist = self.gen_id() - self.indent = '\t' # Recent versions of Xcode uses tabs - self.indent_level = 0 - self.xcodetypemap = {'c': 'sourcecode.c.c', - 'a': 'archive.ar', - 'cc': 'sourcecode.cpp.cpp', - 'cxx': 'sourcecode.cpp.cpp', - 'cpp': 'sourcecode.cpp.cpp', - 'c++': 'sourcecode.cpp.cpp', - 'm': 'sourcecode.c.objc', - 'mm': 'sourcecode.cpp.objcpp', - 'h': 'sourcecode.c.h', - 'hpp': 'sourcecode.cpp.h', - 'hxx': 'sourcecode.cpp.h', - 'hh': 'sourcecode.cpp.hh', - 'inc': 'sourcecode.c.h', - 'dylib': 'compiled.mach-o.dylib', - 'o': 'compiled.mach-o.objfile', - 's': 'sourcecode.asm', - 'asm': 'sourcecode.asm', - } self.maingroup_id = self.gen_id() self.all_id = self.gen_id() self.all_buildconf_id = self.gen_id() - self.buildtypes = ['debug'] + self.buildtypes = [self.buildtype] self.test_id = self.gen_id() self.test_command_id = self.gen_id() self.test_buildconf_id = self.gen_id() + self.regen_id = self.gen_id() + self.regen_command_id = self.gen_id() + self.regen_buildconf_id = self.gen_id() + self.regen_dependency_id = self.gen_id() + self.top_level_dict = PbxDict() + self.generator_outputs = {} + # In Xcode files are not accessed via their file names, but rather every one of them + # gets an unique id. More precisely they get one unique id per target they are used + # in. If you generate only one id per file and use them, compilation will work but the + # UI will only show the file in one target but not the others. Thus they key is + # a tuple containing the target and filename. + self.buildfile_ids = {} + # That is not enough, though. Each target/file combination also gets a unique id + # in the file reference section. Because why not. This means that a source file + # that is used in two targets gets a total of four unique ID numbers. + self.fileref_ids = {} + + def write_pbxfile(self, top_level_dict, ofilename): + tmpname = ofilename + '.tmp' + with open(tmpname, 'w', encoding='utf-8') as ofile: + ofile.write('// !$*UTF8*$!\n') + top_level_dict.write(ofile, 0) + os.replace(tmpname, ofilename) def gen_id(self): return str(uuid.uuid4()).upper().replace('-', '')[:24] def get_target_dir(self, target): - dirname = os.path.join(target.get_subdir(), self.environment.coredata.get_builtin_option('buildtype')) + dirname = os.path.join(target.get_subdir(), self.environment.coredata.get_option(OptionKey('buildtype'))) + #os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) + return dirname + + def get_custom_target_output_dir(self, target): + dirname = target.get_subdir() os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname @@ -69,16 +243,28 @@ directories = os.path.normpath(self.get_target_dir(target)).split(os.sep) return os.sep.join(['..'] * len(directories)) - def write_line(self, text): - self.ofile.write(self.indent * self.indent_level + text) - if not text.endswith('\n'): - self.ofile.write('\n') - - def generate(self, interp): - self.interpreter = interp - test_data = self.serialize_tests()[0] + def object_filename_from_source(self, target, source): + # Xcode has the following naming scheme: + # projectname.build/debug/prog@exe.build/Objects-normal/x86_64/func.o + project = self.build.project_name + buildtype = self.buildtype + tname = target.get_id() + arch = 'x86_64' + if isinstance(source, mesonlib.File): + source = source.fname + stem = os.path.splitext(os.path.basename(source))[0] + obj_path = f'{project}.build/{buildtype}/{tname}.build/Objects-normal/{arch}/{stem}.o' + return obj_path + + def get_extracted_obj_paths(self, target: build.BuildTarget, outputs: T.List[str]) -> T.List[str]: + return outputs + + def generate(self): + self.serialize_tests() + # Cache the result as the method rebuilds the array every time it is called. + self.build_targets = self.build.get_build_targets() + self.custom_targets = self.build.get_custom_targets() self.generate_filemap() - self.generate_buildmap() self.generate_buildstylemap() self.generate_build_phase_map() self.generate_build_configuration_map() @@ -88,42 +274,77 @@ self.generate_test_configurations_map() self.generate_native_target_map() self.generate_native_frameworks_map() + self.generate_custom_target_map() + self.generate_generator_target_map() self.generate_source_phase_map() self.generate_target_dependency_map() self.generate_pbxdep_map() self.generate_containerproxy_map() + self.generate_target_file_maps() + self.generate_build_file_maps() self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj') os.makedirs(self.proj_dir, exist_ok=True) self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj') - with open(self.proj_file, 'w') as self.ofile: - self.generate_prefix() - self.generate_pbx_aggregate_target() - self.generate_pbx_build_file() - self.generate_pbx_build_style() - self.generate_pbx_container_item_proxy() - self.generate_pbx_file_reference() - self.generate_pbx_frameworks_buildphase() - self.generate_pbx_group() - self.generate_pbx_native_target() - self.generate_pbx_project() - self.generate_pbx_shell_build_phase(test_data) - self.generate_pbx_sources_build_phase() - self.generate_pbx_target_dependency() - self.generate_xc_build_configuration() - self.generate_xc_configurationList() - self.generate_suffix() + objects_dict = self.generate_prefix(self.top_level_dict) + objects_dict.add_comment(PbxComment('Begin PBXAggregateTarget section')) + self.generate_pbx_aggregate_target(objects_dict) + objects_dict.add_comment(PbxComment('End PBXAggregateTarget section')) + objects_dict.add_comment(PbxComment('Begin PBXBuildFile section')) + self.generate_pbx_build_file(objects_dict) + objects_dict.add_comment(PbxComment('End PBXBuildFile section')) + objects_dict.add_comment(PbxComment('Begin PBXBuildStyle section')) + self.generate_pbx_build_style(objects_dict) + objects_dict.add_comment(PbxComment('End PBXBuildStyle section')) + objects_dict.add_comment(PbxComment('Begin PBXContainerItemProxy section')) + self.generate_pbx_container_item_proxy(objects_dict) + objects_dict.add_comment(PbxComment('End PBXContainerItemProxy section')) + objects_dict.add_comment(PbxComment('Begin PBXFileReference section')) + self.generate_pbx_file_reference(objects_dict) + objects_dict.add_comment(PbxComment('End PBXFileReference section')) + objects_dict.add_comment(PbxComment('Begin PBXFrameworksBuildPhase section')) + self.generate_pbx_frameworks_buildphase(objects_dict) + objects_dict.add_comment(PbxComment('End PBXFrameworksBuildPhase section')) + objects_dict.add_comment(PbxComment('Begin PBXGroup section')) + self.generate_pbx_group(objects_dict) + objects_dict.add_comment(PbxComment('End PBXGroup section')) + objects_dict.add_comment(PbxComment('Begin PBXNativeTarget section')) + self.generate_pbx_native_target(objects_dict) + objects_dict.add_comment(PbxComment('End PBXNativeTarget section')) + objects_dict.add_comment(PbxComment('Begin PBXProject section')) + self.generate_pbx_project(objects_dict) + objects_dict.add_comment(PbxComment('End PBXProject section')) + objects_dict.add_comment(PbxComment('Begin PBXShellScriptBuildPhase section')) + self.generate_pbx_shell_build_phase(objects_dict) + objects_dict.add_comment(PbxComment('End PBXShellScriptBuildPhase section')) + objects_dict.add_comment(PbxComment('Begin PBXSourcesBuildPhase section')) + self.generate_pbx_sources_build_phase(objects_dict) + objects_dict.add_comment(PbxComment('End PBXSourcesBuildPhase section')) + objects_dict.add_comment(PbxComment('Begin PBXTargetDependency section')) + self.generate_pbx_target_dependency(objects_dict) + objects_dict.add_comment(PbxComment('End PBXTargetDependency section')) + objects_dict.add_comment(PbxComment('Begin XCBuildConfiguration section')) + self.generate_xc_build_configuration(objects_dict) + objects_dict.add_comment(PbxComment('End XCBuildConfiguration section')) + objects_dict.add_comment(PbxComment('Begin XCConfigurationList section')) + self.generate_xc_configurationList(objects_dict) + objects_dict.add_comment(PbxComment('End XCConfigurationList section')) + self.generate_suffix(self.top_level_dict) + self.write_pbxfile(self.top_level_dict, self.proj_file) + self.generate_regen_info() def get_xcodetype(self, fname): - xcodetype = self.xcodetypemap.get(fname.split('.')[-1].lower()) + extension = fname.split('.')[-1] + if extension == 'C': + extension = 'cpp' + xcodetype = XCODETYPEMAP.get(extension.lower()) if not xcodetype: xcodetype = 'sourcecode.unknown' - mlog.warning('Unknown file type "%s" fallbacking to "%s". Xcode project might be malformed.' % (fname, xcodetype)) return xcodetype def generate_filemap(self): self.filemap = {} # Key is source file relative to src root. self.target_filemap = {} - for name, t in self.build.targets.items(): + for name, t in self.build_targets.items(): for s in t.sources: if isinstance(s, mesonlib.File): s = os.path.join(s.subdir, s.fname) @@ -134,22 +355,11 @@ self.filemap[o] = self.gen_id() self.target_filemap[name] = self.gen_id() - def generate_buildmap(self): - self.buildmap = {} - for t in self.build.targets.values(): - for s in t.sources: - s = os.path.join(s.subdir, s.fname) - self.buildmap[s] = self.gen_id() - for o in t.objects: - o = os.path.join(t.subdir, o) - if isinstance(o, str): - self.buildmap[o] = self.gen_id() - def generate_buildstylemap(self): - self.buildstylemap = {'debug': self.gen_id()} + self.buildstylemap = {self.buildtype: self.gen_id()} def generate_build_phase_map(self): - for tname, t in self.build.targets.items(): + for tname, t in self.build_targets.items(): # generate id for our own target-name t.buildphasemap = {} t.buildphasemap[tname] = self.gen_id() @@ -160,33 +370,91 @@ def generate_build_configuration_map(self): self.buildconfmap = {} - for t in self.build.targets: - bconfs = {'debug': self.gen_id()} + for t in self.build_targets: + bconfs = {self.buildtype: self.gen_id()} + self.buildconfmap[t] = bconfs + for t in self.custom_targets: + bconfs = {self.buildtype: self.gen_id()} self.buildconfmap[t] = bconfs def generate_project_configurations_map(self): - self.project_configurations = {'debug': self.gen_id()} + self.project_configurations = {self.buildtype: self.gen_id()} def generate_buildall_configurations_map(self): - self.buildall_configurations = {'debug': self.gen_id()} + self.buildall_configurations = {self.buildtype: self.gen_id()} def generate_test_configurations_map(self): - self.test_configurations = {'debug': self.gen_id()} + self.test_configurations = {self.buildtype: self.gen_id()} def generate_build_configurationlist_map(self): self.buildconflistmap = {} - for t in self.build.targets: + for t in self.build_targets: + self.buildconflistmap[t] = self.gen_id() + for t in self.custom_targets: self.buildconflistmap[t] = self.gen_id() def generate_native_target_map(self): self.native_targets = {} - for t in self.build.targets: + for t in self.build_targets: self.native_targets[t] = self.gen_id() + def generate_custom_target_map(self): + self.shell_targets = {} + self.custom_target_output_buildfile = {} + self.custom_target_output_fileref = {} + for tname, t in self.custom_targets.items(): + self.shell_targets[tname] = self.gen_id() + if not isinstance(t, build.CustomTarget): + continue + (srcs, ofilenames, cmd) = self.eval_custom_target_command(t) + for o in ofilenames: + self.custom_target_output_buildfile[o] = self.gen_id() + self.custom_target_output_fileref[o] = self.gen_id() + + def generate_generator_target_map(self): + # Generator objects do not have natural unique ids + # so use a counter. + self.generator_fileref_ids = {} + self.generator_buildfile_ids = {} + for tname, t in self.build_targets.items(): + generator_id = 0 + for genlist in t.generated: + if not isinstance(genlist, build.GeneratedList): + continue + self.gen_single_target_map(genlist, tname, t, generator_id) + generator_id += 1 + # FIXME add outputs. + for tname, t in self.custom_targets.items(): + generator_id = 0 + for genlist in t.sources: + if not isinstance(genlist, build.GeneratedList): + continue + self.gen_single_target_map(genlist, tname, t, generator_id) + generator_id += 1 + + def gen_single_target_map(self, genlist, tname, t, generator_id): + k = (tname, generator_id) + assert k not in self.shell_targets + self.shell_targets[k] = self.gen_id() + ofile_abs = [] + for i in genlist.get_inputs(): + for o_base in genlist.get_outputs_for(i): + o = os.path.join(self.get_target_private_dir(t), o_base) + ofile_abs.append(os.path.join(self.environment.get_build_dir(), o)) + assert k not in self.generator_outputs + self.generator_outputs[k] = ofile_abs + buildfile_ids = [] + fileref_ids = [] + for i in range(len(ofile_abs)): + buildfile_ids.append(self.gen_id()) + fileref_ids.append(self.gen_id()) + self.generator_buildfile_ids[k] = buildfile_ids + self.generator_fileref_ids[k] = fileref_ids + def generate_native_frameworks_map(self): self.native_frameworks = {} self.native_frameworks_fileref = {} - for t in self.build.targets.values(): + for t in self.build_targets.values(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: @@ -195,141 +463,337 @@ def generate_target_dependency_map(self): self.target_dependency_map = {} - for tname, t in self.build.targets.items(): + for tname, t in self.build_targets.items(): for target in t.link_targets: - self.target_dependency_map[(tname, target.get_basename())] = self.gen_id() + if isinstance(target, build.CustomTargetIndex): + k = (tname, target.target.get_basename()) + if k in self.target_dependency_map: + continue + else: + k = (tname, target.get_basename()) + assert k not in self.target_dependency_map + self.target_dependency_map[k] = self.gen_id() + for tname, t in self.custom_targets.items(): + k = tname + assert k not in self.target_dependency_map + self.target_dependency_map[k] = self.gen_id() def generate_pbxdep_map(self): self.pbx_dep_map = {} - for t in self.build.targets: + self.pbx_custom_dep_map = {} + for t in self.build_targets: self.pbx_dep_map[t] = self.gen_id() + for t in self.custom_targets: + self.pbx_custom_dep_map[t] = self.gen_id() def generate_containerproxy_map(self): self.containerproxy_map = {} - for t in self.build.targets: + for t in self.build_targets: self.containerproxy_map[t] = self.gen_id() + def generate_target_file_maps(self): + self.generate_target_file_maps_impl(self.build_targets) + self.generate_target_file_maps_impl(self.custom_targets) + + def generate_target_file_maps_impl(self, targets): + for tname, t in targets.items(): + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + if not isinstance(s, str): + continue + k = (tname, s) + assert k not in self.buildfile_ids + self.buildfile_ids[k] = self.gen_id() + assert k not in self.fileref_ids + self.fileref_ids[k] = self.gen_id() + if not hasattr(t, 'objects'): + continue + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + # Extracted objects do not live in "the Xcode world". + continue + if isinstance(o, mesonlib.File): + o = os.path.join(o.subdir, o.fname) + if isinstance(o, str): + o = os.path.join(t.subdir, o) + k = (tname, o) + assert k not in self.buildfile_ids + self.buildfile_ids[k] = self.gen_id() + assert k not in self.fileref_ids + self.fileref_ids[k] = self.gen_id() + else: + raise RuntimeError('Unknown input type ' + str(o)) + + def generate_build_file_maps(self): + for buildfile in self.interpreter.get_build_def_files(): + assert isinstance(buildfile, str) + self.buildfile_ids[buildfile] = self.gen_id() + self.fileref_ids[buildfile] = self.gen_id() + def generate_source_phase_map(self): self.source_phase = {} - for t in self.build.targets: + for t in self.build_targets: self.source_phase[t] = self.gen_id() - def generate_pbx_aggregate_target(self): - target_dependencies = list(map(lambda t: self.pbx_dep_map[t], self.build.targets)) + def generate_pbx_aggregate_target(self, objects_dict): + self.custom_aggregate_targets = {} + self.build_all_tdep_id = self.gen_id() + # FIXME: filter out targets that are not built by default. + target_dependencies = list(map(lambda t: self.pbx_dep_map[t], self.build_targets)) + custom_target_dependencies = [self.pbx_custom_dep_map[t] for t in self.custom_targets] aggregated_targets = [] - aggregated_targets.append((self.all_id, 'ALL_BUILD', self.all_buildconf_id, [], target_dependencies)) - aggregated_targets.append((self.test_id, 'RUN_TESTS', self.test_buildconf_id, [self.test_command_id], [])) + aggregated_targets.append((self.all_id, 'ALL_BUILD', + self.all_buildconf_id, + [], + [self.regen_dependency_id] + target_dependencies + custom_target_dependencies)) + aggregated_targets.append((self.test_id, + 'RUN_TESTS', + self.test_buildconf_id, + [self.test_command_id], + [self.regen_dependency_id, self.build_all_tdep_id])) + aggregated_targets.append((self.regen_id, + 'REGENERATE', + self.regen_buildconf_id, + [self.regen_command_id], + [])) + for tname, t in self.build.get_custom_targets().items(): + ct_id = self.gen_id() + self.custom_aggregate_targets[tname] = ct_id + build_phases = [] + dependencies = [self.regen_dependency_id] + generator_id = 0 + for s in t.sources: + if not isinstance(s, build.GeneratedList): + continue + build_phases.append(self.shell_targets[(tname, generator_id)]) + for d in s.depends: + dependencies.append(self.pbx_custom_dep_map[d.get_id()]) + generator_id += 1 + build_phases.append(self.shell_targets[tname]) + aggregated_targets.append((ct_id, tname, self.buildconflistmap[tname], build_phases, dependencies)) + # Sort objects by ID before writing sorted_aggregated_targets = sorted(aggregated_targets, key=operator.itemgetter(0)) - self.ofile.write('\n/* Begin PBXAggregateTarget section */\n') for t in sorted_aggregated_targets: + agt_dict = PbxDict() name = t[1] buildconf_id = t[2] build_phases = t[3] dependencies = t[4] - self.write_line('%s /* %s */ = {' % (t[0], name)) - self.indent_level += 1 - self.write_line('isa = PBXAggregateTarget;') - self.write_line('buildConfigurationList = %s /* Build configuration list for PBXAggregateTarget "%s" */;' % (buildconf_id, name)) - self.write_line('buildPhases = (') - self.indent_level += 1 + agt_dict.add_item('isa', 'PBXAggregateTarget') + agt_dict.add_item('buildConfigurationList', buildconf_id, f'Build configuration list for PBXAggregateTarget "{name}"') + bp_arr = PbxArray() + agt_dict.add_item('buildPhases', bp_arr) for bp in build_phases: - self.write_line('%s /* ShellScript */,' % bp) - self.indent_level -= 1 - self.write_line(');') - self.write_line('dependencies = (') - self.indent_level += 1 + bp_arr.add_item(bp, 'ShellScript') + dep_arr = PbxArray() + agt_dict.add_item('dependencies', dep_arr) for td in dependencies: - self.write_line('%s /* PBXTargetDependency */,' % td) - self.indent_level -= 1 - self.write_line(');') - self.write_line('name = %s;' % name) - self.write_line('productName = %s;' % name) - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End PBXAggregateTarget section */\n') - - def generate_pbx_build_file(self): - self.ofile.write('\n/* Begin PBXBuildFile section */\n') - templ = '%s /* %s */ = { isa = PBXBuildFile; fileRef = %s /* %s */; settings = { COMPILER_FLAGS = "%s"; }; };\n' - otempl = '%s /* %s */ = { isa = PBXBuildFile; fileRef = %s /* %s */;};\n' - - for t in self.build.targets.values(): + dep_arr.add_item(td, 'PBXTargetDependency') + agt_dict.add_item('name', f'"{name}"') + agt_dict.add_item('productName', f'"{name}"') + objects_dict.add_item(t[0], agt_dict, name) + def generate_pbx_build_file(self, objects_dict): + for tname, t in self.build_targets.items(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.write_line('%s /* %s.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = %s /* %s.framework */; };\n' % (self.native_frameworks[f], f, self.native_frameworks_fileref[f], f)) + fw_dict = PbxDict() + objects_dict.add_item(self.native_frameworks[f], fw_dict, f'{f}.framework in Frameworks') + fw_dict.add_item('isa', 'PBXBuildFile') + fw_dict.add_item('fileRef', self.native_frameworks_fileref[f], f) for s in t.sources: + in_build_dir = False if isinstance(s, mesonlib.File): - s = s.fname + if s.is_built: + in_build_dir = True + s = os.path.join(s.subdir, s.fname) - if isinstance(s, str): - s = os.path.join(t.subdir, s) - idval = self.buildmap[s] + if not isinstance(s, str): + continue + sdict = PbxDict() + k = (tname, s) + idval = self.buildfile_ids[k] + fileref = self.fileref_ids[k] + if in_build_dir: + fullpath = os.path.join(self.environment.get_build_dir(), s) + else: fullpath = os.path.join(self.environment.get_source_dir(), s) - fileref = self.filemap[s] - fullpath2 = fullpath - compiler_args = '' - self.write_line(templ % (idval, fullpath, fileref, fullpath2, compiler_args)) + sdict.add_item('isa', 'PBXBuildFile') + sdict.add_item('fileRef', fileref, fullpath) + objects_dict.add_item(idval, sdict) + for o in t.objects: - o = os.path.join(t.subdir, o) - idval = self.buildmap[o] - fileref = self.filemap[o] + if isinstance(o, build.ExtractedObjects): + # Object files are not source files as such. We add them + # by hand in linker flags. It is also not particularly + # clear how to define build files in Xcode's file format. + continue + if isinstance(o, mesonlib.File): + o = os.path.join(o.subdir, o.fname) + elif isinstance(o, str): + o = os.path.join(t.subdir, o) + idval = self.buildfile_ids[(tname, o)] + k = (tname, o) + fileref = self.fileref_ids[k] + assert o not in self.filemap + self.filemap[o] = idval fullpath = os.path.join(self.environment.get_source_dir(), o) fullpath2 = fullpath - self.write_line(otempl % (idval, fullpath, fileref, fullpath2)) - self.ofile.write('/* End PBXBuildFile section */\n') + o_dict = PbxDict() + objects_dict.add_item(idval, o_dict, fullpath) + o_dict.add_item('isa', 'PBXBuildFile') + o_dict.add_item('fileRef', fileref, fullpath2) + + generator_id = 0 + for g in t.generated: + if not isinstance(g, build.GeneratedList): + continue + self.create_generator_shellphase(objects_dict, tname, generator_id) + generator_id += 1 + + # Custom targets are shell build phases in Xcode terminology. + for tname, t in self.custom_targets.items(): + if not isinstance(t, build.CustomTarget): + continue + (srcs, ofilenames, cmd) = self.eval_custom_target_command(t) + for o in ofilenames: + custom_dict = PbxDict() + objects_dict.add_item(self.custom_target_output_buildfile[o], custom_dict, f'/* {o} */') + custom_dict.add_item('isa', 'PBXBuildFile') + custom_dict.add_item('fileRef', self.custom_target_output_fileref[o]) + generator_id = 0 + for g in t.sources: + if not isinstance(g, build.GeneratedList): + continue + self.create_generator_shellphase(objects_dict, tname, generator_id) + generator_id += 1 + + def create_generator_shellphase(self, objects_dict, tname, generator_id): + file_ids = self.generator_buildfile_ids[(tname, generator_id)] + ref_ids = self.generator_fileref_ids[(tname, generator_id)] + assert len(ref_ids) == len(file_ids) + for file_o, ref_id in zip(file_ids, ref_ids): + odict = PbxDict() + objects_dict.add_item(file_o, odict) + odict.add_item('isa', 'PBXBuildFile') + odict.add_item('fileRef', ref_id) - def generate_pbx_build_style(self): + def generate_pbx_build_style(self, objects_dict): # FIXME: Xcode 9 and later does not uses PBXBuildStyle and it gets removed. Maybe we can remove this part. - self.ofile.write('\n/* Begin PBXBuildStyle section */\n') for name, idval in self.buildstylemap.items(): - self.write_line('%s /* %s */ = {\n' % (idval, name)) - self.indent_level += 1 - self.write_line('isa = PBXBuildStyle;\n') - self.write_line('buildSettings = {\n') - self.indent_level += 1 - self.write_line('COPY_PHASE_STRIP = NO;\n') - self.indent_level -= 1 - self.write_line('};\n') - self.write_line('name = "%s";\n' % name) - self.indent_level -= 1 - self.write_line('};\n') - self.ofile.write('/* End PBXBuildStyle section */\n') - - def generate_pbx_container_item_proxy(self): - self.ofile.write('\n/* Begin PBXContainerItemProxy section */\n') - for t in self.build.targets: - self.write_line('%s /* PBXContainerItemProxy */ = {' % self.containerproxy_map[t]) - self.indent_level += 1 - self.write_line('isa = PBXContainerItemProxy;') - self.write_line('containerPortal = %s /* Project object */;' % self.project_uid) - self.write_line('proxyType = 1;') - self.write_line('remoteGlobalIDString = %s;' % self.native_targets[t]) - self.write_line('remoteInfo = "%s";' % t) - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End PBXContainerItemProxy section */\n') - - def generate_pbx_file_reference(self): - self.ofile.write('\n/* Begin PBXFileReference section */\n') - for t in self.build.targets.values(): + styledict = PbxDict() + objects_dict.add_item(idval, styledict, name) + styledict.add_item('isa', 'PBXBuildStyle') + settings_dict = PbxDict() + styledict.add_item('buildSettings', settings_dict) + settings_dict.add_item('COPY_PHASE_STRIP', 'NO') + styledict.add_item('name', f'"{name}"') + + def generate_pbx_container_item_proxy(self, objects_dict): + for t in self.build_targets: + proxy_dict = PbxDict() + objects_dict.add_item(self.containerproxy_map[t], proxy_dict, 'PBXContainerItemProxy') + proxy_dict.add_item('isa', 'PBXContainerItemProxy') + proxy_dict.add_item('containerPortal', self.project_uid, 'Project object') + proxy_dict.add_item('proxyType', '1') + proxy_dict.add_item('remoteGlobalIDString', self.native_targets[t]) + proxy_dict.add_item('remoteInfo', '"' + t + '"') + + def generate_pbx_file_reference(self, objects_dict): + for tname, t in self.build_targets.items(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.write_line('%s /* %s.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = %s.framework; path = System/Library/Frameworks/%s.framework; sourceTree = SDKROOT; };\n' % (self.native_frameworks_fileref[f], f, f, f)) - src_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; fileEncoding = 4; name = "%s"; path = "%s"; sourceTree = SOURCE_ROOT; };\n' - for fname, idval in self.filemap.items(): - fullpath = os.path.join(self.environment.get_source_dir(), fname) - xcodetype = self.get_xcodetype(fname) - name = os.path.basename(fname) - path = fname - self.write_line(src_templ % (idval, fullpath, xcodetype, name, path)) - target_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; path = %s; refType = %d; sourceTree = BUILT_PRODUCTS_DIR; };\n' + fw_dict = PbxDict() + framework_fileref = self.native_frameworks_fileref[f] + if objects_dict.has_item(framework_fileref): + continue + objects_dict.add_item(framework_fileref, fw_dict, f) + fw_dict.add_item('isa', 'PBXFileReference') + fw_dict.add_item('lastKnownFileType', 'wrapper.framework') + fw_dict.add_item('name', f'{f}.framework') + fw_dict.add_item('path', f'System/Library/Frameworks/{f}.framework') + fw_dict.add_item('sourceTree', 'SDKROOT') + for s in t.sources: + in_build_dir = False + if isinstance(s, mesonlib.File): + if s.is_built: + in_build_dir = True + s = os.path.join(s.subdir, s.fname) + if not isinstance(s, str): + continue + idval = self.fileref_ids[(tname, s)] + fullpath = os.path.join(self.environment.get_source_dir(), s) + src_dict = PbxDict() + xcodetype = self.get_xcodetype(s) + name = os.path.basename(s) + path = s + objects_dict.add_item(idval, src_dict, fullpath) + src_dict.add_item('isa', 'PBXFileReference') + src_dict.add_item('explicitFileType', '"' + xcodetype + '"') + src_dict.add_item('fileEncoding', '4') + if in_build_dir: + src_dict.add_item('name', '"' + name + '"') + # This makes no sense. This should say path instead of name + # but then the path gets added twice. + src_dict.add_item('path', '"' + name + '"') + src_dict.add_item('sourceTree', 'BUILD_ROOT') + else: + src_dict.add_item('name', '"' + name + '"') + src_dict.add_item('path', '"' + path + '"') + src_dict.add_item('sourceTree', 'SOURCE_ROOT') + + generator_id = 0 + for g in t.generated: + if not isinstance(g, build.GeneratedList): + continue + outputs = self.generator_outputs[(tname, generator_id)] + ref_ids = self.generator_fileref_ids[tname, generator_id] + assert len(ref_ids) == len(outputs) + for o, ref_id in zip(outputs, ref_ids): + odict = PbxDict() + name = os.path.basename(o) + objects_dict.add_item(ref_id, odict, o) + xcodetype = self.get_xcodetype(o) + rel_name = mesonlib.relpath(o, self.environment.get_source_dir()) + odict.add_item('isa', 'PBXFileReference') + odict.add_item('explicitFileType', '"' + xcodetype + '"') + odict.add_item('fileEncoding', '4') + odict.add_item('name', f'"{name}"') + odict.add_item('path', f'"{rel_name}"') + odict.add_item('sourceTree', 'SOURCE_ROOT') + + generator_id += 1 + + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + # Same as with pbxbuildfile. + continue + if isinstance(o, mesonlib.File): + fullpath = o.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) + o = os.path.join(o.subdir, o.fname) + else: + o = os.path.join(t.subdir, o) + fullpath = os.path.join(self.environment.get_source_dir(), o) + idval = self.fileref_ids[(tname, o)] + rel_name = mesonlib.relpath(fullpath, self.environment.get_source_dir()) + o_dict = PbxDict() + name = os.path.basename(o) + objects_dict.add_item(idval, o_dict, fullpath) + o_dict.add_item('isa', 'PBXFileReference') + o_dict.add_item('explicitFileType', '"' + self.get_xcodetype(o) + '"') + o_dict.add_item('fileEncoding', '4') + o_dict.add_item('name', f'"{name}"') + o_dict.add_item('path', f'"{rel_name}"') + o_dict.add_item('sourceTree', 'SOURCE_ROOT') for tname, idval in self.target_filemap.items(): - t = self.build.targets[tname] + target_dict = PbxDict() + objects_dict.add_item(idval, target_dict, tname) + t = self.build_targets[tname] fname = t.get_filename() reftype = 0 if isinstance(t, build.Executable): @@ -341,178 +805,296 @@ else: typestr = self.get_xcodetype(fname) path = '"%s"' % t.get_filename() - self.write_line(target_templ % (idval, tname, typestr, path, reftype)) - self.ofile.write('/* End PBXFileReference section */\n') - - def generate_pbx_frameworks_buildphase(self): - for t in self.build.targets.values(): - self.ofile.write('\n/* Begin PBXFrameworksBuildPhase section */\n') - self.write_line('%s /* %s */ = {\n' % (t.buildphasemap['Frameworks'], 'Frameworks')) - self.indent_level += 1 - self.write_line('isa = PBXFrameworksBuildPhase;\n') - self.write_line('buildActionMask = %s;\n' % (2147483647)) - self.write_line('files = (\n') - self.indent_level += 1 + target_dict.add_item('isa', 'PBXFileReference') + target_dict.add_item('explicitFileType', '"' + typestr + '"') + if ' ' in path and path[0] != '"': + target_dict.add_item('path', f'"{path}"') + else: + target_dict.add_item('path', path) + target_dict.add_item('refType', reftype) + target_dict.add_item('sourceTree', 'BUILT_PRODUCTS_DIR') + + for tname, t in self.custom_targets.items(): + if not isinstance(t, build.CustomTarget): + continue + (srcs, ofilenames, cmd) = self.eval_custom_target_command(t) + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + elif isinstance(s, str): + s = os.path.joni(t.subdir, s) + else: + continue + custom_dict = PbxDict() + typestr = self.get_xcodetype(s) + custom_dict.add_item('isa', 'PBXFileReference') + custom_dict.add_item('explicitFileType', '"' + typestr + '"') + custom_dict.add_item('name', f'"{s}"') + custom_dict.add_item('path', f'"{s}"') + custom_dict.add_item('refType', 0) + custom_dict.add_item('sourceTree', 'SOURCE_ROOT') + objects_dict.add_item(self.fileref_ids[(tname, s)], custom_dict) + for o in ofilenames: + custom_dict = PbxDict() + typestr = self.get_xcodetype(o) + custom_dict.add_item('isa', 'PBXFileReference') + custom_dict.add_item('explicitFileType', '"' + typestr + '"') + custom_dict.add_item('name', o) + custom_dict.add_item('path', os.path.join(self.src_to_build, o)) + custom_dict.add_item('refType', 0) + custom_dict.add_item('sourceTree', 'SOURCE_ROOT') + objects_dict.add_item(self.custom_target_output_fileref[o], custom_dict) + + for buildfile in self.interpreter.get_build_def_files(): + basename = os.path.split(buildfile)[1] + buildfile_dict = PbxDict() + typestr = self.get_xcodetype(buildfile) + buildfile_dict.add_item('isa', 'PBXFileReference') + buildfile_dict.add_item('explicitFileType', '"' + typestr + '"') + buildfile_dict.add_item('name', f'"{basename}"') + buildfile_dict.add_item('path', f'"{buildfile}"') + buildfile_dict.add_item('refType', 0) + buildfile_dict.add_item('sourceTree', 'SOURCE_ROOT') + objects_dict.add_item(self.fileref_ids[buildfile], buildfile_dict) + + def generate_pbx_frameworks_buildphase(self, objects_dict): + for t in self.build_targets.values(): + bt_dict = PbxDict() + objects_dict.add_item(t.buildphasemap['Frameworks'], bt_dict, 'Frameworks') + bt_dict.add_item('isa', 'PBXFrameworksBuildPhase') + bt_dict.add_item('buildActionMask', 2147483647) + file_list = PbxArray() + bt_dict.add_item('files', file_list) for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.write_line('%s /* %s.framework in Frameworks */,\n' % (self.native_frameworks[f], f)) - self.indent_level -= 1 - self.write_line(');\n') - self.write_line('runOnlyForDeploymentPostprocessing = 0;\n') - self.indent_level -= 1 - self.write_line('};\n') - self.ofile.write('/* End PBXFrameworksBuildPhase section */\n') + file_list.add_item(self.native_frameworks[f], f'{f}.framework in Frameworks') + bt_dict.add_item('runOnlyForDeploymentPostprocessing', 0) - def generate_pbx_group(self): + def generate_pbx_group(self, objects_dict): groupmap = {} target_src_map = {} - for t in self.build.targets: + for t in self.build_targets: groupmap[t] = self.gen_id() target_src_map[t] = self.gen_id() - self.ofile.write('\n/* Begin PBXGroup section */\n') - sources_id = self.gen_id() + for t in self.custom_targets: + groupmap[t] = self.gen_id() + target_src_map[t] = self.gen_id() + projecttree_id = self.gen_id() resources_id = self.gen_id() products_id = self.gen_id() frameworks_id = self.gen_id() - self.write_line('%s = {' % self.maingroup_id) - self.indent_level += 1 - self.write_line('isa = PBXGroup;') - self.write_line('children = (') - self.indent_level += 1 - self.write_line('%s /* Sources */,' % sources_id) - self.write_line('%s /* Resources */,' % resources_id) - self.write_line('%s /* Products */,' % products_id) - self.write_line('%s /* Frameworks */,' % frameworks_id) - self.indent_level -= 1 - self.write_line(');') - self.write_line('sourceTree = "";') - self.indent_level -= 1 - self.write_line('};') - - # Sources - self.write_line('%s /* Sources */ = {' % sources_id) - self.indent_level += 1 - self.write_line('isa = PBXGroup;') - self.write_line('children = (') - self.indent_level += 1 - for t in self.build.targets: - self.write_line('%s /* %s */,' % (groupmap[t], t)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('name = Sources;') - self.write_line('sourceTree = "";') - self.indent_level -= 1 - self.write_line('};') - - self.write_line('%s /* Resources */ = {' % resources_id) - self.indent_level += 1 - self.write_line('isa = PBXGroup;') - self.write_line('children = (') - self.write_line(');') - self.write_line('name = Resources;') - self.write_line('sourceTree = "";') - self.indent_level -= 1 - self.write_line('};') - - self.write_line('%s /* Frameworks */ = {' % frameworks_id) - self.indent_level += 1 - self.write_line('isa = PBXGroup;') - self.write_line('children = (') + main_dict = PbxDict() + objects_dict.add_item(self.maingroup_id, main_dict) + main_dict.add_item('isa', 'PBXGroup') + main_children = PbxArray() + main_dict.add_item('children', main_children) + main_children.add_item(projecttree_id, 'Project tree') + main_children.add_item(resources_id, 'Resources') + main_children.add_item(products_id, 'Products') + main_children.add_item(frameworks_id, 'Frameworks') + main_dict.add_item('sourceTree', '""') + + self.add_projecttree(objects_dict, projecttree_id) + + resource_dict = PbxDict() + objects_dict.add_item(resources_id, resource_dict, 'Resources') + resource_dict.add_item('isa', 'PBXGroup') + resource_children = PbxArray() + resource_dict.add_item('children', resource_children) + resource_dict.add_item('name', 'Resources') + resource_dict.add_item('sourceTree', '""') + + frameworks_dict = PbxDict() + objects_dict.add_item(frameworks_id, frameworks_dict, 'Frameworks') + frameworks_dict.add_item('isa', 'PBXGroup') + frameworks_children = PbxArray() + frameworks_dict.add_item('children', frameworks_children) # write frameworks - self.indent_level += 1 - for t in self.build.targets.values(): + for t in self.build_targets.values(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.write_line('%s /* %s.framework */,\n' % (self.native_frameworks_fileref[f], f)) + frameworks_children.add_item(self.native_frameworks_fileref[f], f) - self.indent_level -= 1 - self.write_line(');') - self.write_line('name = Frameworks;') - self.write_line('sourceTree = "";') - self.indent_level -= 1 - self.write_line('};') - - # Targets - for t in self.build.targets: - self.write_line('%s /* %s */ = {' % (groupmap[t], t)) - self.indent_level += 1 - self.write_line('isa = PBXGroup;') - self.write_line('children = (') - self.indent_level += 1 - self.write_line('%s /* Source files */,' % target_src_map[t]) - self.indent_level -= 1 - self.write_line(');') - self.write_line('name = "%s";' % t) - self.write_line('sourceTree = "";') - self.indent_level -= 1 - self.write_line('};') - self.write_line('%s /* Source files */ = {' % target_src_map[t]) - self.indent_level += 1 - self.write_line('isa = PBXGroup;') - self.write_line('children = (') - self.indent_level += 1 - for s in self.build.targets[t].sources: - s = os.path.join(s.subdir, s.fname) - if isinstance(s, str): - self.write_line('%s /* %s */,' % (self.filemap[s], s)) - for o in self.build.targets[t].objects: - o = os.path.join(self.build.targets[t].subdir, o) - self.write_line('%s /* %s */,' % (self.filemap[o], o)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('name = "Source files";') - self.write_line('sourceTree = "";') - self.indent_level -= 1 - self.write_line('};') + frameworks_dict.add_item('name', 'Frameworks') + frameworks_dict.add_item('sourceTree', '""') + + for tname, t in self.custom_targets.items(): + target_dict = PbxDict() + objects_dict.add_item(groupmap[tname], target_dict, tname) + target_dict.add_item('isa', 'PBXGroup') + target_children = PbxArray() + target_dict.add_item('children', target_children) + target_children.add_item(target_src_map[tname], 'Source files') + if t.subproject: + target_dict.add_item('name', f'"{t.subproject} • {t.name}"') + else: + target_dict.add_item('name', f'"{t.name}"') + target_dict.add_item('sourceTree', '""') + source_files_dict = PbxDict() + objects_dict.add_item(target_src_map[tname], source_files_dict, 'Source files') + source_files_dict.add_item('isa', 'PBXGroup') + source_file_children = PbxArray() + source_files_dict.add_item('children', source_file_children) + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + elif isinstance(s, str): + s = os.path.joni(t.subdir, s) + else: + continue + source_file_children.add_item(self.fileref_ids[(tname, s)], s) + source_files_dict.add_item('name', '"Source files"') + source_files_dict.add_item('sourceTree', '""') # And finally products - self.write_line('%s /* Products */ = {' % products_id) - self.indent_level += 1 - self.write_line('isa = PBXGroup;') - self.write_line('children = (') - self.indent_level += 1 - for t in self.build.targets: - self.write_line('%s /* %s */,' % (self.target_filemap[t], t)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('name = Products;') - self.write_line('sourceTree = "";') - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End PBXGroup section */\n') + product_dict = PbxDict() + objects_dict.add_item(products_id, product_dict, 'Products') + product_dict.add_item('isa', 'PBXGroup') + product_children = PbxArray() + product_dict.add_item('children', product_children) + for t in self.build_targets: + product_children.add_item(self.target_filemap[t], t) + product_dict.add_item('name', 'Products') + product_dict.add_item('sourceTree', '""') + + def write_group_target_entry(self, objects_dict, t): + tid = t.get_id() + group_id = self.gen_id() + target_dict = PbxDict() + objects_dict.add_item(group_id, target_dict, tid) + target_dict.add_item('isa', 'PBXGroup') + target_children = PbxArray() + target_dict.add_item('children', target_children) + target_dict.add_item('name', f'"{t} · target"') + target_dict.add_item('sourceTree', '""') + source_files_dict = PbxDict() + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + elif isinstance(s, str): + s = os.path.joni(t.subdir, s) + else: + continue + target_children.add_item(self.fileref_ids[(tid, s)], s) + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + # Do not show built object files in the project tree. + continue + if isinstance(o, mesonlib.File): + o = os.path.join(o.subdir, o.fname) + else: + o = os.path.join(t.subdir, o) + target_children.add_item(self.fileref_ids[(tid, o)], o) + source_files_dict.add_item('name', '"Source files"') + source_files_dict.add_item('sourceTree', '""') + return group_id + + def add_projecttree(self, objects_dict, projecttree_id): + root_dict = PbxDict() + objects_dict.add_item(projecttree_id, root_dict, "Root of project tree") + root_dict.add_item('isa', 'PBXGroup') + target_children = PbxArray() + root_dict.add_item('children', target_children) + root_dict.add_item('name', '"Project root"') + root_dict.add_item('sourceTree', '""') + + project_tree = self.generate_project_tree() + self.write_tree(objects_dict, project_tree, target_children, '') + + def write_tree(self, objects_dict, tree_node, children_array, current_subdir): + for subdir_name, subdir_node in tree_node.subdirs.items(): + subdir_dict = PbxDict() + subdir_children = PbxArray() + subdir_id = self.gen_id() + objects_dict.add_item(subdir_id, subdir_dict) + children_array.add_item(subdir_id) + subdir_dict.add_item('isa', 'PBXGroup') + subdir_dict.add_item('children', subdir_children) + subdir_dict.add_item('name', f'"{subdir_name}"') + subdir_dict.add_item('sourceTree', '""') + self.write_tree(objects_dict, subdir_node, subdir_children, os.path.join(current_subdir, subdir_name)) + for target in tree_node.targets: + group_id = self.write_group_target_entry(objects_dict, target) + children_array.add_item(group_id) + potentials = [os.path.join(current_subdir, 'meson.build'), + os.path.join(current_subdir, 'meson_options.txt')] + for bf in potentials: + i = self.fileref_ids.get(bf, None) + if i: + children_array.add_item(i) + + def generate_project_tree(self): + tree_info = FileTreeEntry() + for tname, t in self.build_targets.items(): + self.add_target_to_tree(tree_info, t) + return tree_info + + def add_target_to_tree(self, tree_root, t): + current_node = tree_root + path_segments = t.subdir.split('/') + for s in path_segments: + if not s: + continue + if s not in current_node.subdirs: + current_node.subdirs[s] = FileTreeEntry() + current_node = current_node.subdirs[s] + current_node.targets.append(t) - def generate_pbx_native_target(self): - self.ofile.write('\n/* Begin PBXNativeTarget section */\n') + def generate_pbx_native_target(self, objects_dict): for tname, idval in self.native_targets.items(): - t = self.build.targets[tname] - self.write_line('%s /* %s */ = {' % (idval, tname)) - self.indent_level += 1 - self.write_line('isa = PBXNativeTarget;') - self.write_line('buildConfigurationList = %s /* Build configuration list for PBXNativeTarget "%s" */;' - % (self.buildconflistmap[tname], tname)) - self.write_line('buildPhases = (') - self.indent_level += 1 + ntarget_dict = PbxDict() + t = self.build_targets[tname] + objects_dict.add_item(idval, ntarget_dict, tname) + ntarget_dict.add_item('isa', 'PBXNativeTarget') + ntarget_dict.add_item('buildConfigurationList', self.buildconflistmap[tname], f'Build configuration list for PBXNativeTarget "{tname}"') + buildphases_array = PbxArray() + ntarget_dict.add_item('buildPhases', buildphases_array) + generator_id = 0 + for g in t.generated: + # Custom target are handled via inter-target dependencies. + # Generators are built as a shellscriptbuildphase. + if isinstance(g, build.GeneratedList): + buildphases_array.add_item(self.shell_targets[(tname, generator_id)], f'Generator {generator_id}/{tname}') + generator_id += 1 for bpname, bpval in t.buildphasemap.items(): - self.write_line('%s /* %s yyy */,' % (bpval, bpname)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('buildRules = (') - self.write_line(');') - self.write_line('dependencies = (') - self.indent_level += 1 - for lt in self.build.targets[tname].link_targets: + buildphases_array.add_item(bpval, f'{bpname} yyy') + ntarget_dict.add_item('buildRules', PbxArray()) + dep_array = PbxArray() + ntarget_dict.add_item('dependencies', dep_array) + dep_array.add_item(self.regen_dependency_id) + # These dependencies only tell Xcode that the deps must be built + # before this one. They don't set up linkage or anything + # like that. Those are set up in the XCBuildConfiguration. + for lt in self.build_targets[tname].link_targets: # NOT DOCUMENTED, may need to make different links # to same target have different targetdependency item. - idval = self.pbx_dep_map[lt.get_id()] - self.write_line('%s /* PBXTargetDependency */,' % idval) - self.indent_level -= 1 - self.write_line(");") - self.write_line('name = "%s";' % tname) - self.write_line('productName = "%s";' % tname) - self.write_line('productReference = %s /* %s */;' % (self.target_filemap[tname], tname)) + if isinstance(lt, build.CustomTarget): + dep_array.add_item(self.pbx_custom_dep_map[lt.get_id()], lt.name) + elif isinstance(lt, build.CustomTargetIndex): + dep_array.add_item(self.pbx_custom_dep_map[lt.target.get_id()], lt.target.name) + else: + idval = self.pbx_dep_map[lt.get_id()] + dep_array.add_item(idval, 'PBXTargetDependency') + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + source_target_id = o.target.get_id() + idval = self.pbx_dep_map[source_target_id] + dep_array.add_item(idval, 'PBXTargetDependency') + generator_id = 0 + for o in t.generated: + if isinstance(o, build.CustomTarget): + dep_array.add_item(self.pbx_custom_dep_map[o.get_id()], o.name) + elif isinstance(o, build.CustomTargetIndex): + dep_array.add_item(self.pbx_custom_dep_map[o.target.get_id()], o.target.name) + + generator_id += 1 + + ntarget_dict.add_item('name', f'"{tname}"') + ntarget_dict.add_item('productName', f'"{tname}"') + ntarget_dict.add_item('productReference', self.target_filemap[tname], tname) if isinstance(t, build.Executable): typestr = 'com.apple.product-type.tool' elif isinstance(t, build.StaticLibrary): @@ -521,394 +1103,609 @@ typestr = 'com.apple.product-type.library.dynamic' else: raise MesonException('Unknown target type for %s' % tname) - self.write_line('productType = "%s";' % typestr) - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End PBXNativeTarget section */\n') - - def generate_pbx_project(self): - self.ofile.write('\n/* Begin PBXProject section */\n') - self.write_line('%s /* Project object */ = {' % self.project_uid) - self.indent_level += 1 - self.write_line('isa = PBXProject;') - self.write_line('attributes = {') - self.indent_level += 1 - self.write_line('BuildIndependentTargetsInParallel = YES;') - self.indent_level -= 1 - self.write_line('};') - conftempl = 'buildConfigurationList = %s /* Build configuration list for PBXProject "%s" */;' - self.write_line(conftempl % (self.project_conflist, self.build.project_name)) - self.write_line('buildSettings = {') - self.write_line('};') - self.write_line('buildStyles = (') - self.indent_level += 1 + ntarget_dict.add_item('productType', f'"{typestr}"') + + def generate_pbx_project(self, objects_dict): + project_dict = PbxDict() + objects_dict.add_item(self.project_uid, project_dict, 'Project object') + project_dict.add_item('isa', 'PBXProject') + attr_dict = PbxDict() + project_dict.add_item('attributes', attr_dict) + attr_dict.add_item('BuildIndependentTargetsInParallel', 'YES') + project_dict.add_item('buildConfigurationList', self.project_conflist, f'Build configuration list for PBXProject "{self.build.project_name}"') + project_dict.add_item('buildSettings', PbxDict()) + style_arr = PbxArray() + project_dict.add_item('buildStyles', style_arr) for name, idval in self.buildstylemap.items(): - self.write_line('%s /* %s */,' % (idval, name)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('compatibilityVersion = "Xcode 3.2";') - self.write_line('hasScannedForEncodings = 0;') - self.write_line('mainGroup = %s;' % self.maingroup_id) - self.write_line('projectDirPath = "%s";' % self.build_to_src) - self.write_line('projectRoot = "";') - self.write_line('targets = (') - self.indent_level += 1 - self.write_line('%s /* ALL_BUILD */,' % self.all_id) - self.write_line('%s /* RUN_TESTS */,' % self.test_id) - for t in self.build.targets: - self.write_line('%s /* %s */,' % (self.native_targets[t], t)) - self.indent_level -= 1 - self.write_line(');') - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End PBXProject section */\n') - - def generate_pbx_shell_build_phase(self, test_data): - self.ofile.write('\n/* Begin PBXShellScriptBuildPhase section */\n') - self.write_line('%s /* ShellScript */ = {' % self.test_command_id) - self.indent_level += 1 - self.write_line('isa = PBXShellScriptBuildPhase;') - self.write_line('buildActionMask = 2147483647;') - self.write_line('files = (') - self.write_line(');') - self.write_line('inputPaths = (') - self.write_line(');') - self.write_line('outputPaths = (') - self.write_line(');') - self.write_line('runOnlyForDeploymentPostprocessing = 0;') - self.write_line('shellPath = /bin/sh;') - cmd = mesonlib.meson_command + ['test', test_data, '-C', self.environment.get_build_dir()] + style_arr.add_item(idval, name) + project_dict.add_item('compatibilityVersion', '"Xcode 3.2"') + project_dict.add_item('hasScannedForEncodings', 0) + project_dict.add_item('mainGroup', self.maingroup_id) + project_dict.add_item('projectDirPath', '"' + self.environment.get_source_dir() + '"') + project_dict.add_item('projectRoot', '""') + targets_arr = PbxArray() + project_dict.add_item('targets', targets_arr) + targets_arr.add_item(self.all_id, 'ALL_BUILD') + targets_arr.add_item(self.test_id, 'RUN_TESTS') + targets_arr.add_item(self.regen_id, 'REGENERATE') + for t in self.build_targets: + targets_arr.add_item(self.native_targets[t], t) + for t in self.custom_targets: + targets_arr.add_item(self.custom_aggregate_targets[t], t) + + def generate_pbx_shell_build_phase(self, objects_dict): + self.generate_test_shell_build_phase(objects_dict) + self.generate_regen_shell_build_phase(objects_dict) + self.generate_custom_target_shell_build_phases(objects_dict) + self.generate_generator_target_shell_build_phases(objects_dict) + + def generate_test_shell_build_phase(self, objects_dict): + shell_dict = PbxDict() + objects_dict.add_item(self.test_command_id, shell_dict, 'ShellScript') + shell_dict.add_item('isa', 'PBXShellScriptBuildPhase') + shell_dict.add_item('buildActionMask', 2147483647) + shell_dict.add_item('files', PbxArray()) + shell_dict.add_item('inputPaths', PbxArray()) + shell_dict.add_item('outputPaths', PbxArray()) + shell_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + shell_dict.add_item('shellPath', '/bin/sh') + cmd = mesonlib.get_meson_command() + ['test', '--no-rebuild', '-C', self.environment.get_build_dir()] cmdstr = ' '.join(["'%s'" % i for i in cmd]) - self.write_line('shellScript = "%s";' % cmdstr) - self.write_line('showEnvVarsInLog = 0;') - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End PBXShellScriptBuildPhase section */\n') - - def generate_pbx_sources_build_phase(self): - self.ofile.write('\n/* Begin PBXSourcesBuildPhase section */\n') - for name in self.source_phase.keys(): - t = self.build.targets[name] - self.write_line('%s /* Sources */ = {' % (t.buildphasemap[name])) - self.indent_level += 1 - self.write_line('isa = PBXSourcesBuildPhase;') - self.write_line('buildActionMask = 2147483647;') - self.write_line('files = (') - self.indent_level += 1 - for s in self.build.targets[name].sources: + shell_dict.add_item('shellScript', f'"{cmdstr}"') + shell_dict.add_item('showEnvVarsInLog', 0) + + def generate_regen_shell_build_phase(self, objects_dict): + shell_dict = PbxDict() + objects_dict.add_item(self.regen_command_id, shell_dict, 'ShellScript') + shell_dict.add_item('isa', 'PBXShellScriptBuildPhase') + shell_dict.add_item('buildActionMask', 2147483647) + shell_dict.add_item('files', PbxArray()) + shell_dict.add_item('inputPaths', PbxArray()) + shell_dict.add_item('outputPaths', PbxArray()) + shell_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + shell_dict.add_item('shellPath', '/bin/sh') + cmd = mesonlib.get_meson_command() + ['--internal', 'regencheck', os.path.join(self.environment.get_build_dir(), 'meson-private')] + cmdstr = ' '.join(["'%s'" % i for i in cmd]) + shell_dict.add_item('shellScript', f'"{cmdstr}"') + shell_dict.add_item('showEnvVarsInLog', 0) + + def generate_custom_target_shell_build_phases(self, objects_dict): + # Custom targets are shell build phases in Xcode terminology. + for tname, t in self.custom_targets.items(): + if not isinstance(t, build.CustomTarget): + continue + (srcs, ofilenames, cmd) = self.eval_custom_target_command(t, absolute_outputs=True) + fixed_cmd, _ = self.as_meson_exe_cmdline(cmd[0], + cmd[1:], + #workdir=None, + env=t.env) + custom_dict = PbxDict() + objects_dict.add_item(self.shell_targets[tname], custom_dict, f'/* Custom target {tname} */') + custom_dict.add_item('isa', 'PBXShellScriptBuildPhase') + custom_dict.add_item('buildActionMask', 2147483647) + custom_dict.add_item('files', PbxArray()) + custom_dict.add_item('inputPaths', PbxArray()) + outarray = PbxArray() + custom_dict.add_item('name', '"Generate {}."'.format(ofilenames[0])) + custom_dict.add_item('outputPaths', outarray) + for o in ofilenames: + outarray.add_item(os.path.join(self.environment.get_build_dir(), o)) + custom_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + custom_dict.add_item('shellPath', '/bin/sh') + workdir = self.environment.get_build_dir() + quoted_cmd = [] + for c in fixed_cmd: + quoted_cmd.append(c.replace('"', chr(92) + '"')) + cmdstr = ' '.join([f"\\'{x}\\'" for x in quoted_cmd]) + custom_dict.add_item('shellScript', f'"cd {workdir}; {cmdstr}"') + custom_dict.add_item('showEnvVarsInLog', 0) + + def generate_generator_target_shell_build_phases(self, objects_dict): + for tname, t in self.build_targets.items(): + generator_id = 0 + for genlist in t.generated: + if isinstance(genlist, build.GeneratedList): + self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict) + generator_id += 1 + for tname, t in self.custom_targets.items(): + generator_id = 0 + for genlist in t.sources: + if isinstance(genlist, build.GeneratedList): + self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict) + generator_id += 1 + + def generate_single_generator_phase(self, tname, t, genlist, generator_id, objects_dict): + generator = genlist.get_generator() + exe = generator.get_exe() + exe_arr = self.build_target_to_cmd_array(exe) + workdir = self.environment.get_build_dir() + gen_dict = PbxDict() + objects_dict.add_item(self.shell_targets[(tname, generator_id)], gen_dict, f'"Generator {generator_id}/{tname}"') + infilelist = genlist.get_inputs() + outfilelist = genlist.get_outputs() + gen_dict.add_item('isa', 'PBXShellScriptBuildPhase') + gen_dict.add_item('buildActionMask', 2147483647) + gen_dict.add_item('files', PbxArray()) + gen_dict.add_item('inputPaths', PbxArray()) + gen_dict.add_item('name', f'"Generator {generator_id}/{tname}"') + commands = [["cd", workdir]] # Array of arrays, each one a single command, will get concatenated below. + k = (tname, generator_id) + ofile_abs = self.generator_outputs[k] + outarray = PbxArray() + gen_dict.add_item('outputPaths', outarray) + for of in ofile_abs: + outarray.add_item(of) + for i in infilelist: + # This might be needed to be added to inputPaths. It's not done yet as it is + # unclear whether it is necessary, what actually happens when it is defined + # and currently the build works without it. + #infile_abs = i.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) + infilename = i.rel_to_builddir(self.build_to_src) + base_args = generator.get_arglist(infilename) + for o_base in genlist.get_outputs_for(i): + o = os.path.join(self.get_target_private_dir(t), o_base) + args = [] + for arg in base_args: + arg = arg.replace("@INPUT@", infilename) + arg = arg.replace('@OUTPUT@', o).replace('@BUILD_DIR@', self.get_target_private_dir(t)) + arg = arg.replace("@CURRENT_SOURCE_DIR@", os.path.join(self.build_to_src, t.subdir)) + args.append(arg) + args = self.replace_outputs(args, self.get_target_private_dir(t), outfilelist) + args = self.replace_extra_args(args, genlist) + if generator.capture: + # When capturing, stdout is the output. Forward it with the shell. + full_command = ['('] + exe_arr + args + ['>', o, ')'] + else: + full_command = exe_arr + args + commands.append(full_command) + gen_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + gen_dict.add_item('shellPath', '/bin/sh') + quoted_cmds = [] + for cmnd in commands: + q = [] + for c in cmnd: + if ' ' in c: + q.append(f'\\"{c}\\"') + else: + q.append(c) + quoted_cmds.append(' '.join(q)) + cmdstr = '"' + ' && '.join(quoted_cmds) + '"' + gen_dict.add_item('shellScript', cmdstr) + gen_dict.add_item('showEnvVarsInLog', 0) + + def generate_pbx_sources_build_phase(self, objects_dict): + for name in self.source_phase: + phase_dict = PbxDict() + t = self.build_targets[name] + objects_dict.add_item(t.buildphasemap[name], phase_dict, 'Sources') + phase_dict.add_item('isa', 'PBXSourcesBuildPhase') + phase_dict.add_item('buildActionMask', 2147483647) + file_arr = PbxArray() + phase_dict.add_item('files', file_arr) + for s in self.build_targets[name].sources: s = os.path.join(s.subdir, s.fname) if not self.environment.is_header(s): - self.write_line('%s /* %s */,' % (self.buildmap[s], os.path.join(self.environment.get_source_dir(), s))) - self.indent_level -= 1 - self.write_line(');') - self.write_line('runOnlyForDeploymentPostprocessing = 0;') - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End PBXSourcesBuildPhase section */\n') + file_arr.add_item(self.buildfile_ids[(name, s)], os.path.join(self.environment.get_source_dir(), s)) + generator_id = 0 + for gt in t.generated: + if isinstance(gt, build.CustomTarget): + (srcs, ofilenames, cmd) = self.eval_custom_target_command(gt) + for o in ofilenames: + file_arr.add_item(self.custom_target_output_buildfile[o], + os.path.join(self.environment.get_build_dir(), o)) + elif isinstance(gt, build.CustomTargetIndex): + for o in gt.get_outputs(): + file_arr.add_item(self.custom_target_output_buildfile[o], + os.path.join(self.environment.get_build_dir(), o)) + elif isinstance(gt, build.GeneratedList): + genfiles = self.generator_buildfile_ids[(name, generator_id)] + generator_id += 1 + for o in genfiles: + file_arr.add_item(o) + else: + raise RuntimeError('Unknown input type: ' + str(gt)) + phase_dict.add_item('runOnlyForDeploymentPostprocessing', 0) - def generate_pbx_target_dependency(self): + def generate_pbx_target_dependency(self, objects_dict): + all_dict = PbxDict() + objects_dict.add_item(self.build_all_tdep_id, all_dict, 'ALL_BUILD') + all_dict.add_item('isa', 'PBXTargetDependency') + all_dict.add_item('target', self.all_id) targets = [] - for t in self.build.targets: + targets.append((self.regen_dependency_id, self.regen_id, 'REGEN', None)) + for t in self.build_targets: idval = self.pbx_dep_map[t] # VERIFY: is this correct? targets.append((idval, self.native_targets[t], t, self.containerproxy_map[t])) + for t in self.custom_targets: + idval = self.pbx_custom_dep_map[t] + targets.append((idval, self.custom_aggregate_targets[t], t, None))#self.containerproxy_map[t])) + # Sort object by ID sorted_targets = sorted(targets, key=operator.itemgetter(0)) - self.ofile.write('\n/* Begin PBXTargetDependency section */\n') for t in sorted_targets: - self.write_line('%s /* PBXTargetDependency */ = {' % t[0]) - self.indent_level += 1 - self.write_line('isa = PBXTargetDependency;') - self.write_line('target = %s /* %s */;' % (t[1], t[2])) - self.write_line('targetProxy = %s /* PBXContainerItemProxy */;' % t[3]) - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End PBXTargetDependency section */\n') + t_dict = PbxDict() + objects_dict.add_item(t[0], t_dict, 'PBXTargetDependency') + t_dict.add_item('isa', 'PBXTargetDependency') + t_dict.add_item('target', t[1], t[2]) + if t[3] is not None: + t_dict.add_item('targetProxy', t[3], 'PBXContainerItemProxy') - def generate_xc_build_configuration(self): - self.ofile.write('\n/* Begin XCBuildConfiguration section */\n') + def generate_xc_build_configuration(self, objects_dict): # First the setup for the toplevel project. for buildtype in self.buildtypes: - self.write_line('%s /* %s */ = {' % (self.project_configurations[buildtype], buildtype)) - self.indent_level += 1 - self.write_line('isa = XCBuildConfiguration;') - self.write_line('buildSettings = {') - self.indent_level += 1 - self.write_line('ARCHS = "$(ARCHS_STANDARD_64_BIT)";') - self.write_line('ONLY_ACTIVE_ARCH = YES;') - self.write_line('SDKROOT = "macosx";') - self.write_line('SYMROOT = "%s/build";' % self.environment.get_build_dir()) - self.indent_level -= 1 - self.write_line('};') - self.write_line('name = "%s";' % buildtype) - self.indent_level -= 1 - self.write_line('};') + bt_dict = PbxDict() + objects_dict.add_item(self.project_configurations[buildtype], bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('ARCHS', '"$(NATIVE_ARCH_ACTUAL)"') + settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') + settings_dict.add_item('SWIFT_VERSION', '5.0') + settings_dict.add_item('SDKROOT', '"macosx"') + settings_dict.add_item('SYMROOT', '"%s/build"' % self.environment.get_build_dir()) + bt_dict.add_item('name', f'"{buildtype}"') # Then the all target. for buildtype in self.buildtypes: - self.write_line('%s /* %s */ = {' % (self.buildall_configurations[buildtype], buildtype)) - self.indent_level += 1 - self.write_line('isa = XCBuildConfiguration;') - self.write_line('buildSettings = {') - self.indent_level += 1 - self.write_line('COMBINE_HIDPI_IMAGES = YES;') - self.write_line('GCC_GENERATE_DEBUGGING_SYMBOLS = NO;') - self.write_line('GCC_INLINES_ARE_PRIVATE_EXTERN = NO;') - self.write_line('GCC_OPTIMIZATION_LEVEL = 0;') - self.write_line('GCC_PREPROCESSOR_DEFINITIONS = "";') - self.write_line('GCC_SYMBOLS_PRIVATE_EXTERN = NO;') - self.write_line('INSTALL_PATH = "";') - self.write_line('OTHER_CFLAGS = " ";') - self.write_line('OTHER_LDFLAGS = " ";') - self.write_line('OTHER_REZFLAGS = "";') - self.write_line('PRODUCT_NAME = ALL_BUILD;') - self.write_line('SECTORDER_FLAGS = "";') - self.write_line('SYMROOT = "%s";' % self.environment.get_build_dir()) - self.write_line('USE_HEADERMAP = NO;') - self.write_build_setting_line('WARNING_CFLAGS', ['-Wmost', '-Wno-four-char-constants', '-Wno-unknown-pragmas']) - self.indent_level -= 1 - self.write_line('};') - self.write_line('name = "%s";' % buildtype) - self.indent_level -= 1 - self.write_line('};') + bt_dict = PbxDict() + objects_dict.add_item(self.buildall_configurations[buildtype], bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('SYMROOT', '"%s"' % self.environment.get_build_dir()) + warn_array = PbxArray() + warn_array.add_item('"$(inherited)"') + settings_dict.add_item('WARNING_CFLAGS', warn_array) + + bt_dict.add_item('name', f'"{buildtype}"') # Then the test target. for buildtype in self.buildtypes: - self.write_line('%s /* %s */ = {' % (self.test_configurations[buildtype], buildtype)) - self.indent_level += 1 - self.write_line('isa = XCBuildConfiguration;') - self.write_line('buildSettings = {') - self.indent_level += 1 - self.write_line('COMBINE_HIDPI_IMAGES = YES;') - self.write_line('GCC_GENERATE_DEBUGGING_SYMBOLS = NO;') - self.write_line('GCC_INLINES_ARE_PRIVATE_EXTERN = NO;') - self.write_line('GCC_OPTIMIZATION_LEVEL = 0;') - self.write_line('GCC_PREPROCESSOR_DEFINITIONS = "";') - self.write_line('GCC_SYMBOLS_PRIVATE_EXTERN = NO;') - self.write_line('INSTALL_PATH = "";') - self.write_line('OTHER_CFLAGS = " ";') - self.write_line('OTHER_LDFLAGS = " ";') - self.write_line('OTHER_REZFLAGS = "";') - self.write_line('PRODUCT_NAME = RUN_TESTS;') - self.write_line('SECTORDER_FLAGS = "";') - self.write_line('SYMROOT = "%s";' % self.environment.get_build_dir()) - self.write_line('USE_HEADERMAP = NO;') - self.write_build_setting_line('WARNING_CFLAGS', ['-Wmost', '-Wno-four-char-constants', '-Wno-unknown-pragmas']) - self.indent_level -= 1 - self.write_line('};') - self.write_line('name = "%s";' % buildtype) - self.indent_level -= 1 - self.write_line('};') + bt_dict = PbxDict() + objects_dict.add_item(self.test_configurations[buildtype], bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('SYMROOT', '"%s"' % self.environment.get_build_dir()) + warn_array = PbxArray() + settings_dict.add_item('WARNING_CFLAGS', warn_array) + warn_array.add_item('"$(inherited)"') + bt_dict.add_item('name', f'"{buildtype}"') # Now finally targets. - langnamemap = {'c': 'C', 'cpp': 'CPLUSPLUS', 'objc': 'OBJC', 'objcpp': 'OBJCPLUSPLUS'} - for target_name, target in self.build.targets.items(): - for buildtype in self.buildtypes: - dep_libs = [] - links_dylib = False - headerdirs = [] - for d in target.include_dirs: - for sd in d.incdirs: - cd = os.path.join(d.curdir, sd) - headerdirs.append(os.path.join(self.environment.get_source_dir(), cd)) - headerdirs.append(os.path.join(self.environment.get_build_dir(), cd)) - for l in target.link_targets: - abs_path = os.path.join(self.environment.get_build_dir(), - l.subdir, buildtype, l.get_filename()) - dep_libs.append("'%s'" % abs_path) - if isinstance(l, build.SharedLibrary): - links_dylib = True - if links_dylib: - dep_libs = ['-Wl,-search_paths_first', '-Wl,-headerpad_max_install_names'] + dep_libs - dylib_version = None - if isinstance(target, build.SharedLibrary): - ldargs = ['-dynamiclib', '-Wl,-headerpad_max_install_names'] + dep_libs - install_path = os.path.join(self.environment.get_build_dir(), target.subdir, buildtype) - dylib_version = target.soversion + for target_name, target in self.build_targets.items(): + self.generate_single_build_target(objects_dict, target_name, target) + + for target_name, target in self.custom_targets.items(): + bt_dict = PbxDict() + objects_dict.add_item(self.buildconfmap[target_name][buildtype], bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('ARCHS', '"$(NATIVE_ARCH_ACTUAL)"') + settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') + settings_dict.add_item('SDKROOT', '"macosx"') + settings_dict.add_item('SYMROOT', '"%s/build"' % self.environment.get_build_dir()) + bt_dict.add_item('name', f'"{buildtype}"') + + def determine_internal_dep_link_args(self, target, buildtype): + links_dylib = False + dep_libs = [] + for l in target.link_targets: + if isinstance(target, build.SharedModule) and isinstance(l, build.Executable): + continue + if isinstance(l, build.CustomTargetIndex): + rel_dir = self.get_custom_target_output_dir(l.target) + libname = l.get_filename() + elif isinstance(l, build.CustomTarget): + rel_dir = self.get_custom_target_output_dir(l) + libname = l.get_filename() + else: + rel_dir = self.get_target_dir(l) + libname = l.get_filename() + abs_path = os.path.join(self.environment.get_build_dir(), rel_dir, libname) + dep_libs.append("'%s'" % abs_path) + if isinstance(l, build.SharedLibrary): + links_dylib = True + if isinstance(l, build.StaticLibrary): + (sub_libs, sub_links_dylib) = self.determine_internal_dep_link_args(l, buildtype) + dep_libs += sub_libs + links_dylib = links_dylib or sub_links_dylib + return (dep_libs, links_dylib) + + def generate_single_build_target(self, objects_dict, target_name, target): + for buildtype in self.buildtypes: + dep_libs = [] + links_dylib = False + headerdirs = [] + for d in target.include_dirs: + for sd in d.incdirs: + cd = os.path.join(d.curdir, sd) + headerdirs.append(os.path.join(self.environment.get_source_dir(), cd)) + headerdirs.append(os.path.join(self.environment.get_build_dir(), cd)) + for extra in d.extra_build_dirs: + headerdirs.append(os.path.join(self.environment.get_build_dir(), extra)) + (dep_libs, links_dylib) = self.determine_internal_dep_link_args(target, buildtype) + if links_dylib: + dep_libs = ['-Wl,-search_paths_first', '-Wl,-headerpad_max_install_names'] + dep_libs + dylib_version = None + if isinstance(target, build.SharedLibrary): + if isinstance(target, build.SharedModule): + ldargs = [] else: - ldargs = dep_libs - install_path = '' - if dylib_version is not None: - product_name = target.get_basename() + '.' + dylib_version + ldargs = ['-dynamiclib'] + ldargs += ['-Wl,-headerpad_max_install_names'] + dep_libs + install_path = os.path.join(self.environment.get_build_dir(), target.subdir, buildtype) + dylib_version = target.soversion + else: + ldargs = dep_libs + install_path = '' + if dylib_version is not None: + product_name = target.get_basename() + '.' + dylib_version + else: + product_name = target.get_basename() + ldargs += target.link_args + # Swift is special. Again. You can't mix Swift with other languages + # in the same target. Thus for Swift we only use + if self.is_swift_target(target): + linker, stdlib_args = target.compilers['swift'], [] + else: + linker, stdlib_args = self.determine_linker_and_stdlib_args(target) + if not isinstance(target, build.StaticLibrary): + ldargs += self.build.get_project_link_args(linker, target.subproject, target.for_machine) + ldargs += self.build.get_global_link_args(linker, target.for_machine) + cargs = [] + for dep in target.get_external_deps(): + cargs += dep.get_compile_args() + ldargs += dep.get_link_args() + for o in target.objects: + # Add extracted objects to the link line by hand. + if isinstance(o, build.ExtractedObjects): + added_objs = set() + for objname_rel in o.get_outputs(self): + objname_abs = os.path.join(self.environment.get_build_dir(), o.target.subdir, objname_rel) + if objname_abs not in added_objs: + added_objs.add(objname_abs) + ldargs += [r'\"' + objname_abs + r'\"'] + generator_id = 0 + for o in target.generated: + if isinstance(o, build.GeneratedList): + outputs = self.generator_outputs[target_name, generator_id] + generator_id += 1 + for o_abs in outputs: + if o_abs.endswith('.o') or o_abs.endswith('.obj'): + ldargs += [r'\"' + o_abs + r'\"'] else: - product_name = target.get_basename() - ldargs += target.link_args - for dep in target.get_external_deps(): - ldargs += dep.get_link_args() - ldstr = ' '.join(ldargs) - valid = self.buildconfmap[target_name][buildtype] - langargs = {} - for lang in self.environment.coredata.compilers[target.for_machine]: - if lang not in langnamemap: - continue - # Add compile args added using add_project_arguments() - pargs = self.build.projects_args[target.for_machine].get(target.subproject, {}).get(lang, []) - # Add compile args added using add_global_arguments() - # These override per-project arguments - gargs = self.build.global_args[target.for_machine].get(lang, []) - targs = target.get_extra_args(lang) - args = pargs + gargs + targs - if args: - langargs[langnamemap[lang]] = args - symroot = os.path.join(self.environment.get_build_dir(), target.subdir) - self.write_line('%s /* %s */ = {' % (valid, buildtype)) - self.indent_level += 1 - self.write_line('isa = XCBuildConfiguration;') - self.write_line('buildSettings = {') - self.indent_level += 1 - self.write_line('COMBINE_HIDPI_IMAGES = YES;') + if isinstance(o, build.CustomTarget): + (srcs, ofilenames, cmd) = self.eval_custom_target_command(o) + for ofname in ofilenames: + if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS: + ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"'] + elif isinstance(o, build.CustomTargetIndex): + for ofname in o.get_outputs(): + if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS: + ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"'] + else: + raise RuntimeError(o) + if isinstance(target, build.SharedModule): + options = self.environment.coredata.options + ldargs += linker.get_std_shared_module_link_args(options) + elif isinstance(target, build.SharedLibrary): + ldargs += linker.get_std_shared_lib_link_args() + ldstr = ' '.join(ldargs) + valid = self.buildconfmap[target_name][buildtype] + langargs = {} + for lang in self.environment.coredata.compilers[target.for_machine]: + if lang not in LANGNAMEMAP: + continue + compiler = target.compilers.get(lang) + if compiler is None: + continue + # Start with warning args + warn_args = compiler.get_warn_args(self.get_option_for_target(OptionKey('warning_level'), target)) + copt_proxy = self.get_compiler_options_for_target(target) + std_args = compiler.get_option_compile_args(copt_proxy) + # Add compile args added using add_project_arguments() + pargs = self.build.projects_args[target.for_machine].get(target.subproject, {}).get(lang, []) + # Add compile args added using add_global_arguments() + # These override per-project arguments + gargs = self.build.global_args[target.for_machine].get(lang, []) + targs = target.get_extra_args(lang) + args = warn_args + std_args + pargs + gargs + targs + if lang == 'swift': + # For some reason putting Swift module dirs in HEADER_SEARCH_PATHS does not work, + # but adding -I/path to manual args does work. + swift_dep_dirs = self.determine_swift_dep_dirs(target) + for d in swift_dep_dirs: + args += compiler.get_include_args(d, False) + if args: + lang_cargs = cargs + if compiler and target.implicit_include_directories: + # It is unclear what is the cwd when xcode runs. -I. does not seem to + # add the root build dir to the search path. So add an absolute path instead. + # This may break reproducible builds, in which case patches are welcome. + lang_cargs += self.get_custom_target_dir_include_args(target, compiler, absolute_path=True) + # Xcode can not handle separate compilation flags for C and ObjectiveC. They are both + # put in OTHER_CFLAGS. Same with C++ and ObjectiveC++. + if lang == 'objc': + lang = 'c' + elif lang == 'objcpp': + lang = 'cpp' + langname = LANGNAMEMAP[lang] + if langname in langargs: + langargs[langname] += args + else: + langargs[langname] = args + langargs[langname] += lang_cargs + symroot = os.path.join(self.environment.get_build_dir(), target.subdir) + bt_dict = PbxDict() + objects_dict.add_item(valid, bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('COMBINE_HIDPI_IMAGES', 'YES') + if isinstance(target, build.SharedModule): + settings_dict.add_item('DYLIB_CURRENT_VERSION', '""') + settings_dict.add_item('DYLIB_COMPATIBILITY_VERSION', '""') + else: if dylib_version is not None: - self.write_line('DYLIB_CURRENT_VERSION = "%s";' % dylib_version) - self.write_line('EXECUTABLE_PREFIX = "%s";' % target.prefix) - if target.suffix == '': - suffix = '' - else: - suffix = '.' + target.suffix - self.write_line('EXECUTABLE_SUFFIX = "%s";' % suffix) - self.write_line('GCC_GENERATE_DEBUGGING_SYMBOLS = YES;') - self.write_line('GCC_INLINES_ARE_PRIVATE_EXTERN = NO;') - self.write_line('GCC_OPTIMIZATION_LEVEL = 0;') - if target.has_pch: - # Xcode uses GCC_PREFIX_HEADER which only allows one file per target/executable. Precompiling various header files and - # applying a particular pch to each source file will require custom scripts (as a build phase) and build flags per each - # file. Since Xcode itself already discourages precompiled headers in favor of modules we don't try much harder here. - pchs = target.get_pch('c') + target.get_pch('cpp') + target.get_pch('objc') + target.get_pch('objcpp') - # Make sure to use headers (other backends require implementation files like *.c *.cpp, etc; these should not be used here) - pchs = [pch for pch in pchs if pch.endswith('.h') or pch.endswith('.hh') or pch.endswith('hpp')] - if pchs: - if len(pchs) > 1: - mlog.warning('Unsupported Xcode configuration: More than 1 precompiled header found "%s". Target "%s" might not compile correctly.' % (str(pchs), target.name)) - relative_pch_path = os.path.join(target.get_subdir(), pchs[0]) # Path relative to target so it can be used with "$(PROJECT_DIR)" - self.write_line('GCC_PRECOMPILE_PREFIX_HEADER = YES;') - self.write_line('GCC_PREFIX_HEADER = "$(PROJECT_DIR)/%s";' % relative_pch_path) - self.write_line('GCC_PREPROCESSOR_DEFINITIONS = "";') - self.write_line('GCC_SYMBOLS_PRIVATE_EXTERN = NO;') - if headerdirs: - quotedh = ','.join(['"\\"%s\\""' % i for i in headerdirs]) - self.write_line('HEADER_SEARCH_PATHS=(%s);' % quotedh) - self.write_line('INSTALL_PATH = "%s";' % install_path) - self.write_line('LIBRARY_SEARCH_PATHS = "";') - if isinstance(target, build.SharedLibrary): - self.write_line('LIBRARY_STYLE = DYNAMIC;') - for langname, args in langargs.items(): - self.write_build_setting_line('OTHER_%sFLAGS' % langname, args) - self.write_line('OTHER_LDFLAGS = "%s";' % ldstr) - self.write_line('OTHER_REZFLAGS = "";') - self.write_line('PRODUCT_NAME = %s;' % product_name) - self.write_line('SECTORDER_FLAGS = "";') - self.write_line('SYMROOT = "%s";' % symroot) - self.write_build_setting_line('SYSTEM_HEADER_SEARCH_PATHS', [self.environment.get_build_dir()]) - self.write_line('USE_HEADERMAP = NO;') - self.write_build_setting_line('WARNING_CFLAGS', ['-Wmost', '-Wno-four-char-constants', '-Wno-unknown-pragmas']) - self.indent_level -= 1 - self.write_line('};') - self.write_line('name = %s;' % buildtype) - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End XCBuildConfiguration section */\n') + settings_dict.add_item('DYLIB_CURRENT_VERSION', f'"{dylib_version}"') + if target.prefix: + settings_dict.add_item('EXECUTABLE_PREFIX', target.prefix) + if target.suffix: + suffix = '.' + target.suffix + settings_dict.add_item('EXECUTABLE_SUFFIX', suffix) + settings_dict.add_item('GCC_GENERATE_DEBUGGING_SYMBOLS', BOOL2XCODEBOOL[self.get_option_for_target(OptionKey('debug'), target)]) + settings_dict.add_item('GCC_INLINES_ARE_PRIVATE_EXTERN', 'NO') + settings_dict.add_item('GCC_OPTIMIZATION_LEVEL', OPT2XCODEOPT[self.get_option_for_target(OptionKey('optimization'), target)]) + if target.has_pch: + # Xcode uses GCC_PREFIX_HEADER which only allows one file per target/executable. Precompiling various header files and + # applying a particular pch to each source file will require custom scripts (as a build phase) and build flags per each + # file. Since Xcode itself already discourages precompiled headers in favor of modules we don't try much harder here. + pchs = target.get_pch('c') + target.get_pch('cpp') + target.get_pch('objc') + target.get_pch('objcpp') + # Make sure to use headers (other backends require implementation files like *.c *.cpp, etc; these should not be used here) + pchs = [pch for pch in pchs if pch.endswith('.h') or pch.endswith('.hh') or pch.endswith('hpp')] + if pchs: + if len(pchs) > 1: + mlog.warning(f'Unsupported Xcode configuration: More than 1 precompiled header found "{pchs!s}". Target "{target.name}" might not compile correctly.') + relative_pch_path = os.path.join(target.get_subdir(), pchs[0]) # Path relative to target so it can be used with "$(PROJECT_DIR)" + settings_dict.add_item('GCC_PRECOMPILE_PREFIX_HEADER', 'YES') + settings_dict.add_item('GCC_PREFIX_HEADER', f'"$(PROJECT_DIR)/{relative_pch_path}"') + settings_dict.add_item('GCC_PREPROCESSOR_DEFINITIONS', '""') + settings_dict.add_item('GCC_SYMBOLS_PRIVATE_EXTERN', 'NO') + header_arr = PbxArray() + unquoted_headers = [] + unquoted_headers.append(self.get_target_private_dir_abs(target)) + if target.implicit_include_directories: + unquoted_headers.append(os.path.join(self.environment.get_build_dir(), target.get_subdir())) + unquoted_headers.append(os.path.join(self.environment.get_source_dir(), target.get_subdir())) + if headerdirs: + for i in headerdirs: + i = os.path.normpath(i) + unquoted_headers.append(i) + for i in unquoted_headers: + header_arr.add_item(f'"\\"{i}\\""') + settings_dict.add_item('HEADER_SEARCH_PATHS', header_arr) + settings_dict.add_item('INSTALL_PATH', f'"{install_path}"') + settings_dict.add_item('LIBRARY_SEARCH_PATHS', '""') + if isinstance(target, build.SharedModule): + settings_dict.add_item('LIBRARY_STYLE', 'BUNDLE') + settings_dict.add_item('MACH_O_TYPE', 'mh_bundle') + elif isinstance(target, build.SharedLibrary): + settings_dict.add_item('LIBRARY_STYLE', 'DYNAMIC') + self.add_otherargs(settings_dict, langargs) + settings_dict.add_item('OTHER_LDFLAGS', f'"{ldstr}"') + settings_dict.add_item('OTHER_REZFLAGS', '""') + if ' ' in product_name: + settings_dict.add_item('PRODUCT_NAME', f'"{product_name}"') + else: + settings_dict.add_item('PRODUCT_NAME', product_name) + settings_dict.add_item('SECTORDER_FLAGS', '""') + settings_dict.add_item('SYMROOT', f'"{symroot}"') + sysheader_arr = PbxArray() + # XCode will change every -I flag that points inside these directories + # to an -isystem. Thus set nothing in it since we control our own + # include flags. + settings_dict.add_item('SYSTEM_HEADER_SEARCH_PATHS', sysheader_arr) + settings_dict.add_item('USE_HEADERMAP', 'NO') + warn_array = PbxArray() + settings_dict.add_item('WARNING_CFLAGS', warn_array) + warn_array.add_item('"$(inherited)"') + bt_dict.add_item('name', buildtype) + + def add_otherargs(self, settings_dict, langargs): + for langname, args in langargs.items(): + if args: + quoted_args = [] + for a in args: + # This works but + # a) it's ugly as sin + # b) I don't know why it works or why every backslash must be escaped into eight backslashes + a = a.replace(chr(92), 8*chr(92)) # chr(92) is backslash, this how we smuggle it in without Python's quoting grabbing it. + a = a.replace(r'"', r'\\\"') + if ' ' in a or "'" in a: + a = r'\"' + a + r'\"' + quoted_args.append(a) + settings_dict.add_item(f'OTHER_{langname}FLAGS', '"' + ' '.join(quoted_args) + '"') - def generate_xc_configurationList(self): + def generate_xc_configurationList(self, objects_dict): # FIXME: sort items - self.ofile.write('\n/* Begin XCConfigurationList section */\n') - self.write_line('%s /* Build configuration list for PBXProject "%s" */ = {' % (self.project_conflist, self.build.project_name)) - self.indent_level += 1 - self.write_line('isa = XCConfigurationList;') - self.write_line('buildConfigurations = (') - self.indent_level += 1 + conf_dict = PbxDict() + objects_dict.add_item(self.project_conflist, conf_dict, f'Build configuration list for PBXProject "{self.build.project_name}"') + conf_dict.add_item('isa', 'XCConfigurationList') + confs_arr = PbxArray() + conf_dict.add_item('buildConfigurations', confs_arr) for buildtype in self.buildtypes: - self.write_line('%s /* %s */,' % (self.project_configurations[buildtype], buildtype)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('defaultConfigurationIsVisible = 0;') - self.write_line('defaultConfigurationName = debug;') - self.indent_level -= 1 - self.write_line('};') + confs_arr.add_item(self.project_configurations[buildtype], buildtype) + conf_dict.add_item('defaultConfigurationIsVisible', 0) + conf_dict.add_item('defaultConfigurationName', self.buildtype) # Now the all target - self.write_line('%s /* Build configuration list for PBXAggregateTarget "ALL_BUILD" */ = {' % self.all_buildconf_id) - self.indent_level += 1 - self.write_line('isa = XCConfigurationList;') - self.write_line('buildConfigurations = (') - self.indent_level += 1 + all_dict = PbxDict() + objects_dict.add_item(self.all_buildconf_id, all_dict, 'Build configuration list for PBXAggregateTarget "ALL_BUILD"') + all_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + all_dict.add_item('buildConfigurations', conf_arr) for buildtype in self.buildtypes: - self.write_line('%s /* %s */,' % (self.buildall_configurations[buildtype], buildtype)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('defaultConfigurationIsVisible = 0;') - self.write_line('defaultConfigurationName = debug;') - self.indent_level -= 1 - self.write_line('};') + conf_arr.add_item(self.buildall_configurations[buildtype], buildtype) + all_dict.add_item('defaultConfigurationIsVisible', 0) + all_dict.add_item('defaultConfigurationName', self.buildtype) # Test target - self.write_line('%s /* Build configuration list for PBXAggregateTarget "ALL_BUILD" */ = {' % self.test_buildconf_id) - self.indent_level += 1 - self.write_line('isa = XCConfigurationList;') - self.write_line('buildConfigurations = (') - self.indent_level += 1 + test_dict = PbxDict() + objects_dict.add_item(self.test_buildconf_id, test_dict, 'Build configuration list for PBXAggregateTarget "RUN_TEST"') + test_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + test_dict.add_item('buildConfigurations', conf_arr) for buildtype in self.buildtypes: - self.write_line('%s /* %s */,' % (self.test_configurations[buildtype], buildtype)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('defaultConfigurationIsVisible = 0;') - self.write_line('defaultConfigurationName = debug;') - self.indent_level -= 1 - self.write_line('};') + conf_arr.add_item(self.test_configurations[buildtype], buildtype) + test_dict.add_item('defaultConfigurationIsVisible', 0) + test_dict.add_item('defaultConfigurationName', self.buildtype) + + # Regen target + regen_dict = PbxDict() + objects_dict.add_item(self.regen_buildconf_id, test_dict, 'Build configuration list for PBXAggregateTarget "REGENERATE"') + regen_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + regen_dict.add_item('buildConfigurations', conf_arr) + for buildtype in self.buildtypes: + conf_arr.add_item(self.test_configurations[buildtype], buildtype) + regen_dict.add_item('defaultConfigurationIsVisible', 0) + regen_dict.add_item('defaultConfigurationName', self.buildtype) - for target_name in self.build.targets: + for target_name in self.build_targets: + t_dict = PbxDict() listid = self.buildconflistmap[target_name] - self.write_line('%s /* Build configuration list for PBXNativeTarget "%s" */ = {' % (listid, target_name)) - self.indent_level += 1 - self.write_line('isa = XCConfigurationList;') - self.write_line('buildConfigurations = (') - self.indent_level += 1 - typestr = 'debug' - idval = self.buildconfmap[target_name][typestr] - self.write_line('%s /* %s */,' % (idval, typestr)) - self.indent_level -= 1 - self.write_line(');') - self.write_line('defaultConfigurationIsVisible = 0;') - self.write_line('defaultConfigurationName = %s;' % typestr) - self.indent_level -= 1 - self.write_line('};') - self.ofile.write('/* End XCConfigurationList section */\n') - - def write_build_setting_line(self, flag_name, flag_values, explicit=False): - if flag_values: - if len(flag_values) == 1: - value = flag_values[0] - if (' ' in value): - # If path contains spaces surround it with double colon - self.write_line('%s = "\\"%s\\"";' % (flag_name, value)) - else: - self.write_line('%s = "%s";' % (flag_name, value)) - else: - self.write_line('%s = (' % flag_name) - self.indent_level += 1 - for value in flag_values: - if (' ' in value): - # If path contains spaces surround it with double colon - self.write_line('"\\"%s\\"",' % value) - else: - self.write_line('"%s",' % value) - self.indent_level -= 1 - self.write_line(');') - else: - if explicit: - self.write_line('%s = "";' % flag_name) + objects_dict.add_item(listid, t_dict, f'Build configuration list for PBXNativeTarget "{target_name}"') + t_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + t_dict.add_item('buildConfigurations', conf_arr) + idval = self.buildconfmap[target_name][self.buildtype] + conf_arr.add_item(idval, self.buildtype) + t_dict.add_item('defaultConfigurationIsVisible', 0) + t_dict.add_item('defaultConfigurationName', self.buildtype) + + for target_name in self.custom_targets: + t_dict = PbxDict() + listid = self.buildconflistmap[target_name] + objects_dict.add_item(listid, t_dict, f'Build configuration list for PBXAggregateTarget "{target_name}"') + t_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + t_dict.add_item('buildConfigurations', conf_arr) + idval = self.buildconfmap[target_name][self.buildtype] + conf_arr.add_item(idval, self.buildtype) + t_dict.add_item('defaultConfigurationIsVisible', 0) + t_dict.add_item('defaultConfigurationName', self.buildtype) + + def generate_prefix(self, pbxdict): + pbxdict.add_item('archiveVersion', '1') + pbxdict.add_item('classes', PbxDict()) + pbxdict.add_item('objectVersion', '46') + objects_dict = PbxDict() + pbxdict.add_item('objects', objects_dict) + + return objects_dict - def generate_prefix(self): - self.ofile.write('// !$*UTF8*$!\n{\n') - self.indent_level += 1 - self.write_line('archiveVersion = 1;\n') - self.write_line('classes = {\n') - self.write_line('};\n') - self.write_line('objectVersion = 46;\n') - self.write_line('objects = {\n') - self.indent_level += 1 - - def generate_suffix(self): - self.indent_level -= 1 - self.write_line('};\n') - self.write_line('rootObject = ' + self.project_uid + ' /* Project object */;') - self.indent_level -= 1 - self.write_line('}\n') + def generate_suffix(self, pbxdict): + pbxdict.add_item('rootObject', self.project_uid, 'Project object') diff -Nru meson-0.53.2/mesonbuild/build.py meson-0.61.2/mesonbuild/build.py --- meson-0.53.2/mesonbuild/build.py 2020-01-23 21:41:11.000000000 +0000 +++ meson-0.61.2/mesonbuild/build.py 2022-01-17 10:50:45.000000000 +0000 @@ -12,29 +12,49 @@ # See the License for the specific language governing permissions and # limitations under the License. -import copy, os, re from collections import OrderedDict -import itertools, pathlib +from functools import lru_cache +import copy import hashlib +import itertools, pathlib +import os import pickle -from functools import lru_cache +import re +import textwrap import typing as T from . import environment from . import dependencies from . import mlog +from . import programs from .mesonlib import ( + HoldableObject, SecondLevelHolder, File, MesonException, MachineChoice, PerMachine, OrderedSet, listify, extract_as_list, typeslistify, stringlistify, classify_unity_sources, get_filenames_templates_dict, substitute_values, has_path_sep, + OptionKey, PerMachineDefaultable, + MesonBugException, +) +from .compilers import ( + Compiler, is_object, clink_langs, sort_clink, lang_suffixes, + is_known_suffix, detect_static_linker, detect_compiler_for ) -from .compilers import Compiler, is_object, clink_langs, sort_clink, lang_suffixes from .linkers import StaticLinker -from .interpreterbase import FeatureNew +from .interpreterbase import FeatureNew, FeatureDeprecated -pch_kwargs = set(['c_pch', 'cpp_pch']) +if T.TYPE_CHECKING: + from ._typing import ImmutableListProtocol, ImmutableSetProtocol + from .backend.backends import Backend, ExecutableSerialisation + from .interpreter.interpreter import Test, SourceOutputs, Interpreter + from .mesonlib import FileMode, FileOrString + from .modules import ModuleState + from .mparser import BaseNode -lang_arg_kwargs = set([ + GeneratedTypes = T.Union['CustomTarget', 'CustomTargetIndex', 'GeneratedList'] + +pch_kwargs = {'c_pch', 'cpp_pch'} + +lang_arg_kwargs = { 'c_args', 'cpp_args', 'cuda_args', @@ -50,13 +70,14 @@ 'rust_args', 'vala_args', 'cs_args', -]) + 'cython_args', +} -vala_kwargs = set(['vala_header', 'vala_gir', 'vala_vapi']) -rust_kwargs = set(['rust_crate_type']) -cs_kwargs = set(['resources', 'cs_args']) +vala_kwargs = {'vala_header', 'vala_gir', 'vala_vapi'} +rust_kwargs = {'rust_crate_type'} +cs_kwargs = {'resources', 'cs_args'} -buildtarget_kwargs = set([ +buildtarget_kwargs = { 'build_by_default', 'build_rpath', 'dependencies', @@ -72,6 +93,7 @@ 'install_rpath', 'install_dir', 'install_mode', + 'install_tag', 'name_prefix', 'name_suffix', 'native', @@ -79,7 +101,9 @@ 'override_options', 'sources', 'gnu_symbol_visibility', -]) + 'link_language', + 'win_subsystem', +} known_build_target_kwargs = ( buildtarget_kwargs | @@ -89,10 +113,10 @@ rust_kwargs | cs_kwargs) -known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'link_language', 'pie'} +known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie'} known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'} known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'} -known_stlib_kwargs = known_build_target_kwargs | {'pic'} +known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink'} known_jar_kwargs = known_exe_kwargs | {'main_class'} @lru_cache(maxsize=None) @@ -106,6 +130,105 @@ class InvalidArguments(MesonException): pass +class DependencyOverride(HoldableObject): + def __init__(self, dep: dependencies.Dependency, node: 'BaseNode', explicit: bool = True): + self.dep = dep + self.node = node + self.explicit = explicit + +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 + + # TODO: we really don't need any of these methods, but they're preserved to + # keep APIs relying on them working. + + def set_install_subdir(self, subdir: str) -> None: + self.install_subdir = subdir + + def get_install_subdir(self) -> T.Optional[str]: + return self.install_subdir + + def get_sources(self) -> T.List[File]: + return self.sources + + def get_custom_install_dir(self) -> T.Optional[str]: + return self.custom_install_dir + + def get_custom_install_mode(self) -> 'FileMode': + return self.custom_install_mode + + +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 + + def get_custom_install_dir(self) -> T.Optional[str]: + return self.custom_install_dir + + def get_custom_install_mode(self) -> 'FileMode': + return self.custom_install_mode + + def get_sources(self) -> T.List['File']: + return self.sources + + +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 + + +class InstallDir(HoldableObject): + + 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 + + +class DepManifest: + + def __init__(self, version: str, license: T.List[str]): + self.version = version + self.license = license + + def to_json(self) -> T.Dict[str, T.Union[str, T.List[str]]]: + return { + 'version': self.version, + 'license': self.license, + } + + class Build: """A class that holds the status of one build including all dependencies and so on. @@ -116,32 +239,56 @@ self.project_version = None self.environment = environment self.projects = {} - self.targets = OrderedDict() - self.run_target_names = set() # type: T.Set[T.Tuple[str, str]] - self.global_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]] - self.projects_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]] - self.global_link_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]] - self.projects_link_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]] - self.tests = [] - self.benchmarks = [] - self.headers = [] - self.man = [] - self.data = [] - self.static_linker = PerMachine(None, None) # type: PerMachine[StaticLinker] + self.targets: 'T.OrderedDict[str, T.Union[CustomTarget, BuildTarget]]' = OrderedDict() + self.run_target_names: T.Set[T.Tuple[str, str]] = set() + self.global_args: PerMachine[T.Dict[str, T.List[str]]] = PerMachine({}, {}) + self.global_link_args: PerMachine[T.Dict[str, T.List[str]]] = PerMachine({}, {}) + self.projects_args: PerMachine[T.Dict[str, T.Dict[str, T.List[str]]]] = PerMachine({}, {}) + self.projects_link_args: PerMachine[T.Dict[str, T.Dict[str, T.List[str]]]] = PerMachine({}, {}) + self.tests: T.List['Test'] = [] + self.benchmarks: T.List['Test'] = [] + self.headers: T.List[Headers] = [] + self.man: T.List[Man] = [] + self.emptydir: T.List[EmptyDir] = [] + self.data: T.List[Data] = [] + self.symlinks: T.List[SymlinkData] = [] + self.static_linker: PerMachine[StaticLinker] = PerMachine(None, None) self.subprojects = {} self.subproject_dir = '' - self.install_scripts = [] - self.postconf_scripts = [] - self.dist_scripts = [] - self.install_dirs = [] - self.dep_manifest_name = None - self.dep_manifest = {} + self.install_scripts: T.List['ExecutableSerialisation'] = [] + self.postconf_scripts: T.List['ExecutableSerialisation'] = [] + self.dist_scripts: T.List['ExecutableSerialisation'] = [] + self.install_dirs: T.List[InstallDir] = [] + self.dep_manifest_name: T.Optional[str] = None + self.dep_manifest: T.Dict[str, DepManifest] = {} self.stdlibs = PerMachine({}, {}) - self.test_setups = {} # type: T.Dict[str, TestSetup] + self.test_setups: T.Dict[str, TestSetup] = {} self.test_setup_default_name = None - self.find_overrides = {} + self.find_overrides: T.Dict[str, T.Union['Executable', programs.ExternalProgram, programs.OverrideProgram]] = {} self.searched_programs = set() # The list of all programs that have been searched for. + # If we are doing a cross build we need two caches, if we're doing a + # build == host compilation the both caches should point to the same place. + self.dependency_overrides: PerMachine[T.Dict[T.Tuple, DependencyOverride]] = PerMachineDefaultable.default( + environment.is_cross_build(), {}, {}) + self.devenv: T.List[EnvironmentVariables] = [] + self.modules: T.List[str] = [] + self.need_vsenv = False + + def get_build_targets(self): + build_targets = OrderedDict() + for name, t in self.targets.items(): + if isinstance(t, BuildTarget): + build_targets[name] = t + return build_targets + + def get_custom_targets(self): + custom_targets = OrderedDict() + for name, t in self.targets.items(): + if isinstance(t, CustomTarget): + custom_targets[name] = t + return custom_targets + def copy(self): other = Build(self.environment) for k, v in self.__dict__.items(): @@ -157,7 +304,7 @@ def ensure_static_linker(self, compiler): if self.static_linker[compiler.for_machine] is None and compiler.needs_static_linker(): - self.static_linker[compiler.for_machine] = self.environment.detect_static_linker(compiler) + self.static_linker[compiler.for_machine] = detect_static_linker(self.environment, compiler) def get_project(self): return self.projects[''] @@ -165,43 +312,49 @@ def get_subproject_dir(self): return self.subproject_dir - def get_targets(self): + def get_targets(self) -> 'T.OrderedDict[str, T.Union[CustomTarget, BuildTarget]]': return self.targets - def get_tests(self): + def get_tests(self) -> T.List['Test']: return self.tests - def get_benchmarks(self): + def get_benchmarks(self) -> T.List['Test']: return self.benchmarks - def get_headers(self): + def get_headers(self) -> T.List['Headers']: return self.headers - def get_man(self): + def get_man(self) -> T.List['Man']: return self.man - def get_data(self): + def get_data(self) -> T.List['Data']: return self.data - def get_install_subdirs(self): + def get_symlinks(self) -> T.List['SymlinkData']: + return self.symlinks + + def get_emptydir(self) -> T.List['EmptyDir']: + return self.emptydir + + def get_install_subdirs(self) -> T.List['InstallDir']: return self.install_dirs - def get_global_args(self, compiler, for_machine): + def get_global_args(self, compiler: 'Compiler', for_machine: 'MachineChoice') -> T.List[str]: d = self.global_args[for_machine] return d.get(compiler.get_language(), []) - def get_project_args(self, compiler, project, for_machine): + def get_project_args(self, compiler: 'Compiler', project: str, for_machine: 'MachineChoice') -> T.List[str]: d = self.projects_args[for_machine] args = d.get(project) if not args: return [] return args.get(compiler.get_language(), []) - def get_global_link_args(self, compiler, for_machine): + def get_global_link_args(self, compiler: 'Compiler', for_machine: 'MachineChoice') -> T.List[str]: d = self.global_link_args[for_machine] return d.get(compiler.get_language(), []) - def get_project_link_args(self, compiler, project, for_machine): + def get_project_link_args(self, compiler: 'Compiler', project: str, for_machine: 'MachineChoice') -> T.List[str]: d = self.projects_link_args[for_machine] link_args = d.get(project) @@ -210,49 +363,71 @@ return link_args.get(compiler.get_language(), []) -class IncludeDirs: - def __init__(self, curdir, dirs, is_system, extra_build_dirs=None): +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 = dirs + self.incdirs = incdirs self.is_system = is_system + # Interpreter has validated that all given directories # actually exist. - if extra_build_dirs is None: - self.extra_build_dirs = [] - else: - self.extra_build_dirs = extra_build_dirs + self.extra_build_dirs: T.List[str] = extra_build_dirs or [] - def __repr__(self): + def __repr__(self) -> str: r = '<{} {}/{}>' return r.format(self.__class__.__name__, self.curdir, self.incdirs) - def get_curdir(self): + def get_curdir(self) -> str: return self.curdir - def get_incdirs(self): + def get_incdirs(self) -> T.List[str]: return self.incdirs - def get_extra_build_dirs(self): + def get_extra_build_dirs(self) -> T.List[str]: return self.extra_build_dirs -class ExtractedObjects: + def to_string_list(self, sourcedir: str, builddir: T.Optional[str] = None) -> T.List[str]: + """Convert IncludeDirs object to a list of strings. + + :param sourcedir: The absolute source directory + :param builddir: The absolute build directory, option, buid dir will not + be added if this is unset + :returns: A list of strings (without compiler argument) + """ + strlist: T.List[str] = [] + for idir in self.incdirs: + strlist.append(os.path.join(sourcedir, self.curdir, idir)) + if builddir: + strlist.append(os.path.join(builddir, self.curdir, idir)) + return strlist + +class ExtractedObjects(HoldableObject): ''' Holds a list of sources for which the objects must be extracted ''' - def __init__(self, target, srclist=None, genlist=None, objlist=None, recursive=True): + 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 = srclist if srclist is not None else [] - self.genlist = genlist if genlist is not None else [] - self.objlist = objlist if objlist is not None else [] + 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 [] if self.target.is_unity: self.check_unity_compatible() - def __repr__(self): + def __repr__(self) -> str: r = '<{0} {1!r}: {2}>' return r.format(self.__class__.__name__, self.target.name, self.srclist) - def classify_all_sources(self, sources, generated_sources): + @staticmethod + def get_sources(sources: T.Sequence['FileOrString'], generated_sources: T.Sequence['GeneratedTypes']) -> T.List['FileOrString']: # Merge sources and generated sources sources = list(sources) for gensrc in generated_sources: @@ -263,11 +438,13 @@ sources.append(s) # Filter out headers and all non-source files - sources = [s for s in sources if environment.is_source(s) and not environment.is_header(s)] + return [s for s in sources if environment.is_source(s) and not environment.is_header(s)] - return classify_unity_sources(self.target.compilers.values(), sources) + def classify_all_sources(self, sources: T.List[str], generated_sources: T.Sequence['GeneratedTypes']) -> T.Dict['Compiler', T.List['FileOrString']]: + sources_ = self.get_sources(sources, generated_sources) + return classify_unity_sources(self.target.compilers.values(), sources_) - def check_unity_compatible(self): + def check_unity_compatible(self) -> None: # Figure out if the extracted object list is compatible with a Unity # build. When we're doing a Unified build, we go through the sources, # and create a single source file from each subset of the sources that @@ -283,67 +460,81 @@ 'in Unity builds. You can only extract all ' 'the object files for each compiler at once.') - def get_outputs(self, backend): - # TODO: Consider if we need to handle genlist here + def get_outputs(self, backend: 'Backend') -> T.List[str]: return [ backend.object_filename_from_source(self.target, source) - for source in self.srclist + for source in self.get_sources(self.srclist, self.genlist) ] -class EnvironmentVariables: - def __init__(self): - self.envvars = [] +class EnvironmentVariables(HoldableObject): + def __init__(self, values: T.Optional[T.Dict[str, str]] = None) -> None: + self.envvars: T.List[T.Tuple[T.Callable[[T.Dict[str, str], str, T.List[str], str], str], str, T.List[str], str]] = [] # The set of all env vars we have operations for. Only used for self.has_name() - self.varnames = set() + self.varnames: T.Set[str] = set() - def __repr__(self): + if values: + for name, value in values.items(): + self.set(name, [value]) + + def __repr__(self) -> str: repr_str = "<{0}: {1}>" return repr_str.format(self.__class__.__name__, self.envvars) - def add_var(self, method, name, args, kwargs): - self.varnames.add(name) - self.envvars.append((method, name, args, kwargs)) + def hash(self, hasher: T.Any): + myenv = self.get_env({}) + for key in sorted(myenv.keys()): + hasher.update(bytes(key, encoding='utf-8')) + hasher.update(b',') + hasher.update(bytes(myenv[key], encoding='utf-8')) + hasher.update(b';') - def has_name(self, name): + def has_name(self, name: str) -> bool: return name in self.varnames - def get_value(self, values, kwargs): - separator = kwargs.get('separator', os.pathsep) + def set(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + self.varnames.add(name) + self.envvars.append((self._set, name, values, separator)) - value = '' - for var in values: - value += separator + var - return separator, value.strip(separator) - - def set(self, env, name, values, kwargs): - return self.get_value(values, kwargs)[1] - - def append(self, env, name, values, kwargs): - sep, value = self.get_value(values, kwargs) - if name in env: - return env[name] + sep + value - return value + def append(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + self.varnames.add(name) + self.envvars.append((self._append, name, values, separator)) - def prepend(self, env, name, values, kwargs): - sep, value = self.get_value(values, kwargs) - if name in env: - return value + sep + env[name] + def prepend(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + self.varnames.add(name) + self.envvars.append((self._prepend, name, values, separator)) - return value + @staticmethod + def _set(env: T.Dict[str, str], name: str, values: T.List[str], separator: str) -> str: + return separator.join(values) + + @staticmethod + def _append(env: T.Dict[str, str], name: str, values: T.List[str], separator: str) -> str: + curr = env.get(name) + return separator.join(values if curr is None else [curr] + values) + + @staticmethod + def _prepend(env: T.Dict[str, str], name: str, values: T.List[str], separator: str) -> str: + curr = env.get(name) + return separator.join(values if curr is None else values + [curr]) def get_env(self, full_env: T.Dict[str, str]) -> T.Dict[str, str]: env = full_env.copy() - for method, name, values, kwargs in self.envvars: - env[name] = method(full_env, name, values, kwargs) + for method, name, values, separator in self.envvars: + env[name] = method(env, name, values, separator) return env -class Target: - def __init__(self, name, subdir, subproject, build_by_default, for_machine: MachineChoice): +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): # Fix failing test 53 when this becomes an error. - mlog.warning('''Target "%s" 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.''' % name) + mlog.warning(textwrap.dedent(f'''\ + Target "{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 @@ -351,51 +542,65 @@ self.for_machine = for_machine self.install = False self.build_always_stale = False - self.option_overrides = {} + self.option_overrides_base: T.Dict[OptionKey, str] = {} + self.option_overrides_compiler: T.Dict[OptionKey, str] = {} + self.extra_files = [] # type: T.List[File] if not hasattr(self, 'typename'): - raise RuntimeError('Target type is not set for target class "{}". This is a bug'.format(type(self).__name__)) + raise RuntimeError(f'Target type is not set for target class "{type(self).__name__}". This is a bug') - def __lt__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]: - if not hasattr(other, 'get_id') and not callable(other.get_id): + def __lt__(self, other: object) -> bool: + if not isinstance(other, Target): return NotImplemented return self.get_id() < other.get_id() - def __le__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]: - if not hasattr(other, 'get_id') and not callable(other.get_id): + def __le__(self, other: object) -> bool: + if not isinstance(other, Target): return NotImplemented return self.get_id() <= other.get_id() - def __gt__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]: - if not hasattr(other, 'get_id') and not callable(other.get_id): + def __gt__(self, other: object) -> bool: + if not isinstance(other, Target): return NotImplemented return self.get_id() > other.get_id() - def __ge__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]: - if not hasattr(other, 'get_id') and not callable(other.get_id): + def __ge__(self, other: object) -> bool: + if not isinstance(other, Target): return NotImplemented return self.get_id() >= other.get_id() - def get_install_dir(self, environment): + def get_default_install_dir(self, env: environment.Environment) -> T.Tuple[str, str]: + raise NotImplementedError + + def get_custom_install_dir(self) -> T.List[T.Union[str, bool]]: + raise NotImplementedError + + def get_install_dir(self, environment: environment.Environment) -> T.Tuple[T.Any, str, bool]: # Find the installation directory. - default_install_dir = self.get_default_install_dir(environment) + default_install_dir, install_dir_name = self.get_default_install_dir(environment) outdirs = self.get_custom_install_dir() - if outdirs[0] is not None and outdirs[0] != default_install_dir and outdirs[0] is not True: + if outdirs and outdirs[0] != default_install_dir and outdirs[0] is not True: # Either the value is set to a non-default value, or is set to # False (which means we want this specific output out of many # outputs to not be installed). custom_install_dir = True else: custom_install_dir = False - outdirs[0] = default_install_dir - return outdirs, custom_install_dir + # if outdirs is empty we need to set to something, otherwise we set + # only the first value to the default + if outdirs: + outdirs[0] = default_install_dir + else: + outdirs = [default_install_dir] - def get_basename(self): + return outdirs, install_dir_name, custom_install_dir + + def get_basename(self) -> str: return self.name - def get_subdir(self): + def get_subdir(self) -> str: return self.subdir - def get_typename(self): + def get_typename(self) -> str: return self.typename @staticmethod @@ -409,7 +614,7 @@ return h.hexdigest()[:7] @staticmethod - def construct_id_from_path(subdir, name, type_suffix): + def construct_id_from_path(subdir: str, name: str, type_suffix: str) -> str: """Construct target ID from subdir, name and type suffix. This helper function is made public mostly for tests.""" @@ -427,11 +632,11 @@ return subdir_part + '@@' + my_id return my_id - def get_id(self): + def get_id(self) -> str: return self.construct_id_from_path( self.subdir, self.name, self.type_suffix()) - def process_kwargs_base(self, kwargs): + def process_kwargs_base(self, kwargs: T.Dict[str, T.Any]) -> None: if 'build_by_default' in kwargs: self.build_by_default = kwargs['build_by_default'] if not isinstance(self.build_by_default, bool): @@ -441,40 +646,63 @@ # set, use the value of 'install' if it's enabled. self.build_by_default = True - self.option_overrides = self.parse_overrides(kwargs) + option_overrides = self.parse_overrides(kwargs) + + for k, v in option_overrides.items(): + if k.lang: + self.option_overrides_compiler[k.evolve(machine=self.for_machine)] = v + continue + self.option_overrides_base[k] = v + + @staticmethod + def parse_overrides(kwargs: T.Dict[str, T.Any]) -> T.Dict[OptionKey, str]: + opts = kwargs.get('override_options', []) + + # In this case we have an already parsed and ready to go dictionary + # provided by typed_kwargs + if isinstance(opts, dict): + return T.cast(T.Dict[OptionKey, str], opts) - def parse_overrides(self, kwargs) -> dict: - result = {} - overrides = stringlistify(kwargs.get('override_options', [])) + result: T.Dict[OptionKey, str] = {} + overrides = stringlistify(opts) for o in overrides: if '=' not in o: raise InvalidArguments('Overrides must be of form "key=value"') k, v = o.split('=', 1) - k = k.strip() + key = OptionKey.from_string(k.strip()) v = v.strip() - result[k] = v + result[key] = v return result def is_linkable_target(self) -> bool: return False + def get_outputs(self) -> T.List[str]: + return [] + + def should_install(self) -> bool: + return False + class BuildTarget(Target): known_kwargs = known_build_target_kwargs - def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): + install_dir: T.List[T.Union[str, bool]] + + def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice, + sources: T.List['SourceOutputs'], objects, environment: environment.Environment, kwargs): super().__init__(name, subdir, subproject, True, for_machine) - unity_opt = environment.coredata.get_builtin_option('unity') + unity_opt = environment.coredata.get_option(OptionKey('unity')) self.is_unity = unity_opt == 'on' or (unity_opt == 'subprojects' and subproject != '') self.environment = environment - self.sources = [] self.compilers = OrderedDict() # type: OrderedDict[str, Compiler] - self.objects = [] - self.external_deps = [] - self.include_dirs = [] + self.objects: T.List[T.Union[str, 'File', 'ExtractedObjects']] = [] + self.external_deps: T.List[dependencies.Dependency] = [] + self.include_dirs: T.List['IncludeDirs'] = [] self.link_language = kwargs.get('link_language') - self.link_targets = [] + self.link_targets: T.List[T.Union['BuildTarget', 'CustomTarget', 'CustomTargetIndex']] = [] self.link_whole_targets = [] self.link_depends = [] + self.added_deps = set() self.name_prefix_set = False self.name_suffix_set = False self.filename = 'no_name' @@ -482,17 +710,15 @@ # as Vala which generates .vapi and .h besides the compiled output. self.outputs = [self.filename] self.need_install = False - self.pch = {} - self.extra_args = {} - self.generated = [] - self.extra_files = [] + self.pch: T.Dict[str, T.List[str]] = {} + self.extra_args: T.Dict[str, T.List['FileOrString']] = {} + self.sources: T.List[File] = [] + self.generated: T.List['GeneratedTypes'] = [] self.d_features = {} self.pic = False self.pie = False - # Sources can be: - # 1. Pre-existing source files in the source tree - # 2. Pre-existing sources generated by configure_file in the build tree - # 3. Sources files generated by another target or a Generator + # Track build_rpath entries so we can remove them at install time + self.rpath_dirs_to_remove: T.Set[bytes] = set() self.process_sourcelist(sources) # Objects can be: # 1. Pre-existing objects provided by the user with the `objects:` kwarg @@ -502,7 +728,7 @@ self.check_unknown_kwargs(kwargs) self.process_compilers() if not any([self.sources, self.generated, self.objects, self.link_whole]): - raise InvalidArguments('Build target %s has no sources.' % name) + raise InvalidArguments(f'Build target {name} has no sources.') self.process_compilers_late() self.validate_sources() self.validate_install(environment) @@ -512,6 +738,9 @@ repr_str = "<{0} {1}: {2}>" return repr_str.format(self.__class__.__name__, self.get_id(), self.filename) + def __str__(self): + return f"{self.name}" + def validate_install(self, environment): if self.for_machine is MachineChoice.BUILD and self.need_install: if environment.is_cross_build(): @@ -530,45 +759,42 @@ if k not in known_kwargs: unknowns.append(k) if len(unknowns) > 0: - mlog.warning('Unknown keyword argument(s) in target %s: %s.' % - (self.name, ', '.join(unknowns))) + mlog.warning('Unknown keyword argument(s) in target {}: {}.'.format(self.name, ', '.join(unknowns))) def process_objectlist(self, objects): - assert(isinstance(objects, list)) + assert isinstance(objects, list) for s in objects: - if hasattr(s, 'held_object'): - s = s.held_object if isinstance(s, (str, File, ExtractedObjects)): self.objects.append(s) elif isinstance(s, (GeneratedList, CustomTarget)): msg = 'Generated files are not allowed in the \'objects\' kwarg ' + \ - 'for target {!r}.\nIt is meant only for '.format(self.name) + \ + f'for target {self.name!r}.\nIt is meant only for ' + \ 'pre-built object files that are shipped with the\nsource ' + \ 'tree. Try adding it in the list of sources.' raise InvalidArguments(msg) else: - msg = 'Bad object of type {!r} in target {!r}.'.format(type(s).__name__, self.name) - raise InvalidArguments(msg) + raise InvalidArguments(f'Bad object of type {type(s).__name__!r} in target {self.name!r}.') - def process_sourcelist(self, sources): - sources = listify(sources) - added_sources = {} # If the same source is defined multiple times, use it only once. + def process_sourcelist(self, sources: T.List['SourceOutputs']) -> None: + """Split sources into generated and static sources. + + Sources can be: + 1. Pre-existing source files in the source tree (static) + 2. Pre-existing sources generated by configure_file in the build tree. + (static as they are only regenerated if meson itself is regenerated) + 3. Sources files generated by another target or a Generator (generated) + """ + added_sources: T.Set[File] = set() # If the same source is defined multiple times, use it only once. for s in sources: - # Holder unpacking. Ugly. - if hasattr(s, 'held_object'): - s = s.held_object if isinstance(s, File): if s not in added_sources: self.sources.append(s) - added_sources[s] = True - elif isinstance(s, (GeneratedList, CustomTarget, CustomTargetIndex)): + added_sources.add(s) + elif isinstance(s, (CustomTarget, CustomTargetIndex, GeneratedList)): self.generated.append(s) - else: - msg = 'Bad source of type {!r} in target {!r}.'.format(type(s).__name__, self.name) - raise InvalidArguments(msg) @staticmethod - def can_compile_remove_sources(compiler, sources): + def can_compile_remove_sources(compiler: 'Compiler', sources: T.List['FileOrString']) -> bool: removed = False for s in sources[:]: if compiler.can_compile(s): @@ -634,8 +860,6 @@ if not is_object(s): sources.append(s) for d in self.external_deps: - if hasattr(d, 'held_object'): - d = d.held_object for s in d.sources: if isinstance(s, (str, File)): sources.append(s) @@ -652,14 +876,24 @@ sources.append(s) if sources: # For each source, try to add one compiler that can compile it. - # It's ok if no compilers can do so, because users are expected to - # be able to add arbitrary non-source files to the sources list. + # + # If it has a suffix that belongs to a known language, we must have + # a compiler for that language. + # + # Otherwise, it's ok if no compilers can compile it, because users + # are expected to be able to add arbitrary non-source files to the + # sources list for s in sources: for lang, compiler in compilers.items(): if compiler.can_compile(s): if lang not in self.compilers: self.compilers[lang] = compiler break + else: + if is_known_suffix(s): + raise MesonException('No {} machine compiler for "{}"'. + format(self.for_machine.get_lower_case_name(), s)) + # Re-sort according to clink_langs self.compilers = OrderedDict(sorted(self.compilers.items(), key=lambda t: sort_clink(t[0]))) @@ -668,6 +902,38 @@ # it won't get added above. if 'vala' in self.compilers and 'c' not in self.compilers: self.compilers['c'] = compilers['c'] + if 'cython' in self.compilers: + key = OptionKey('language', machine=self.for_machine, lang='cython') + if key in self.option_overrides_compiler: + value = self.option_overrides_compiler[key] + else: + value = self.environment.coredata.options[key].value + + try: + self.compilers[value] = compilers[value] + except KeyError: + # TODO: it would be nice to not have to do this here, but we + # have two problems to work around: + # 1. If this is set via an override we have no way to know + # before now that we need a compiler for the non-default language + # 2. Because Cython itself initializes the `cython_language` + # option, we have no good place to insert that you need it + # before now, so we just have to do it here. + comp = detect_compiler_for(self.environment, value, self.for_machine) + + # This is copied verbatim from the interpreter + if self.for_machine == MachineChoice.HOST or self.environment.is_cross_build(): + logger_fun = mlog.log + else: + logger_fun = mlog.debug + logger_fun(comp.get_display_language(), 'compiler for the', self.for_machine.get_lower_case_name(), 'machine:', + mlog.bold(' '.join(comp.get_exelist())), comp.get_version_string()) + if comp.linker is not None: + logger_fun(comp.get_display_language(), 'linker for the', self.for_machine.get_lower_case_name(), 'machine:', + mlog.bold(' '.join(comp.linker.get_exelist())), comp.linker.id, comp.linker.version) + if comp is None: + raise MesonException(f'Cannot find required compiler {value}') + self.compilers[value] = comp def validate_sources(self): if not self.sources: @@ -677,14 +943,13 @@ check_sources = list(self.sources) compiler = self.compilers[lang] if not self.can_compile_remove_sources(compiler, check_sources): - m = 'No {} sources found in target {!r}'.format(lang, self.name) - raise InvalidArguments(m) + raise InvalidArguments(f'No {lang} sources found in target {self.name!r}') if check_sources: m = '{0} targets can only contain {0} files:\n'.format(lang.capitalize()) m += '\n'.join([repr(c) for c in check_sources]) raise InvalidArguments(m) # CSharp and Java targets can't contain any other file types - assert(len(self.compilers) == 1) + assert len(self.compilers) == 1 return def process_link_depends(self, sources, environment): @@ -698,17 +963,13 @@ """ sources = listify(sources) for s in sources: - if hasattr(s, 'held_object'): - s = s.held_object - if isinstance(s, File): self.link_depends.append(s) elif isinstance(s, str): self.link_depends.append( File.from_source_file(environment.source_dir, self.subdir, s)) elif hasattr(s, 'get_outputs'): - self.link_depends.extend( - [File.from_built_file(s.subdir, p) for p in s.get_outputs()]) + self.link_depends.append(s) else: raise InvalidArguments( 'Link_depends arguments must be strings, Files, ' @@ -717,69 +978,60 @@ def get_original_kwargs(self): return self.kwargs - def unpack_holder(self, d): - d = listify(d) - newd = [] - for i in d: - if isinstance(i, list): - i = self.unpack_holder(i) - elif hasattr(i, 'held_object'): - i = i.held_object - for t in ['dependencies', 'link_with', 'include_directories', 'sources']: - if hasattr(i, t): - setattr(i, t, self.unpack_holder(getattr(i, t))) - newd.append(i) - return newd - def copy_kwargs(self, kwargs): self.kwargs = copy.copy(kwargs) - # This sucks quite badly. Arguments - # are holders but they can't be pickled - # so unpack those known. for k, v in self.kwargs.items(): if isinstance(v, list): - self.kwargs[k] = self.unpack_holder(v) - if hasattr(v, 'held_object'): - self.kwargs[k] = v.held_object + self.kwargs[k] = listify(v, flatten=True) for t in ['dependencies', 'link_with', 'include_directories', 'sources']: if t in self.kwargs: - self.kwargs[t] = self.unpack_holder(self.kwargs[t]) + self.kwargs[t] = listify(self.kwargs[t], flatten=True) - def extract_objects(self, srclist): - obj_src = [] + def extract_objects(self, srclist: T.List[T.Union['FileOrString', 'GeneratedTypes']]) -> ExtractedObjects: + sources_set = set(self.sources) + generated_set = set(self.generated) + + obj_src: T.List['File'] = [] + obj_gen: T.List['GeneratedTypes'] = [] for src in srclist: - if isinstance(src, str): - src = File(False, self.subdir, src) - elif isinstance(src, File): - FeatureNew('File argument for extract_objects', '0.50.0').use(self.subproject) - else: - raise MesonException('Object extraction arguments must be strings or Files.') - # FIXME: It could be a generated source - if src not in self.sources: - raise MesonException('Tried to extract unknown source %s.' % src) - obj_src.append(src) - return ExtractedObjects(self, obj_src) + if isinstance(src, (str, File)): + if isinstance(src, str): + src = File(False, self.subdir, src) + else: + FeatureNew.single_use('File argument for extract_objects', '0.50.0', self.subproject) + if src not in sources_set: + raise MesonException(f'Tried to extract unknown source {src}.') + obj_src.append(src) + elif isinstance(src, (CustomTarget, CustomTargetIndex, GeneratedList)): + FeatureNew.single_use('Generated sources for extract_objects', '0.61.0', self.subproject) + target = src.target if isinstance(src, CustomTargetIndex) else src + if src not in generated_set and target not in generated_set: + raise MesonException(f'Tried to extract unknown source {target.get_basename()}.') + obj_gen.append(src) + else: + raise MesonException(f'Object extraction arguments must be strings, Files or targets (got {type(src).__name__}).') + return ExtractedObjects(self, obj_src, obj_gen) - def extract_all_objects(self, recursive=True): + def extract_all_objects(self, recursive: bool = True) -> ExtractedObjects: return ExtractedObjects(self, self.sources, self.generated, self.objects, recursive) - def get_all_link_deps(self): + def get_all_link_deps(self) -> 'ImmutableListProtocol[Target]': return self.get_transitive_link_deps() @lru_cache(maxsize=None) - def get_transitive_link_deps(self): - result = [] + def get_transitive_link_deps(self) -> 'ImmutableListProtocol[Target]': + result: T.List[Target] = [] for i in self.link_targets: result += i.get_all_link_deps() return result - def get_link_deps_mapping(self, prefix, environment): + def get_link_deps_mapping(self, prefix: str, environment: environment.Environment) -> T.Mapping[str, str]: return self.get_transitive_link_deps_mapping(prefix, environment) @lru_cache(maxsize=None) - def get_transitive_link_deps_mapping(self, prefix, environment): - result = {} + def get_transitive_link_deps_mapping(self, prefix: str, environment: environment.Environment) -> T.Mapping[str, str]: + result: T.Dict[str, str] = {} for i in self.link_targets: mapping = i.get_link_deps_mapping(prefix, environment) #we are merging two dictionaries, while keeping the earlier one dominant @@ -789,20 +1041,21 @@ return result @lru_cache(maxsize=None) - def get_link_dep_subdirs(self): - result = OrderedSet() + def get_link_dep_subdirs(self) -> 'ImmutableSetProtocol[str]': + result: OrderedSet[str] = OrderedSet() for i in self.link_targets: - result.add(i.get_subdir()) + if not isinstance(i, StaticLibrary): + result.add(i.get_subdir()) result.update(i.get_link_dep_subdirs()) return result - def get_default_install_dir(self, environment): - return environment.get_libdir() + def get_default_install_dir(self, environment: environment.Environment) -> T.Tuple[str, str]: + return environment.get_libdir(), '{libdir}' - def get_custom_install_dir(self): + def get_custom_install_dir(self) -> T.List[T.Union[str, bool]]: return self.install_dir - def get_custom_install_mode(self): + def get_custom_install_mode(self) -> T.Optional['FileMode']: return self.install_mode def process_kwargs(self, kwargs, environment): @@ -812,24 +1065,21 @@ self.need_install = kwargs.get('install', self.need_install) llist = extract_as_list(kwargs, 'link_with') for linktarget in llist: - # Sorry for this hack. Keyword targets are kept in holders - # in kwargs. Unpack here without looking at the exact type. - if hasattr(linktarget, "held_object"): - linktarget = linktarget.held_object if isinstance(linktarget, dependencies.ExternalLibrary): - raise MesonException('''An external library was used in link_with keyword argument, which -is reserved for libraries built as part of this project. External -libraries must be passed using the dependencies keyword argument -instead, because they are conceptually "external dependencies", -just like those detected with the dependency() function.''') + raise MesonException(textwrap.dedent('''\ + An external library was used in link_with keyword argument, which + is reserved for libraries built as part of this project. External + libraries must be passed using the dependencies keyword argument + instead, because they are conceptually "external dependencies", + just like those detected with the dependency() function.\ + ''')) self.link(linktarget) lwhole = extract_as_list(kwargs, 'link_whole') for linktarget in lwhole: self.link_whole(linktarget) c_pchlist, cpp_pchlist, clist, cpplist, cudalist, cslist, valalist, objclist, objcpplist, fortranlist, rustlist \ - = extract_as_list(kwargs, 'c_pch', 'cpp_pch', 'c_args', 'cpp_args', 'cuda_args', 'cs_args', 'vala_args', 'objc_args', - 'objcpp_args', 'fortran_args', 'rust_args') + = (extract_as_list(kwargs, c) for c in ['c_pch', 'cpp_pch', 'c_args', 'cpp_args', 'cuda_args', 'cs_args', 'vala_args', 'objc_args', 'objcpp_args', 'fortran_args', 'rust_args']) self.add_pch('c', c_pchlist) self.add_pch('cpp', cpp_pchlist) @@ -857,7 +1107,7 @@ if dfeature_debug: dfeatures['debug'] = dfeature_debug if 'd_import_dirs' in kwargs: - dfeature_import_dirs = extract_as_list(kwargs, 'd_import_dirs', unholder=True) + dfeature_import_dirs = extract_as_list(kwargs, 'd_import_dirs') for d in dfeature_import_dirs: if not isinstance(d, IncludeDirs): raise InvalidArguments('Arguments to d_import_dirs must be include_directories.') @@ -871,8 +1121,11 @@ raise InvalidArguments('Link_args arguments must be strings.') for l in self.link_args: if '-Wl,-rpath' in l or l.startswith('-rpath'): - mlog.warning('''Please do not define rpath with a linker argument, use install_rpath or build_rpath properties instead. -This will become a hard error in a future Meson release.''') + mlog.warning(textwrap.dedent('''\ + Please do not define rpath with a linker argument, use install_rpath + or build_rpath properties instead. + This will become a hard error in a future Meson release.\ + ''')) self.process_link_depends(kwargs.get('link_depends', []), environment) # Target-specific include dirs must be added BEFORE include dirs from # internal deps (added inside self.add_deps()) to override them. @@ -883,27 +1136,37 @@ self.add_deps(deplist) # If an item in this list is False, the output corresponding to # the list index of that item will not be installed - self.install_dir = typeslistify(kwargs.get('install_dir', [None]), + self.install_dir = typeslistify(kwargs.get('install_dir', []), (str, bool)) self.install_mode = kwargs.get('install_mode', None) + self.install_tag = stringlistify(kwargs.get('install_tag', [None])) main_class = kwargs.get('main_class', '') if not isinstance(main_class, str): raise InvalidArguments('Main class must be a string') self.main_class = main_class if isinstance(self, Executable): - self.gui_app = kwargs.get('gui_app', False) - if not isinstance(self.gui_app, bool): - raise InvalidArguments('Argument gui_app must be boolean.') + # This kwarg is deprecated. The value of "none" means that the kwarg + # was not specified and win_subsystem should be used instead. + self.gui_app = None + if 'gui_app' in kwargs: + if 'win_subsystem' in kwargs: + raise InvalidArguments('Can specify only gui_app or win_subsystem for a target, not both.') + self.gui_app = kwargs['gui_app'] + if not isinstance(self.gui_app, bool): + raise InvalidArguments('Argument gui_app must be boolean.') + self.win_subsystem = self.validate_win_subsystem(kwargs.get('win_subsystem', 'console')) elif 'gui_app' in kwargs: raise InvalidArguments('Argument gui_app can only be used on executables.') + elif 'win_subsystem' in kwargs: + raise InvalidArguments('Argument win_subsystem can only be used on executables.') extra_files = extract_as_list(kwargs, 'extra_files') for i in extra_files: - assert(isinstance(i, File)) + assert isinstance(i, File) trial = os.path.join(environment.get_source_dir(), i.subdir, i.fname) - if not(os.path.isfile(trial)): - raise InvalidArguments('Tried to add non-existing extra file %s.' % i) + if not os.path.isfile(trial): + raise InvalidArguments(f'Tried to add non-existing extra file {i}.') self.extra_files = extra_files - self.install_rpath = kwargs.get('install_rpath', '') + self.install_rpath: str = kwargs.get('install_rpath', '') if not isinstance(self.install_rpath, str): raise InvalidArguments('Install_rpath is not a string.') self.build_rpath = kwargs.get('build_rpath', '') @@ -915,22 +1178,23 @@ raise InvalidArguments('Resource argument is not a string.') trial = os.path.join(environment.get_source_dir(), self.subdir, r) if not os.path.isfile(trial): - raise InvalidArguments('Tried to add non-existing resource %s.' % r) + raise InvalidArguments(f'Tried to add non-existing resource {r}.') self.resources = resources if 'name_prefix' in kwargs: name_prefix = kwargs['name_prefix'] if isinstance(name_prefix, list): if name_prefix: - raise InvalidArguments('name_prefix array must be empty to signify null.') - elif not isinstance(name_prefix, str): - raise InvalidArguments('name_prefix must be a string.') - self.prefix = name_prefix - self.name_prefix_set = True + raise InvalidArguments('name_prefix array must be empty to signify default.') + else: + if not isinstance(name_prefix, str): + raise InvalidArguments('name_prefix must be a string.') + self.prefix = name_prefix + self.name_prefix_set = True if 'name_suffix' in kwargs: name_suffix = kwargs['name_suffix'] if isinstance(name_suffix, list): if name_suffix: - raise InvalidArguments('name_suffix array must be empty to signify null.') + raise InvalidArguments('name_suffix array must be empty to signify default.') else: if not isinstance(name_suffix, str): raise InvalidArguments('name_suffix must be a string.') @@ -948,13 +1212,13 @@ if m.is_darwin() or m.is_windows(): self.pic = True else: - self.pic = self._extract_pic_pie(kwargs, 'pic') - if isinstance(self, Executable): + self.pic = self._extract_pic_pie(kwargs, 'pic', environment, 'b_staticpic') + if isinstance(self, Executable) or (isinstance(self, StaticLibrary) and not self.pic): # Executables must be PIE on Android if self.environment.machines[self.for_machine].is_android(): self.pie = True else: - self.pie = self._extract_pic_pie(kwargs, 'pie') + self.pie = self._extract_pic_pie(kwargs, 'pie', environment, 'b_pie') self.implicit_include_directories = kwargs.get('implicit_include_directories', True) if not isinstance(self.implicit_include_directories, bool): raise InvalidArguments('Implicit_include_directories must be a boolean.') @@ -964,47 +1228,52 @@ if self.gnu_symbol_visibility != '': permitted = ['default', 'internal', 'hidden', 'protected', 'inlineshidden'] if self.gnu_symbol_visibility not in permitted: - raise InvalidArguments('GNU symbol visibility arg %s not one of: %s', - self.symbol_visibility, ', '.join(permitted)) + raise InvalidArguments('GNU symbol visibility arg {} not one of: {}'.format(self.symbol_visibility, ', '.join(permitted))) - def _extract_pic_pie(self, kwargs, arg): + def validate_win_subsystem(self, value: str) -> str: + value = value.lower() + if re.fullmatch(r'(boot_application|console|efi_application|efi_boot_service_driver|efi_rom|efi_runtime_driver|native|posix|windows)(,\d+(\.\d+)?)?', value) is None: + raise InvalidArguments(f'Invalid value for win_subsystem: {value}.') + return value + + def _extract_pic_pie(self, kwargs, arg: str, environment, option: str): # Check if we have -fPIC, -fpic, -fPIE, or -fpie in cflags all_flags = self.extra_args['c'] + self.extra_args['cpp'] if '-f' + arg.lower() in all_flags or '-f' + arg.upper() in all_flags: - mlog.warning("Use the '{}' kwarg instead of passing '{}' manually to {!r}".format(arg, '-f' + arg, self.name)) + mlog.warning(f"Use the '{arg}' kwarg instead of passing '-f{arg}' manually to {self.name!r}") return True - val = kwargs.get(arg, False) + k = OptionKey(option) + if arg in kwargs: + val = kwargs[arg] + elif k in environment.coredata.options: + val = environment.coredata.options[k].value + else: + val = False + if not isinstance(val, bool): - raise InvalidArguments('Argument {} to {!r} must be boolean'.format(arg, self.name)) + raise InvalidArguments(f'Argument {arg} to {self.name!r} must be boolean') return val - def get_filename(self): + def get_filename(self) -> str: return self.filename - def get_outputs(self): + def get_outputs(self) -> T.List[str]: return self.outputs def get_extra_args(self, language): return self.extra_args.get(language, []) - def get_dependencies(self, exclude=None, for_pkgconfig=False): + def get_dependencies(self, exclude=None): transitive_deps = [] if exclude is None: exclude = [] for t in itertools.chain(self.link_targets, self.link_whole_targets): if t in transitive_deps or t in exclude: continue - # When generating `Libs:` and `Libs.private:` lists in pkg-config - # files we don't want to include static libraries that we link_whole - # or are uninstalled (they're implicitly promoted to link_whole). - # But we still need to include their transitive dependencies, - # a static library we link_whole would itself link to a shared - # library or an installed static library. - if not for_pkgconfig or (not t.is_internal() and t not in self.link_whole_targets): - transitive_deps.append(t) + transitive_deps.append(t) if isinstance(t, StaticLibrary): - transitive_deps += t.get_dependencies(transitive_deps + exclude, for_pkgconfig) + transitive_deps += t.get_dependencies(transitive_deps + exclude) return transitive_deps def get_source_subdir(self): @@ -1013,32 +1282,29 @@ def get_sources(self): return self.sources - def get_objects(self): + def get_objects(self) -> T.List[T.Union[str, 'File', 'ExtractedObjects']]: return self.objects - def get_generated_sources(self): + def get_generated_sources(self) -> T.List['GeneratedTypes']: return self.generated - def should_install(self): + def should_install(self) -> bool: return self.need_install - def has_pch(self): - return len(self.pch) > 0 + def has_pch(self) -> bool: + return bool(self.pch) - def get_pch(self, language): - try: - return self.pch[language] - except KeyError: - return[] + def get_pch(self, language: str) -> T.List[str]: + return self.pch.get(language, []) - def get_include_dirs(self): + def get_include_dirs(self) -> T.List['IncludeDirs']: return self.include_dirs def add_deps(self, deps): deps = listify(deps) for dep in deps: - if hasattr(dep, 'held_object'): - dep = dep.held_object + if dep in self.added_deps: + continue if isinstance(dep, dependencies.InternalDependency): # Those parts that are internal. self.process_sourcelist(dep.sources) @@ -1053,7 +1319,7 @@ [], dep.get_compile_args(), dep.get_link_args(), - [], [], [], []) + [], [], [], [], {}) self.external_deps.append(extpart) # Deps of deps. self.add_deps(dep.ext_deps) @@ -1073,33 +1339,40 @@ raise InvalidArguments('Tried to use subproject object as a dependency.\n' 'You probably wanted to use a dependency declared in it instead.\n' 'Access it by calling get_variable() on the subproject object.') - raise InvalidArguments('Argument is of an unacceptable type {!r}.\nMust be ' + raise InvalidArguments(f'Argument is of an unacceptable type {type(dep).__name__!r}.\nMust be ' 'either an external dependency (returned by find_library() or ' 'dependency()) or an internal dependency (returned by ' - 'declare_dependency()).'.format(type(dep).__name__)) + 'declare_dependency()).') + self.added_deps.add(dep) - def get_external_deps(self): + def get_external_deps(self) -> T.List[dependencies.Dependency]: return self.external_deps - def is_internal(self): + def is_internal(self) -> bool: return isinstance(self, StaticLibrary) and not self.need_install def link(self, target): - for t in listify(target, unholder=True): - if isinstance(self, StaticLibrary) and self.need_install and t.is_internal(): - # When we're a static library and we link_with to an - # internal/convenience library, promote to link_whole. - return self.link_whole(t) + for t in listify(target): + if isinstance(self, StaticLibrary) and self.need_install: + if isinstance(t, (CustomTarget, CustomTargetIndex)): + if not t.should_install(): + mlog.warning(f'Try to link an installed static library target {self.name} with a' + 'custom target that is not installed, this might cause problems' + 'when you try to use this static library') + elif t.is_internal(): + # When we're a static library and we link_with to an + # internal/convenience library, promote to link_whole. + return self.link_whole(t) if not isinstance(t, (Target, CustomTargetIndex)): - raise InvalidArguments('{!r} is not a target.'.format(t)) + raise InvalidArguments(f'{t!r} is not a target.') if not t.is_linkable_target(): - raise InvalidArguments('Link target {!r} is not linkable.'.format(t)) + raise InvalidArguments(f"Link target '{t!s}' is not linkable.") if isinstance(self, SharedLibrary) and isinstance(t, StaticLibrary) and not t.pic: - msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name) + msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) if self.for_machine is not t.for_machine: - msg = 'Tried to mix libraries for machines {} and {} in target {!r}'.format(self.for_machine, t.for_machine, self.name) + msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' if self.environment.is_cross_build(): raise InvalidArguments(msg + ' This is not possible in a cross build.') else: @@ -1107,23 +1380,23 @@ self.link_targets.append(t) def link_whole(self, target): - for t in listify(target, unholder=True): + for t in listify(target): if isinstance(t, (CustomTarget, CustomTargetIndex)): if not t.is_linkable_target(): - raise InvalidArguments('Custom target {!r} is not linkable.'.format(t)) + raise InvalidArguments(f'Custom target {t!r} is not linkable.') if not t.get_filename().endswith('.a'): raise InvalidArguments('Can only link_whole custom targets that are .a archives.') if isinstance(self, StaticLibrary): # FIXME: We could extract the .a archive to get object files raise InvalidArguments('Cannot link_whole a custom target into a static library') elif not isinstance(t, StaticLibrary): - raise InvalidArguments('{!r} is not a static library.'.format(t)) + raise InvalidArguments(f'{t!r} is not a static library.') elif isinstance(self, SharedLibrary) and not t.pic: - msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name) + msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) if self.for_machine is not t.for_machine: - msg = 'Tried to mix libraries for machines {1} and {2} in target {0!r}'.format(self.name, self.for_machine, t.for_machine) + msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' if self.environment.is_cross_build(): raise InvalidArguments(msg + ' This is not possible in a cross build.') else: @@ -1134,19 +1407,19 @@ self.objects += t.extract_all_objects_recurse() self.link_whole_targets.append(t) - def extract_all_objects_recurse(self): + def extract_all_objects_recurse(self) -> T.List[T.Union[str, 'ExtractedObjects']]: objs = [self.extract_all_objects()] for t in self.link_targets: if t.is_internal(): objs += t.extract_all_objects_recurse() return objs - def add_pch(self, language, pchlist): + def add_pch(self, language: str, pchlist: T.List[str]) -> None: if not pchlist: return elif len(pchlist) == 1: if not environment.is_header(pchlist[0]): - raise InvalidArguments('PCH argument %s is not a header.' % pchlist[0]) + raise InvalidArguments(f'PCH argument {pchlist[0]} is not a header.') elif len(pchlist) == 2: if environment.is_header(pchlist[0]): if not environment.is_source(pchlist[1]): @@ -1156,27 +1429,25 @@ raise InvalidArguments('PCH definition must contain one header and at most one source.') pchlist = [pchlist[1], pchlist[0]] else: - raise InvalidArguments('PCH argument %s is of unknown type.' % pchlist[0]) + raise InvalidArguments(f'PCH argument {pchlist[0]} is of unknown type.') - if (os.path.dirname(pchlist[0]) != os.path.dirname(pchlist[1])): + if os.path.dirname(pchlist[0]) != os.path.dirname(pchlist[1]): raise InvalidArguments('PCH files must be stored in the same folder.') - mlog.warning('PCH source files are deprecated, only a single header file should be used.') + FeatureDeprecated.single_use('PCH source files', '0.50.0', self.subproject, + 'Only a single header file should be used.') elif len(pchlist) > 2: raise InvalidArguments('PCH definition may have a maximum of 2 files.') for f in pchlist: if not isinstance(f, str): raise MesonException('PCH arguments must be strings.') if not os.path.isfile(os.path.join(self.environment.source_dir, self.subdir, f)): - raise MesonException('File %s does not exist.' % f) + raise MesonException(f'File {f} does not exist.') self.pch[language] = pchlist - def add_include_dirs(self, args, set_is_system: T.Optional[str] = None): - ids = [] + def add_include_dirs(self, args: T.Sequence['IncludeDirs'], set_is_system: T.Optional[str] = None) -> None: + ids: T.List['IncludeDirs'] = [] for a in args: - # FIXME same hack, forcibly unpack from holder. - if hasattr(a, 'held_object'): - a = a.held_object if not isinstance(a, IncludeDirs): raise InvalidArguments('Include directory to be added is not an include directory object.') ids.append(a) @@ -1187,7 +1458,7 @@ ids = [IncludeDirs(x.get_curdir(), x.get_incdirs(), is_system, x.get_extra_build_dirs()) for x in ids] self.include_dirs += ids - def add_compiler_args(self, language, args): + def add_compiler_args(self, language: str, args: T.List['FileOrString']) -> None: args = listify(args) for a in args: if not isinstance(a, (str, File)): @@ -1197,7 +1468,7 @@ else: self.extra_args[language] = args - def get_aliases(self): + def get_aliases(self) -> T.Dict[str, str]: return {} def get_langs_used_by_deps(self) -> T.List[str]: @@ -1209,11 +1480,7 @@ See: https://github.com/mesonbuild/meson/issues/1653 ''' - langs = [] - - # User specified link_language of target (for multi-language targets) - if self.link_language: - return [self.link_language] + langs = [] # type: T.List[str] # Check if any of the external libraries were written in this language for dep in self.external_deps: @@ -1232,7 +1499,24 @@ return langs - def get_clink_dynamic_linker_and_stdlibs(self): + def get_prelinker(self): + all_compilers = self.environment.coredata.compilers[self.for_machine] + if self.link_language: + comp = all_compilers[self.link_language] + return comp + for l in clink_langs: + if l in self.compilers: + try: + prelinker = all_compilers[l] + except KeyError: + raise MesonException( + f'Could not get a prelinker linker for build target {self.name!r}. ' + f'Requires a compiler for language "{l}", but that is not ' + 'a project language.') + return prelinker + raise MesonException(f'Could not determine prelinker for {self.name!r}.') + + def get_clink_dynamic_linker_and_stdlibs(self) -> T.Tuple['Compiler', T.List[str]]: ''' We use the order of languages in `clink_langs` to determine which linker to use in case the target has sources compiled with multiple @@ -1245,6 +1529,12 @@ # Populate list of all compilers, not just those being used to compile # sources in this target all_compilers = self.environment.coredata.compilers[self.for_machine] + + # If the user set the link_language, just return that. + if self.link_language: + comp = all_compilers[self.link_language] + return comp, comp.language_stdlib_only_link_flags(self.environment) + # Languages used by dependencies dep_langs = self.get_langs_used_by_deps() # Pick a compiler based on the language priority-order @@ -1254,25 +1544,33 @@ linker = all_compilers[l] except KeyError: raise MesonException( - 'Could not get a dynamic linker for build target {!r}. ' - 'Requires a linker for language "{}", but that is not ' - 'a project language.'.format(self.name, l)) - stdlib_args = [] - added_languages = set() + f'Could not get a dynamic linker for build target {self.name!r}. ' + f'Requires a linker for language "{l}", but that is not ' + 'a project language.') + stdlib_args: T.List[str] = [] + added_languages: T.Set[str] = set() for dl in itertools.chain(self.compilers, dep_langs): if dl != linker.language: - stdlib_args += all_compilers[dl].language_stdlib_only_link_flags() + stdlib_args += all_compilers[dl].language_stdlib_only_link_flags(self.environment) added_languages.add(dl) + # Type of var 'linker' is Compiler. + # Pretty hard to fix because the return value is passed everywhere return linker, stdlib_args - m = 'Could not get a dynamic linker for build target {!r}' - raise AssertionError(m.format(self.name)) + raise AssertionError(f'Could not get a dynamic linker for build target {self.name!r}') - def get_using_rustc(self): - if len(self.sources) > 0 and self.sources[0].fname.endswith('.rs'): - return True + def uses_rust(self) -> bool: + """Is this target a rust target.""" + if self.sources: + first_file = self.sources[0] + if first_file.fname.endswith('.rs'): + return True + elif self.generated: + if self.generated[0].get_outputs()[0].endswith('.rs'): + return True + return False - def get_using_msvc(self): + def get_using_msvc(self) -> bool: ''' Check if the dynamic linker is MSVC. Used by Executable, StaticLibrary, and SharedLibrary for deciding when to use MSVC-specific file naming @@ -1290,165 +1588,148 @@ 2. If the target contains only objects, process_compilers guesses and picks the first compiler that smells right. ''' - linker, _ = self.get_clink_dynamic_linker_and_stdlibs() + # Rustc can use msvc style linkers + if self.uses_rust(): + compiler = self.environment.coredata.compilers[self.for_machine]['rust'] + else: + compiler, _ = self.get_clink_dynamic_linker_and_stdlibs() # Mixing many languages with MSVC is not supported yet so ignore stdlibs. - if linker and linker.get_id() in {'msvc', 'clang-cl', 'intel-cl', 'llvm', 'dmd', 'nvcc'}: - return True - return False + return compiler and compiler.get_linker_id() in {'link', 'lld-link', 'xilink', 'optlink'} def check_module_linking(self): ''' Warn if shared modules are linked with target: (link_with) #2865 ''' for link_target in self.link_targets: - if isinstance(link_target, SharedModule): + if isinstance(link_target, SharedModule) and not link_target.backwards_compat_want_soname: if self.environment.machines[self.for_machine].is_darwin(): - raise MesonException('''target links against shared modules. -This is not permitted on OSX''') + raise MesonException( + f'target {self.name} links against shared module {link_target.name}. This is not permitted on OSX') else: - mlog.warning('''target links against shared modules. This is not -recommended as it is not supported on some platforms''') - return - -class Generator: - def __init__(self, args, kwargs): - if len(args) != 1: - raise InvalidArguments('Generator requires exactly one positional argument: the executable') - exe = args[0] - if hasattr(exe, 'held_object'): - exe = exe.held_object - if not isinstance(exe, (Executable, dependencies.ExternalProgram)): - raise InvalidArguments('First generator argument must be an executable.') + mlog.deprecation(f'target {self.name} links against shared module {link_target.name}, which is incorrect.' + '\n ' + f'This will be an error in the future, so please use shared_library() for {link_target.name} instead.' + '\n ' + f'If shared_module() was used for {link_target.name} because it has references to undefined symbols,' + '\n ' + 'use shared_libary() with `override_options: [\'b_lundef=false\']` instead.') + link_target.backwards_compat_want_soname = True + +class Generator(HoldableObject): + def __init__(self, exe: T.Union['Executable', programs.ExternalProgram], + arguments: T.List[str], + output: T.List[str], + *, + depfile: T.Optional[str] = None, + capture: bool = False, + depends: T.Optional[T.List[T.Union[BuildTarget, 'CustomTarget']]] = None, + name: str = 'Generator'): self.exe = exe - self.depfile = None - self.capture = False - self.depends = [] - self.process_kwargs(kwargs) + self.depfile = depfile + self.capture = capture + self.depends: T.List[T.Union[BuildTarget, 'CustomTarget']] = depends or [] + self.arglist = arguments + self.outputs = output + self.name = name - def __repr__(self): + def __repr__(self) -> str: repr_str = "<{0}: {1}>" return repr_str.format(self.__class__.__name__, self.exe) - def get_exe(self): + def get_exe(self) -> T.Union['Executable', programs.ExternalProgram]: return self.exe - def process_kwargs(self, kwargs): - if 'arguments' not in kwargs: - raise InvalidArguments('Generator must have "arguments" keyword argument.') - args = kwargs['arguments'] - if isinstance(args, str): - args = [args] - if not isinstance(args, list): - raise InvalidArguments('"Arguments" keyword argument must be a string or a list of strings.') - for a in args: - if not isinstance(a, str): - raise InvalidArguments('A non-string object in "arguments" keyword argument.') - self.arglist = args - if 'output' not in kwargs: - raise InvalidArguments('Generator must have "output" keyword argument.') - outputs = listify(kwargs['output']) - for rule in outputs: - if not isinstance(rule, str): - raise InvalidArguments('"output" may only contain strings.') - if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule: - raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.') - if has_path_sep(rule): - raise InvalidArguments('"outputs" must not contain a directory separator.') - if len(outputs) > 1: - for o in outputs: - if '@OUTPUT@' in o: - raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.') - self.outputs = outputs - if 'depfile' in kwargs: - depfile = kwargs['depfile'] - if not isinstance(depfile, str): - raise InvalidArguments('Depfile must be a string.') - if os.path.basename(depfile) != depfile: - raise InvalidArguments('Depfile must be a plain filename without a subdirectory.') - self.depfile = depfile - if 'capture' in kwargs: - capture = kwargs['capture'] - if not isinstance(capture, bool): - raise InvalidArguments('Capture must be boolean.') - self.capture = capture - if 'depends' in kwargs: - depends = listify(kwargs['depends'], unholder=True) - for d in depends: - if not isinstance(d, BuildTarget): - raise InvalidArguments('Depends entries must be build targets.') - self.depends.append(d) - - def get_base_outnames(self, inname): + def get_base_outnames(self, inname: str) -> T.List[str]: plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] bases = [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs] return bases - def get_dep_outname(self, inname): + def get_dep_outname(self, inname: str) -> T.List[str]: if self.depfile is None: raise InvalidArguments('Tried to get dep name for rule that does not have dependency file defined.') plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) - def get_arglist(self, inname): + def get_arglist(self, inname: str) -> T.List[str]: plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist] - def is_parent_path(self, parent, trial): + @staticmethod + def is_parent_path(parent: str, trial: str) -> bool: relpath = pathlib.PurePath(trial).relative_to(parent) return relpath.parts[0] != '..' # For subdirs we can only go "down". - def process_files(self, name, files, state, preserve_path_from=None, extra_args=None): + def process_files(self, files: T.Iterable[T.Union[str, File, 'CustomTarget', 'CustomTargetIndex', 'GeneratedList']], + state: T.Union['Interpreter', 'ModuleState'], + preserve_path_from: T.Optional[str] = None, + extra_args: T.Optional[T.List[str]] = None) -> 'GeneratedList': output = GeneratedList(self, state.subdir, preserve_path_from, extra_args=extra_args if extra_args is not None else []) - for f in files: - if isinstance(f, str): - f = File.from_source_file(state.environment.source_dir, state.subdir, f) - elif not isinstance(f, File): - raise InvalidArguments('{} arguments must be strings or files not {!r}.'.format(name, f)) - if preserve_path_from: - abs_f = f.absolute_path(state.environment.source_dir, state.environment.build_dir) - if not self.is_parent_path(preserve_path_from, abs_f): - raise InvalidArguments('When using preserve_path_from, all input files must be in a subdirectory of the given dir.') - output.add_file(f, state) + + for e in files: + if isinstance(e, CustomTarget): + output.depends.add(e) + if isinstance(e, CustomTargetIndex): + output.depends.add(e.target) + + if isinstance(e, (CustomTarget, CustomTargetIndex, GeneratedList)): + self.depends.append(e) # BUG: this should go in the GeneratedList object, not this object. + fs = [File.from_built_file(state.subdir, f) for f in e.get_outputs()] + elif isinstance(e, str): + fs = [File.from_source_file(state.environment.source_dir, state.subdir, e)] + else: + fs = [e] + + for f in fs: + if preserve_path_from: + abs_f = f.absolute_path(state.environment.source_dir, state.environment.build_dir) + if not self.is_parent_path(preserve_path_from, abs_f): + raise InvalidArguments('generator.process: When using preserve_path_from, all input files must be in a subdirectory of the given dir.') + output.add_file(f, state) return output -class GeneratedList: - def __init__(self, generator, subdir, preserve_path_from=None, extra_args=None): - if hasattr(generator, 'held_object'): - generator = generator.held_object +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 = self.generator.exe + self.name = 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 = [] - self.outfilelist = [] - self.outmap = {} - self.extra_depends = [] - self.depend_files = [] + 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 = extra_args if extra_args is not None else [] - if isinstance(generator.exe, dependencies.ExternalProgram): - if not generator.exe.found(): + self.extra_args: T.List[str] = extra_args if extra_args is not None else [] + + if isinstance(self.generator.exe, programs.ExternalProgram): + if not self.generator.exe.found(): raise InvalidArguments('Tried to use not-found external program as generator') - path = generator.exe.get_path() + path = self.generator.exe.get_path() if os.path.isabs(path): # Can only add a dependency on an external program which we # know the absolute path of self.depend_files.append(File.from_absolute_file(path)) - def add_preserved_path_segment(self, infile, outfiles, state): - result = [] + def add_preserved_path_segment(self, infile: File, outfiles: T.List[str], state: T.Union['Interpreter', 'ModuleState']) -> T.List[str]: + result: T.List[str] = [] in_abs = infile.absolute_path(state.environment.source_dir, state.environment.build_dir) - assert(os.path.isabs(self.preserve_path_from)) + assert os.path.isabs(self.preserve_path_from) rel = os.path.relpath(in_abs, self.preserve_path_from) path_segment = os.path.dirname(rel) for of in outfiles: result.append(os.path.join(path_segment, of)) return result - def add_file(self, newfile, state): + def add_file(self, newfile: File, state: T.Union['Interpreter', 'ModuleState']) -> None: self.infilelist.append(newfile) outfiles = self.generator.get_base_outnames(newfile.fname) if self.preserve_path_from: @@ -1456,28 +1737,34 @@ self.outfilelist += outfiles self.outmap[newfile] = outfiles - def get_inputs(self): + def get_inputs(self) -> T.List['File']: return self.infilelist - def get_outputs(self): + def get_outputs(self) -> T.List[str]: return self.outfilelist - def get_outputs_for(self, filename): + def get_outputs_for(self, filename: 'File') -> T.List[str]: return self.outmap[filename] - def get_generator(self): + def get_generator(self) -> 'Generator': return self.generator - def get_extra_args(self): + def get_extra_args(self) -> T.List[str]: return self.extra_args + def get_subdir(self) -> str: + return self.subdir + + class Executable(BuildTarget): known_kwargs = known_exe_kwargs - def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): + def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice, + sources: T.List[File], objects, environment: environment.Environment, kwargs): self.typename = 'executable' - if 'pie' not in kwargs and 'b_pie' in environment.coredata.base_options: - kwargs['pie'] = environment.coredata.base_options['b_pie'].value + key = OptionKey('b_pie') + if 'pie' not in kwargs and key in environment.coredata.options: + kwargs['pie'] = environment.coredata.options[key].value super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) # Unless overridden, executables have no suffix or prefix. Except on # Windows and with C#/Mono executables where the suffix is 'exe' @@ -1496,6 +1783,11 @@ 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')): self.suffix = 'abs' + elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('xc16')): + self.suffix = 'elf' + elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('c2000') or + 'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('c2000')): + self.suffix = 'out' else: self.suffix = environment.machines[for_machine].get_exe_suffix() self.filename = self.name @@ -1531,23 +1823,26 @@ if not isinstance(kwargs.get('implib', False), bool): implib_basename = kwargs['implib'] if m.is_windows() or m.is_cygwin(): - self.vs_import_filename = '{0}.lib'.format(implib_basename) - self.gcc_import_filename = 'lib{0}.a'.format(implib_basename) + self.vs_import_filename = f'{implib_basename}.lib' + self.gcc_import_filename = f'lib{implib_basename}.a' if self.get_using_msvc(): self.import_filename = self.vs_import_filename else: self.import_filename = self.gcc_import_filename if m.is_windows() and ('cs' in self.compilers or - self.get_using_rustc() or + self.uses_rust() or self.get_using_msvc()): self.debug_filename = self.name + '.pdb' # Only linkwithable if using export_dynamic self.is_linkwithable = self.export_dynamic - def get_default_install_dir(self, environment): - return environment.get_bindir() + # Remember that this exe was returned by `find_program()` through an override + self.was_returned_by_find_program = False + + def get_default_install_dir(self, environment: environment.Environment) -> T.Tuple[str, str]: + return environment.get_bindir(), '{bindir}' def description(self): '''Human friendly description of the executable''' @@ -1556,7 +1851,7 @@ def type_suffix(self): return "@exe" - def get_import_filename(self): + def get_import_filename(self) -> T.Optional[str]: """ The name of the import library that will be outputted by the compiler @@ -1569,7 +1864,7 @@ return [self.vs_import_filename, self.gcc_import_filename] return [] - def get_debug_filename(self): + def get_debug_filename(self) -> T.Optional[str]: """ The name of debuginfo file that will be created by the compiler @@ -1580,13 +1875,18 @@ def is_linkable_target(self): return self.is_linkwithable + def get_command(self) -> 'ImmutableListProtocol[str]': + """Provides compatibility with ExternalProgram. + + Since you can override ExternalProgram instances with Executables. + """ + return self.outputs + class StaticLibrary(BuildTarget): known_kwargs = known_stlib_kwargs def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): self.typename = 'static library' - if 'pic' not in kwargs and 'b_staticpic' in environment.coredata.base_options: - kwargs['pic'] = environment.coredata.base_options['b_staticpic'].value super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) if 'cs' in self.compilers: raise InvalidArguments('Static libraries not supported for C#.') @@ -1597,7 +1897,7 @@ self.rust_crate_type = 'rlib' # Don't let configuration proceed with a non-static crate type elif self.rust_crate_type not in ['rlib', 'staticlib']: - raise InvalidArguments('Crate type "{0}" invalid for static libraries; must be "rlib" or "staticlib"'.format(self.rust_crate_type)) + raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for static libraries; must be "rlib" or "staticlib"') # By default a static library is named libfoo.a even on Windows because # MSVC does not have a consistent convention for what static libraries # are called. The MSVC CRT uses libfoo.lib syntax but nothing else uses @@ -1618,12 +1918,15 @@ self.suffix = 'a' self.filename = self.prefix + self.name + '.' + self.suffix self.outputs = [self.filename] + self.prelink = kwargs.get('prelink', False) + if not isinstance(self.prelink, bool): + raise InvalidArguments('Prelink keyword argument must be a boolean.') - def get_link_deps_mapping(self, prefix, environment): + def get_link_deps_mapping(self, prefix: str, environment: environment.Environment) -> T.Mapping[str, str]: return {} - def get_default_install_dir(self, environment): - return environment.get_static_lib_dir() + def get_default_install_dir(self, environment) -> T.Tuple[str, str]: + return environment.get_static_lib_dir(), '{libdir_static}' def type_suffix(self): return "@sta" @@ -1635,7 +1938,7 @@ if isinstance(rust_crate_type, str): self.rust_crate_type = rust_crate_type else: - raise InvalidArguments('Invalid rust_crate_type "{0}": must be a string.'.format(rust_crate_type)) + raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.') def is_linkable_target(self): return True @@ -1658,6 +1961,8 @@ self.gcc_import_filename = None # The debugging information file this target will generate self.debug_filename = None + # Use by the pkgconfig module + self.shared_library_only = False super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) if 'rust' in self.compilers: # If no crate type is specified, or it's the generic lib type, use dylib @@ -1666,7 +1971,7 @@ self.rust_crate_type = 'dylib' # Don't let configuration proceed with a non-dynamic crate type elif self.rust_crate_type not in ['dylib', 'cdylib']: - raise InvalidArguments('Crate type "{0}" invalid for dynamic libraries; must be "dylib" or "cdylib"'.format(self.rust_crate_type)) + raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for dynamic libraries; must be "dylib" or "cdylib"') if not hasattr(self, 'prefix'): self.prefix = None if not hasattr(self, 'suffix'): @@ -1674,20 +1979,20 @@ self.basic_filename_tpl = '{0.prefix}{0.name}.{0.suffix}' self.determine_filenames(environment) - def get_link_deps_mapping(self, prefix, environment): - result = {} + def get_link_deps_mapping(self, prefix: str, environment: environment.Environment) -> T.Mapping[str, str]: + result: T.Dict[str, str] = {} mappings = self.get_transitive_link_deps_mapping(prefix, environment) old = get_target_macos_dylib_install_name(self) if old not in mappings: fname = self.get_filename() - outdirs, _ = self.get_install_dir(self.environment) + outdirs, _, _ = self.get_install_dir(self.environment) new = os.path.join(prefix, outdirs[0], fname) result.update({old: new}) mappings.update(result) return mappings - def get_default_install_dir(self, environment): - return environment.get_shared_lib_dir() + def get_default_install_dir(self, environment) -> T.Tuple[str, str]: + return environment.get_shared_lib_dir(), '{libdir_shared}' def determine_filenames(self, env): """ @@ -1726,13 +2031,13 @@ # For all other targets/platforms import_filename stays None elif env.machines[self.for_machine].is_windows(): suffix = 'dll' - self.vs_import_filename = '{0}{1}.lib'.format(self.prefix if self.prefix is not None else '', self.name) - self.gcc_import_filename = '{0}{1}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) - if self.get_using_rustc(): + self.vs_import_filename = '{}{}.lib'.format(self.prefix if self.prefix is not None else '', self.name) + self.gcc_import_filename = '{}{}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) + if self.uses_rust(): # Shared library is of the form foo.dll prefix = '' # Import library is called foo.dll.lib - self.import_filename = '{0}.dll.lib'.format(self.name) + self.import_filename = f'{self.name}.dll.lib' create_debug_file = True elif self.get_using_msvc(): # Shared library is of the form foo.dll @@ -1753,7 +2058,7 @@ self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' elif env.machines[self.for_machine].is_cygwin(): suffix = 'dll' - self.gcc_import_filename = '{0}{1}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) + self.gcc_import_filename = '{}{}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) # Shared library is of the form cygfoo.dll # (ld --dll-search-prefix=cyg is the default) prefix = 'cyg' @@ -1808,7 +2113,7 @@ darwin_versions = 2 * [darwin_versions] if not isinstance(darwin_versions, list): raise InvalidArguments('Shared library darwin_versions: must be a string, integer,' - 'or a list, not {!r}'.format(darwin_versions)) + f'or a list, not {darwin_versions!r}') if len(darwin_versions) > 2: raise InvalidArguments('Shared library darwin_versions: list must contain 2 or fewer elements') if len(darwin_versions) == 1: @@ -1818,7 +2123,7 @@ v = str(v) if not isinstance(v, str): raise InvalidArguments('Shared library darwin_versions: list elements ' - 'must be strings or integers, not {!r}'.format(v)) + f'must be strings or integers, not {v!r}') if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', v): raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z where ' 'X, Y, Z are numbers, and Y and Z are optional') @@ -1852,7 +2157,7 @@ if not isinstance(self.ltversion, str): raise InvalidArguments('Shared library version needs to be a string, not ' + type(self.ltversion).__name__) if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', self.ltversion): - raise InvalidArguments('Invalid Shared library version "{0}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.'.format(self.ltversion)) + raise InvalidArguments(f'Invalid Shared library version "{self.ltversion}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.') # Try to extract/deduce the soversion if 'soversion' in kwargs: self.soversion = kwargs['soversion'] @@ -1875,35 +2180,31 @@ # Visual Studio module-definitions file if 'vs_module_defs' in kwargs: path = kwargs['vs_module_defs'] - if hasattr(path, 'held_object'): - path = path.held_object if isinstance(path, str): if os.path.isabs(path): self.vs_module_defs = File.from_absolute_file(path) else: self.vs_module_defs = File.from_source_file(environment.source_dir, self.subdir, path) - self.link_depends.append(self.vs_module_defs) elif isinstance(path, File): # When passing a generated file. self.vs_module_defs = path - self.link_depends.append(path) elif hasattr(path, 'get_filename'): # When passing output of a Custom Target - path = File.from_built_file(path.subdir, path.get_filename()) - self.vs_module_defs = path - self.link_depends.append(path) + self.vs_module_defs = File.from_built_file(path.subdir, path.get_filename()) else: raise InvalidArguments( 'Shared library vs_module_defs must be either a string, ' 'a file object or a Custom Target') + self.process_link_depends(path, environment) + if 'rust_crate_type' in kwargs: rust_crate_type = kwargs['rust_crate_type'] if isinstance(rust_crate_type, str): self.rust_crate_type = rust_crate_type else: - raise InvalidArguments('Invalid rust_crate_type "{0}": must be a string.'.format(rust_crate_type)) + raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.') - def get_import_filename(self): + def get_import_filename(self) -> T.Optional[str]: """ The name of the import library that will be outputted by the compiler @@ -1911,7 +2212,7 @@ """ return self.import_filename - def get_debug_filename(self): + def get_debug_filename(self) -> T.Optional[str]: """ The name of debuginfo file that will be created by the compiler @@ -1927,7 +2228,7 @@ def get_all_link_deps(self): return [self] + self.get_transitive_link_deps() - def get_aliases(self): + def get_aliases(self) -> T.Dict[str, str]: """ If the versioned library name is libfoo.so.0.100.0, aliases are: * libfoo.so.0 (soversion) -> libfoo.so.0.100.0 @@ -1935,11 +2236,11 @@ Same for dylib: * libfoo.dylib (unversioned; for linking) -> libfoo.0.dylib """ - aliases = {} + aliases: T.Dict[str, str] = {} # Aliases are only useful with .so and .dylib libraries. Also if # there's no self.soversion (no versioning), we don't need aliases. if self.suffix not in ('so', 'dylib') or not self.soversion: - return {} + return aliases # With .so libraries, the minor and micro versions are also in the # filename. If ltversion != soversion we create an soversion alias: # libfoo.so.0 -> libfoo.so.0.100.0 @@ -1975,20 +2276,79 @@ raise MesonException('Shared modules must not specify the soversion kwarg.') super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) self.typename = 'shared module' + # We need to set the soname in cases where build files link the module + # to build targets, see: https://github.com/mesonbuild/meson/issues/9492 + self.backwards_compat_want_soname = False + + def get_default_install_dir(self, environment) -> T.Tuple[str, str]: + return environment.get_shared_module_dir(), '{moduledir_shared}' + +class BothLibraries(SecondLevelHolder): + def __init__(self, shared: SharedLibrary, static: StaticLibrary) -> None: + self._preferred_library = 'shared' + self.shared = shared + self.static = static + self.subproject = self.shared.subproject + + def __repr__(self) -> str: + return f'' + + def get_default_object(self) -> BuildTarget: + if self._preferred_library == 'shared': + return self.shared + elif self._preferred_library == 'static': + return self.static + raise MesonBugException(f'self._preferred_library == "{self._preferred_library}" is neither "shared" nor "static".') + +class CommandBase: + + depend_files: T.List[File] + dependencies: T.List[T.Union[BuildTarget, 'CustomTarget']] + subproject: str + + def flatten_command(self, cmd: T.Sequence[T.Union[str, File, programs.ExternalProgram, 'BuildTarget', 'CustomTarget', 'CustomTargetIndex']]) -> \ + T.List[T.Union[str, File, BuildTarget, 'CustomTarget']]: + cmd = listify(cmd) + final_cmd: T.List[T.Union[str, File, BuildTarget, 'CustomTarget']] = [] + for c in cmd: + if isinstance(c, str): + final_cmd.append(c) + elif isinstance(c, File): + self.depend_files.append(c) + final_cmd.append(c) + elif isinstance(c, programs.ExternalProgram): + if not c.found(): + raise InvalidArguments('Tried to use not-found external program in "command"') + path = c.get_path() + if os.path.isabs(path): + # Can only add a dependency on an external program which we + # know the absolute path of + self.depend_files.append(File.from_absolute_file(path)) + final_cmd += c.get_command() + elif isinstance(c, (BuildTarget, CustomTarget)): + self.dependencies.append(c) + final_cmd.append(c) + elif isinstance(c, CustomTargetIndex): + FeatureNew.single_use('CustomTargetIndex for command argument', '0.60', self.subproject) + self.dependencies.append(c.target) + final_cmd += self.flatten_command(File.from_built_file(c.get_subdir(), c.get_filename())) + elif isinstance(c, list): + final_cmd += self.flatten_command(c) + else: + raise InvalidArguments(f'Argument {c!r} in "command" is invalid') + return final_cmd - def get_default_install_dir(self, environment): - return environment.get_shared_module_dir() - - -class CustomTarget(Target): - known_kwargs = set([ +class CustomTarget(Target, CommandBase): + known_kwargs = { 'input', 'output', 'command', 'capture', + 'feed', 'install', 'install_dir', 'install_mode', + 'install_tag', 'build_always', 'build_always_stale', 'depends', @@ -1997,46 +2357,48 @@ 'build_by_default', 'override_options', 'console', - ]) + 'env', + } + + install_dir: T.List[T.Union[str, bool]] - def __init__(self, name, subdir, subproject, kwargs, absolute_paths=False, backend=None): + def __init__(self, name: str, subdir: str, subproject: str, kwargs: T.Mapping[str, T.Any], + absolute_paths: bool = False, backend: T.Optional['Backend'] = None): self.typename = 'custom' # TODO expose keyword arg to make MachineChoice.HOST configurable super().__init__(name, subdir, subproject, False, MachineChoice.HOST) - self.dependencies = [] - self.extra_depends = [] + self.dependencies: T.List[T.Union[CustomTarget, BuildTarget]] = [] + self.extra_depends: T.List[T.Union[CustomTarget, BuildTarget]] = [] self.depend_files = [] # Files that this target depends on but are not on the command line. self.depfile = None self.process_kwargs(kwargs, backend) - self.extra_files = [] # Whether to use absolute paths for all files on the commandline self.absolute_paths = absolute_paths unknowns = [] for k in kwargs: if k not in CustomTarget.known_kwargs: unknowns.append(k) - if len(unknowns) > 0: - mlog.warning('Unknown keyword arguments in target %s: %s' % - (self.name, ', '.join(unknowns))) + if unknowns: + mlog.warning('Unknown keyword arguments in target {}: {}'.format(self.name, ', '.join(unknowns))) - def get_default_install_dir(self, environment): - return None + def get_default_install_dir(self, environment) -> T.Tuple[str, str]: + return None, None def __repr__(self): repr_str = "<{0} {1}: {2}>" return repr_str.format(self.__class__.__name__, self.get_id(), self.command) - def get_target_dependencies(self): + def get_target_dependencies(self) -> T.List[T.Union['BuildTarget', 'CustomTarget']]: deps = self.dependencies[:] deps += self.extra_depends for c in self.sources: - if hasattr(c, 'held_object'): - c = c.held_object if isinstance(c, (BuildTarget, CustomTarget)): deps.append(c) + if isinstance(c, CustomTargetIndex): + deps.append(c.target) return deps - def get_transitive_build_target_deps(self): + def get_transitive_build_target_deps(self) -> T.Set[T.Union[BuildTarget, 'CustomTarget']]: ''' Recursively fetch the build targets that this custom target depends on, whether through `command:`, `depends:`, or `sources:` The recursion is @@ -2045,7 +2407,7 @@ F.ex, if you have a python script that loads a C module that links to other DLLs in your project. ''' - bdeps = set() + bdeps: T.Set[T.Union[BuildTarget, 'CustomTarget']] = set() deps = self.get_target_dependencies() for d in deps: if isinstance(d, BuildTarget): @@ -2054,36 +2416,9 @@ bdeps.update(d.get_transitive_build_target_deps()) return bdeps - def flatten_command(self, cmd): - cmd = listify(cmd, unholder=True) - final_cmd = [] - for c in cmd: - if isinstance(c, str): - final_cmd.append(c) - elif isinstance(c, File): - self.depend_files.append(c) - final_cmd.append(c) - elif isinstance(c, dependencies.ExternalProgram): - if not c.found(): - raise InvalidArguments('Tried to use not-found external program in "command"') - path = c.get_path() - if os.path.isabs(path): - # Can only add a dependency on an external program which we - # know the absolute path of - self.depend_files.append(File.from_absolute_file(path)) - final_cmd += c.get_command() - elif isinstance(c, (BuildTarget, CustomTarget)): - self.dependencies.append(c) - final_cmd.append(c) - elif isinstance(c, list): - final_cmd += self.flatten_command(c) - else: - raise InvalidArguments('Argument {!r} in "command" is invalid'.format(c)) - return final_cmd - def process_kwargs(self, kwargs, backend): self.process_kwargs_base(kwargs) - self.sources = extract_as_list(kwargs, 'input', unholder=True) + self.sources = extract_as_list(kwargs, 'input') if 'output' not in kwargs: raise InvalidArguments('Missing keyword argument "output".') self.outputs = listify(kwargs['output']) @@ -2091,14 +2426,14 @@ inputs = get_sources_string_names(self.sources, backend) values = get_filenames_templates_dict(inputs, []) for i in self.outputs: - if not(isinstance(i, str)): + if not isinstance(i, str): raise InvalidArguments('Output argument not a string.') if i == '': raise InvalidArguments('Output must not be empty.') if i.strip() == '': raise InvalidArguments('Output must not consist only of whitespace.') if has_path_sep(i): - raise InvalidArguments('Output {!r} must not contain a path segment.'.format(i)) + raise InvalidArguments(f'Output {i!r} must not contain a path segment.') if '@INPUT@' in i or '@INPUT0@' in i: m = 'Output cannot contain @INPUT@ or @INPUT0@, did you ' \ 'mean @PLAINNAME@ or @BASENAME@?' @@ -2110,9 +2445,14 @@ "there is more than one input (we can't know which to use)" raise InvalidArguments(m) self.outputs = substitute_values(self.outputs, values) + if not self.name: + self.name = self.outputs[0] self.capture = kwargs.get('capture', False) if self.capture and len(self.outputs) != 1: raise InvalidArguments('Capturing can only output to a single file.') + self.feed = kwargs.get('feed', False) + if self.feed and len(self.sources) != 1: + raise InvalidArguments('Feeding can only input from a single file.') self.console = kwargs.get('console', False) if not isinstance(self.console, bool): raise InvalidArguments('"console" kwarg only accepts booleans') @@ -2120,7 +2460,7 @@ raise InvalidArguments("Can't both capture output and output to console") if 'command' not in kwargs: raise InvalidArguments('Missing keyword argument "command".') - if 'depfile' in kwargs: + if kwargs.get('depfile') is not None: depfile = kwargs['depfile'] if not isinstance(depfile, str): raise InvalidArguments('Depfile must be a string.') @@ -2128,92 +2468,102 @@ raise InvalidArguments('Depfile must be a plain filename without a subdirectory.') self.depfile = depfile self.command = self.flatten_command(kwargs['command']) - if self.capture: - for c in self.command: - if isinstance(c, str) and '@OUTPUT@' in c: - raise InvalidArguments('@OUTPUT@ is not allowed when capturing output.') + for c in self.command: + if self.capture and isinstance(c, str) and '@OUTPUT@' in c: + raise InvalidArguments('@OUTPUT@ is not allowed when capturing output.') + if self.feed and isinstance(c, str) and '@INPUT@' in c: + raise InvalidArguments('@INPUT@ is not allowed when feeding input.') if 'install' in kwargs: self.install = kwargs['install'] if not isinstance(self.install, bool): raise InvalidArguments('"install" must be boolean.') if self.install: - if 'install_dir' not in kwargs: + if not kwargs.get('install_dir', False): raise InvalidArguments('"install_dir" must be specified ' 'when installing a target') - if isinstance(kwargs['install_dir'], list): - FeatureNew('multiple install_dir for custom_target', '0.40.0').use(self.subproject) - # If an item in this list is False, the output corresponding to - # the list index of that item will not be installed - self.install_dir = typeslistify(kwargs['install_dir'], (str, bool)) - self.install_mode = kwargs.get('install_mode', None) + if isinstance(kwargs['install_dir'], list): + FeatureNew.single_use('multiple install_dir for custom_target', '0.40.0', self.subproject) + # If an item in this list is False, the output corresponding to + # the list index of that item will not be installed + self.install_dir = typeslistify(kwargs['install_dir'], (str, bool)) + self.install_mode = kwargs.get('install_mode', None) + # If only one tag is provided, assume all outputs have the same tag. + # Otherwise, we must have as much tags as outputs. + install_tag: T.List[T.Union[str, bool, None]] = typeslistify(kwargs.get('install_tag', []), (str, bool, type(None))) + if not install_tag: + self.install_tag = [None] * len(self.outputs) + elif len(install_tag) == 1: + self.install_tag = install_tag * len(self.outputs) + elif install_tag and len(install_tag) != len(self.outputs): + m = f'Target {self.name!r} has {len(self.outputs)} outputs but {len(install_tag)} "install_tag"s were found.' + raise InvalidArguments(m) + else: + self.install_tag = install_tag else: self.install = False - self.install_dir = [None] + self.install_dir = [] self.install_mode = None - if 'build_always' in kwargs and 'build_always_stale' in kwargs: + self.install_tag = [] + if kwargs.get('build_always') is not None and kwargs.get('build_always_stale') is not None: raise InvalidArguments('build_always and build_always_stale are mutually exclusive. Combine build_by_default and build_always_stale.') - elif 'build_always' in kwargs: - mlog.deprecation('build_always is deprecated. Combine build_by_default and build_always_stale instead.') - if 'build_by_default' not in kwargs: + elif kwargs.get('build_always') is not None: + if kwargs.get('build_by_default') is not None: self.build_by_default = kwargs['build_always'] self.build_always_stale = kwargs['build_always'] - elif 'build_always_stale' in kwargs: + elif kwargs.get('build_always_stale') is not None: self.build_always_stale = kwargs['build_always_stale'] if not isinstance(self.build_always_stale, bool): raise InvalidArguments('Argument build_always_stale must be a boolean.') - extra_deps, depend_files = extract_as_list(kwargs, 'depends', 'depend_files', pop = False) + extra_deps, depend_files = (extract_as_list(kwargs, c, pop=False) for c in ['depends', 'depend_files']) for ed in extra_deps: - while hasattr(ed, 'held_object'): - ed = ed.held_object if not isinstance(ed, (CustomTarget, BuildTarget)): - raise InvalidArguments('Can only depend on toplevel targets: custom_target or build_target (executable or a library) got: %s(%s)' - % (type(ed), ed)) + raise InvalidArguments('Can only depend on toplevel targets: custom_target or build_target ' + f'(executable or a library) got: {type(ed)}({ed})') self.extra_depends.append(ed) for i in depend_files: if isinstance(i, (File, str)): self.depend_files.append(i) else: mlog.debug(i) - raise InvalidArguments('Unknown type {!r} in depend_files.'.format(type(i).__name__)) + raise InvalidArguments(f'Unknown type {type(i).__name__!r} in depend_files.') + self.env = kwargs.get('env') def get_dependencies(self): return self.dependencies - def should_install(self): + def should_install(self) -> bool: return self.install - def get_custom_install_dir(self): + def get_custom_install_dir(self) -> T.List[T.Union[str, bool]]: return self.install_dir - def get_custom_install_mode(self): + def get_custom_install_mode(self) -> T.Optional['FileMode']: return self.install_mode - def get_outputs(self): + def get_outputs(self) -> T.List[str]: return self.outputs - def get_filename(self): + def get_filename(self) -> str: return self.outputs[0] - def get_sources(self): + def get_sources(self) -> T.List[T.Union[str, File, 'CustomTarget', 'CustomTargetIndex', 'GeneratedList', 'ExtractedObjects']]: return self.sources - def get_generated_lists(self): - genlists = [] + def get_generated_lists(self) -> T.List[GeneratedList]: + genlists: T.List[GeneratedList] = [] for c in self.sources: - if hasattr(c, 'held_object'): - c = c.held_object if isinstance(c, GeneratedList): genlists.append(c) return genlists - def get_generated_sources(self): + def get_generated_sources(self) -> T.List[GeneratedList]: return self.get_generated_lists() def get_dep_outname(self, infilenames): if self.depfile is None: raise InvalidArguments('Tried to get depfile name for custom_target that does not have depfile defined.') - if len(infilenames): + if infilenames: plainname = os.path.basename(infilenames[0]) basename = os.path.splitext(plainname)[0] return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) @@ -2222,14 +2572,13 @@ raise InvalidArguments('Substitution in depfile for custom_target that does not have an input file.') return self.depfile - def is_linkable_target(self): + def is_linkable_target(self) -> bool: if len(self.outputs) != 1: return False suf = os.path.splitext(self.outputs[0])[-1] - if suf == '.a' or suf == '.dll' or suf == '.lib' or suf == '.so': - return True + return suf in {'.a', '.dll', '.lib', '.so', '.dylib'} - def get_link_deps_mapping(self, prefix, environment): + def get_link_deps_mapping(self, prefix: str, environment: environment.Environment) -> T.Mapping[str, str]: return {} def get_link_dep_subdirs(self): @@ -2238,10 +2587,21 @@ def get_all_link_deps(self): return [] + def is_internal(self) -> bool: + ''' + 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() + def type_suffix(self): return "@cus" - def __getitem__(self, index): + def __getitem__(self, index: int) -> 'CustomTargetIndex': return CustomTargetIndex(self, self.outputs[index]) def __setitem__(self, index, value): @@ -2250,38 +2610,50 @@ def __delitem__(self, index): raise NotImplementedError -class RunTarget(Target): - def __init__(self, name, command, args, dependencies, subdir, subproject): + def __iter__(self): + for i in self.outputs: + yield CustomTargetIndex(self, i) + + def __len__(self) -> int: + return len(self.outputs) + +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']], + subdir: str, + subproject: str, + env: T.Optional['EnvironmentVariables'] = None): self.typename = 'run' # These don't produce output artifacts super().__init__(name, subdir, subproject, False, MachineChoice.BUILD) - self.command = command - self.args = args self.dependencies = dependencies + self.depend_files = [] + self.command = self.flatten_command(command) + self.absolute_paths = False + self.env = env - def __repr__(self): + def __repr__(self) -> str: repr_str = "<{0} {1}: {2}>" - return repr_str.format(self.__class__.__name__, self.get_id(), self.command) + return repr_str.format(self.__class__.__name__, self.get_id(), self.command[0]) - def process_kwargs(self, kwargs): - return self.process_kwargs_base(kwargs) - - def get_dependencies(self): + def get_dependencies(self) -> T.List[T.Union[BuildTarget, 'CustomTarget']]: return self.dependencies - def get_generated_sources(self): + def get_generated_sources(self) -> T.List['GeneratedTypes']: return [] - def get_sources(self): + def get_sources(self) -> T.List[File]: return [] - def should_install(self): + def should_install(self) -> bool: return False - def get_filename(self): + def get_filename(self) -> str: return self.name - def get_outputs(self): + def get_outputs(self) -> T.List[str]: if isinstance(self.name, str): return [self.name] elif isinstance(self.name, list): @@ -2289,12 +2661,17 @@ else: raise RuntimeError('RunTarget: self.name is neither a list nor a string. This is a bug') - def type_suffix(self): + def type_suffix(self) -> str: return "@run" class AliasTarget(RunTarget): - def __init__(self, name, dependencies, subdir, subproject): - super().__init__(name, '', [], dependencies, subdir, subproject) + def __init__(self, name: str, dependencies: T.Sequence[T.Union[BuildTarget, 'CustomTarget']], + subdir: str, subproject: str): + super().__init__(name, [], dependencies, subdir, subproject) + + def __repr__(self): + repr_str = "<{0} {1}>" + return repr_str.format(self.__class__.__name__, self.get_id()) class Jar(BuildTarget): known_kwargs = known_jar_kwargs @@ -2304,10 +2681,10 @@ super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) for s in self.sources: if not s.endswith('.java'): - raise InvalidArguments('Jar source %s is not a java file.' % s) + raise InvalidArguments(f'Jar source {s} is not a java file.') for t in self.link_targets: if not isinstance(t, Jar): - raise InvalidArguments('Link target %s is not a jar target.' % t) + raise InvalidArguments(f'Link target {t} is not a jar target.') self.filename = self.name + '.jar' self.outputs = [self.filename] self.java_args = kwargs.get('java_args', []) @@ -2335,125 +2712,133 @@ return ['-cp', os.pathsep.join(cp_paths)] return [] -class CustomTargetIndex: +class CustomTargetIndex(HoldableObject): """A special opaque object returned by indexing a CustomTarget. This object - exists in meson, but acts as a proxy in the backends, making targets depend + exists in Meson, but acts as a proxy in the backends, making targets depend on the CustomTarget it's derived from, but only adding one source file to the sources. """ - def __init__(self, target, output): + def __init__(self, target: CustomTarget, output: str): self.typename = 'custom' self.target = target self.output = output self.for_machine = target.for_machine + @property + def name(self) -> str: + return f'{self.target.name}[{self.output}]' + def __repr__(self): return ''.format( self.target, self.target.get_outputs().index(self.output)) - def get_outputs(self): + def get_outputs(self) -> T.List[str]: return [self.output] - def get_subdir(self): + def get_subdir(self) -> str: return self.target.get_subdir() - def get_filename(self): + def get_filename(self) -> str: return self.output - def get_id(self): + def get_id(self) -> str: return self.target.get_id() def get_all_link_deps(self): return self.target.get_all_link_deps() - def get_link_deps_mapping(self, prefix, environment): + def get_link_deps_mapping(self, prefix: str, environment: environment.Environment) -> T.Mapping[str, str]: return self.target.get_link_deps_mapping(prefix, environment) def get_link_dep_subdirs(self): return self.target.get_link_dep_subdirs() - def is_linkable_target(self): + def is_linkable_target(self) -> bool: suf = os.path.splitext(self.output)[-1] - if suf == '.a' or suf == '.dll' or suf == '.lib' or suf == '.so': - return True + return suf in {'.a', '.dll', '.lib', '.so'} -class ConfigureFile: + def should_install(self) -> bool: + return self.target.should_install() - def __init__(self, subdir, sourcename, targetname, configuration_data): - self.subdir = subdir - self.sourcename = sourcename - self.targetname = targetname - self.configuration_data = configuration_data - - def __repr__(self): - repr_str = "<{0}: {1} -> {2}>" - src = os.path.join(self.subdir, self.sourcename) - dst = os.path.join(self.subdir, self.targetname) - return repr_str.format(self.__class__.__name__, src, dst) - - def get_configuration_data(self): - return self.configuration_data - - def get_subdir(self): - return self.subdir + def is_internal(self) -> bool: + ''' + 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 get_source_name(self): - return self.sourcename + def extract_all_objects_recurse(self) -> T.List[T.Union[str, 'ExtractedObjects']]: + return self.target.extract_all_objects_recurse() - def get_target_name(self): - return self.targetname + def get_custom_install_dir(self) -> T.List[T.Union[str, bool]]: + return self.target.get_custom_install_dir() -class ConfigurationData: - def __init__(self): +class ConfigurationData(HoldableObject): + def __init__(self) -> None: super().__init__() - self.values = {} + self.values: T.Dict[ + str, + T.Tuple[ + T.Union[str, int, bool], + T.Optional[str] + ] + ] = {} def __repr__(self): return repr(self.values) - def __contains__(self, value): + def __contains__(self, value: str) -> bool: return value in self.values - def get(self, name): + def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]: return self.values[name] # (val, desc) - def keys(self): + def keys(self) -> T.Iterator[str]: return self.values.keys() # A bit poorly named, but this represents plain data files to copy # during install. -class Data: - def __init__(self, sources, install_dir, install_mode=None, rename=None): +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.sources = listify(self.sources) - for s in self.sources: - assert(isinstance(s, File)) + self.install_tag = install_tag if rename is None: self.rename = [os.path.basename(f.fname) for f in self.sources] else: - self.rename = stringlistify(rename) - if len(self.rename) != len(self.sources): - raise MesonException('Size of rename argument is different from number of sources') + self.rename = rename + self.subproject = subproject + self.data_type = data_type -class RunScript(dict): - def __init__(self, script, args): - super().__init__() - assert(isinstance(script, list)) - assert(isinstance(args, list)) - self['exe'] = script - self['args'] = args +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. ' + 'The dir part should be in install_dir.') + self.name = name + self.install_dir = install_dir + self.subproject = subproject + self.install_tag = install_tag class TestSetup: - def __init__(self, exe_wrapper: T.Optional[T.List[str]], gdb: bool, - timeout_multiplier: int, env: EnvironmentVariables): + 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 def get_sources_string_names(sources, backend): ''' @@ -2462,8 +2847,6 @@ ''' names = [] for s in sources: - if hasattr(s, 'held_object'): - s = s.held_object if isinstance(s, str): names.append(s) elif isinstance(s, (BuildTarget, CustomTarget, CustomTargetIndex, GeneratedList)): @@ -2473,13 +2856,13 @@ elif isinstance(s, File): names.append(s.fname) else: - raise AssertionError('Unknown source type: {!r}'.format(s)) + raise AssertionError(f'Unknown source type: {s!r}') return names def load(build_dir: str) -> Build: filename = os.path.join(build_dir, 'meson-private', 'build.dat') - load_fail_msg = 'Build data file {!r} is corrupted. Try with a fresh build tree.'.format(filename) - nonexisting_fail_msg = 'No such build data file as "{!r}".'.format(filename) + load_fail_msg = f'Build data file {filename!r} is corrupted. Try with a fresh build tree.' + nonexisting_fail_msg = f'No such build data file as "{filename!r}".' try: with open(filename, 'rb') as f: obj = pickle.load(f) @@ -2489,14 +2872,14 @@ raise MesonException(load_fail_msg) except AttributeError: raise MesonException( - "Build data file {!r} references functions or classes that don't " + f"Build data file {filename!r} references functions or classes that don't " "exist. This probably means that it was generated with an old " "version of meson. Try running from the source directory " - "meson {} --wipe".format(filename, build_dir)) + f"meson {build_dir} --wipe") if not isinstance(obj, Build): raise MesonException(load_fail_msg) return obj -def save(obj, filename): +def save(obj: Build, filename: str) -> None: with open(filename, 'wb') as f: pickle.dump(obj, f) diff -Nru meson-0.53.2/mesonbuild/cmake/client.py meson-0.61.2/mesonbuild/cmake/client.py --- meson-0.53.2/mesonbuild/cmake/client.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/client.py 2021-04-27 06:49:45.000000000 +0000 @@ -16,15 +16,16 @@ # or an interpreter-based tool. from .common import CMakeException, CMakeConfiguration, CMakeBuildFile -from .executor import CMakeExecutor -from ..environment import Environment -from ..mesonlib import MachineChoice from .. import mlog from contextlib import contextmanager from subprocess import Popen, PIPE, TimeoutExpired +from pathlib import Path import typing as T import json -import os + +if T.TYPE_CHECKING: + from ..environment import Environment + from .executor import CMakeExecutor CMAKE_SERVER_BEGIN_STR = '[== "CMake Server" ==[' CMAKE_SERVER_END_STR = ']== "CMake Server" ==]' @@ -36,7 +37,7 @@ 'progress': ['cookie'], 'reply': ['cookie', 'inReplyTo'], 'signal': ['cookie', 'name'], -} +} # type: T.Dict[str, T.List[str]] CMAKE_REPLY_TYPES = { 'handshake': [], @@ -44,16 +45,16 @@ 'compute': [], 'cmakeInputs': ['buildFiles', 'cmakeRootDirectory', 'sourceDirectory'], 'codemodel': ['configurations'] -} +} # type: T.Dict[str, T.List[str]] # Base CMake server message classes class MessageBase: - def __init__(self, msg_type: str, cookie: str): + def __init__(self, msg_type: str, cookie: str) -> None: self.type = msg_type self.cookie = cookie - def to_dict(self) -> dict: + def to_dict(self) -> T.Dict[str, T.Union[str, T.List[str], T.Dict[str, int]]]: return {'type': self.type, 'cookie': self.cookie} def log(self) -> None: @@ -62,21 +63,21 @@ class RequestBase(MessageBase): cookie_counter = 0 - def __init__(self, msg_type: str): + def __init__(self, msg_type: str) -> None: super().__init__(msg_type, self.gen_cookie()) @staticmethod - def gen_cookie(): + def gen_cookie() -> str: RequestBase.cookie_counter += 1 - return 'meson_{}'.format(RequestBase.cookie_counter) + return f'meson_{RequestBase.cookie_counter}' class ReplyBase(MessageBase): - def __init__(self, cookie: str, in_reply_to: str): + def __init__(self, cookie: str, in_reply_to: str) -> None: super().__init__('reply', cookie) self.in_reply_to = in_reply_to class SignalBase(MessageBase): - def __init__(self, cookie: str, signal_name: str): + def __init__(self, cookie: str, signal_name: str) -> None: super().__init__('signal', cookie) self.signal_name = signal_name @@ -86,7 +87,7 @@ # Special Message classes class Error(MessageBase): - def __init__(self, cookie: str, message: str): + def __init__(self, cookie: str, message: str) -> None: super().__init__('error', cookie) self.message = message @@ -94,7 +95,7 @@ mlog.error(mlog.bold('CMake server error:'), mlog.red(self.message)) class Message(MessageBase): - def __init__(self, cookie: str, message: str): + def __init__(self, cookie: str, message: str) -> None: super().__init__('message', cookie) self.message = message @@ -103,19 +104,21 @@ pass class Progress(MessageBase): - def __init__(self, cookie: str): + def __init__(self, cookie: str) -> None: super().__init__('progress', cookie) def log(self) -> None: pass class MessageHello(MessageBase): - def __init__(self, supported_protocol_versions: T.List[dict]): + def __init__(self, supported_protocol_versions: T.List[T.Dict[str, int]]) -> None: super().__init__('hello', '') self.supported_protocol_versions = supported_protocol_versions def supports(self, major: int, minor: T.Optional[int] = None) -> bool: for i in self.supported_protocol_versions: + assert 'major' in i + assert 'minor' in i if major == i['major']: if minor is None or minor == i['minor']: return True @@ -124,7 +127,7 @@ # Request classes class RequestHandShake(RequestBase): - def __init__(self, src_dir: str, build_dir: str, generator: str, vers_major: int, vers_minor: T.Optional[int] = None): + def __init__(self, src_dir: Path, build_dir: Path, generator: str, vers_major: int, vers_minor: T.Optional[int] = None) -> None: super().__init__('handshake') self.src_dir = src_dir self.build_dir = build_dir @@ -132,19 +135,19 @@ self.vers_major = vers_major self.vers_minor = vers_minor - def to_dict(self) -> dict: + def to_dict(self) -> T.Dict[str, T.Union[str, T.List[str], T.Dict[str, int]]]: vers = {'major': self.vers_major} if self.vers_minor is not None: vers['minor'] = self.vers_minor # Old CMake versions (3.7) want '/' even on Windows - src_list = os.path.normpath(self.src_dir).split(os.sep) - bld_list = os.path.normpath(self.build_dir).split(os.sep) + self.src_dir = self.src_dir.resolve() + self.build_dir = self.build_dir.resolve() return { **super().to_dict(), - 'sourceDirectory': '/'.join(src_list), - 'buildDirectory': '/'.join(bld_list), + 'sourceDirectory': self.src_dir.as_posix(), + 'buildDirectory': self.build_dir.as_posix(), 'generator': self.generator, 'protocolVersion': vers } @@ -154,55 +157,55 @@ super().__init__('configure') self.args = args - def to_dict(self) -> dict: + def to_dict(self) -> T.Dict[str, T.Union[str, T.List[str], T.Dict[str, int]]]: res = super().to_dict() if self.args: res['cacheArguments'] = self.args return res class RequestCompute(RequestBase): - def __init__(self): + def __init__(self) -> None: super().__init__('compute') class RequestCMakeInputs(RequestBase): - def __init__(self): + def __init__(self) -> None: super().__init__('cmakeInputs') class RequestCodeModel(RequestBase): - def __init__(self): + def __init__(self) -> None: super().__init__('codemodel') # Reply classes class ReplyHandShake(ReplyBase): - def __init__(self, cookie: str): + def __init__(self, cookie: str) -> None: super().__init__(cookie, 'handshake') class ReplyConfigure(ReplyBase): - def __init__(self, cookie: str): + def __init__(self, cookie: str) -> None: super().__init__(cookie, 'configure') class ReplyCompute(ReplyBase): - def __init__(self, cookie: str): + def __init__(self, cookie: str) -> None: super().__init__(cookie, 'compute') class ReplyCMakeInputs(ReplyBase): - def __init__(self, cookie: str, cmake_root: str, src_dir: str, build_files: T.List[CMakeBuildFile]): + def __init__(self, cookie: str, cmake_root: Path, src_dir: Path, build_files: T.List[CMakeBuildFile]) -> None: super().__init__(cookie, 'cmakeInputs') self.cmake_root = cmake_root self.src_dir = src_dir self.build_files = build_files def log(self) -> None: - mlog.log('CMake root: ', mlog.bold(self.cmake_root)) - mlog.log('Source dir: ', mlog.bold(self.src_dir)) + mlog.log('CMake root: ', mlog.bold(self.cmake_root.as_posix())) + mlog.log('Source dir: ', mlog.bold(self.src_dir.as_posix())) mlog.log('Build files:', mlog.bold(str(len(self.build_files)))) with mlog.nested(): for i in self.build_files: mlog.log(str(i)) class ReplyCodeModel(ReplyBase): - def __init__(self, data: dict): + def __init__(self, data: T.Dict[str, T.Any]) -> None: super().__init__(data['cookie'], 'codemodel') self.configs = [] for i in data['configurations']: @@ -211,16 +214,16 @@ def log(self) -> None: mlog.log('CMake code mode:') for idx, i in enumerate(self.configs): - mlog.log('Configuration {}:'.format(idx)) + mlog.log(f'Configuration {idx}:') with mlog.nested(): i.log() # Main client class class CMakeClient: - def __init__(self, env: Environment): + def __init__(self, env: 'Environment') -> None: self.env = env - self.proc = None + self.proc = None # type: T.Optional[Popen] self.type_map = { 'error': lambda data: Error(data['cookie'], data['errorMessage']), 'hello': lambda data: MessageHello(data['supportedProtocolVersions']), @@ -228,7 +231,7 @@ 'progress': lambda data: Progress(data['cookie']), 'reply': self.resolve_type_reply, 'signal': lambda data: SignalBase(data['cookie'], data['name']) - } + } # type: T.Dict[str, T.Callable[[T.Dict[str, T.Any]], MessageBase]] self.reply_map = { 'handshake': lambda data: ReplyHandShake(data['cookie']), @@ -236,10 +239,10 @@ 'compute': lambda data: ReplyCompute(data['cookie']), 'cmakeInputs': self.resolve_reply_cmakeInputs, 'codemodel': lambda data: ReplyCodeModel(data), - } + } # type: T.Dict[str, T.Callable[[T.Dict[str, T.Any]], ReplyBase]] - def readMessageRaw(self) -> dict: - assert(self.proc is not None) + def readMessageRaw(self) -> T.Dict[str, T.Any]: + assert self.proc is not None rawData = [] begin = False while self.proc.poll() is None: @@ -257,7 +260,11 @@ begin = True # Begin of the message if rawData: - return json.loads('\n'.join(rawData)) + res = json.loads('\n'.join(rawData)) + assert isinstance(res, dict) + for i in res.keys(): + assert isinstance(i, str) + return res raise CMakeException('Failed to read data from the CMake server') def readMessage(self) -> MessageBase: @@ -267,10 +274,10 @@ msg_type = raw_data['type'] func = self.type_map.get(msg_type, None) if not func: - raise CMakeException('Recieved unknown message type "{}"'.format(msg_type)) + raise CMakeException(f'Recieved unknown message type "{msg_type}"') for i in CMAKE_MESSAGE_TYPES[msg_type]: if i not in raw_data: - raise CMakeException('Key "{}" is missing from CMake server message type {}'.format(i, msg_type)) + raise CMakeException(f'Key "{i}" is missing from CMake server message type {msg_type}') return func(raw_data) def writeMessage(self, msg: MessageBase) -> None: @@ -287,7 +294,7 @@ reply.log() - def query_checked(self, request: RequestBase, message: str) -> ReplyBase: + def query_checked(self, request: RequestBase, message: str) -> MessageBase: reply = self.query(request) h = mlog.green('SUCCEEDED') if reply.type == 'reply' else mlog.red('FAILED') mlog.log(message + ':', h) @@ -296,7 +303,7 @@ raise CMakeException('CMake server query failed') return reply - def do_handshake(self, src_dir: str, build_dir: str, generator: str, vers_major: int, vers_minor: T.Optional[int] = None) -> None: + def do_handshake(self, src_dir: Path, build_dir: Path, generator: str, vers_major: int, vers_minor: T.Optional[int] = None) -> None: # CMake prints the hello message on startup msg = self.readMessage() if not isinstance(msg, MessageHello): @@ -305,38 +312,35 @@ request = RequestHandShake(src_dir, build_dir, generator, vers_major, vers_minor) self.query_checked(request, 'CMake server handshake') - def resolve_type_reply(self, data: dict) -> ReplyBase: + def resolve_type_reply(self, data: T.Dict[str, T.Any]) -> ReplyBase: reply_type = data['inReplyTo'] func = self.reply_map.get(reply_type, None) if not func: - raise CMakeException('Recieved unknown reply type "{}"'.format(reply_type)) + raise CMakeException(f'Recieved unknown reply type "{reply_type}"') for i in ['cookie'] + CMAKE_REPLY_TYPES[reply_type]: if i not in data: - raise CMakeException('Key "{}" is missing from CMake server message type {}'.format(i, type)) + raise CMakeException(f'Key "{i}" is missing from CMake server message type {type}') return func(data) - def resolve_reply_cmakeInputs(self, data: dict) -> ReplyCMakeInputs: + def resolve_reply_cmakeInputs(self, data: T.Dict[str, T.Any]) -> ReplyCMakeInputs: files = [] for i in data['buildFiles']: for j in i['sources']: - files += [CMakeBuildFile(j, i['isCMake'], i['isTemporary'])] - return ReplyCMakeInputs(data['cookie'], data['cmakeRootDirectory'], data['sourceDirectory'], files) + files += [CMakeBuildFile(Path(j), i['isCMake'], i['isTemporary'])] + return ReplyCMakeInputs(data['cookie'], Path(data['cmakeRootDirectory']), Path(data['sourceDirectory']), files) @contextmanager - def connect(self): - self.startup() + def connect(self, cmake_exe: 'CMakeExecutor') -> T.Generator[None, None, None]: + self.startup(cmake_exe) try: yield finally: self.shutdown() - def startup(self) -> None: + def startup(self, cmake_exe: 'CMakeExecutor') -> None: if self.proc is not None: raise CMakeException('The CMake server was already started') - for_machine = MachineChoice.HOST # TODO make parameter - cmake_exe = CMakeExecutor(self.env, '>=3.7', for_machine) - if not cmake_exe.found(): - raise CMakeException('Unable to find CMake') + assert cmake_exe.found() mlog.debug('Starting CMake server with CMake', mlog.bold(' '.join(cmake_exe.get_command())), 'version', mlog.cyan(cmake_exe.version())) self.proc = Popen(cmake_exe.get_command() + ['-E', 'server', '--experimental', '--debug'], stdin=PIPE, stdout=PIPE) diff -Nru meson-0.53.2/mesonbuild/cmake/common.py meson-0.61.2/mesonbuild/cmake/common.py --- meson-0.53.2/mesonbuild/cmake/common.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/common.py 2021-12-26 16:24:25.000000000 +0000 @@ -15,21 +15,75 @@ # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. -from ..mesonlib import MesonException +from ..mesonlib import MesonException, OptionKey from .. import mlog +from pathlib import Path import typing as T +if T.TYPE_CHECKING: + from ..environment import Environment + +language_map = { + 'c': 'C', + 'cpp': 'CXX', + 'cuda': 'CUDA', + 'objc': 'OBJC', + 'objcpp': 'OBJCXX', + 'cs': 'CSharp', + 'java': 'Java', + 'fortran': 'Fortran', + 'swift': 'Swift', +} + +backend_generator_map = { + 'ninja': 'Ninja', + 'xcode': 'Xcode', + 'vs2010': 'Visual Studio 10 2010', + 'vs2012': 'Visual Studio 11 2012', + 'vs2013': 'Visual Studio 12 2013', + 'vs2015': 'Visual Studio 14 2015', + 'vs2017': 'Visual Studio 15 2017', + 'vs2019': 'Visual Studio 16 2019', + 'vs2022': 'Visual Studio 17 2022', +} + +blacklist_cmake_defs = [ + 'CMAKE_TOOLCHAIN_FILE', + 'CMAKE_PROJECT_INCLUDE', + 'MESON_PRELOAD_FILE', + 'MESON_PS_CMAKE_CURRENT_BINARY_DIR', + 'MESON_PS_CMAKE_CURRENT_SOURCE_DIR', + 'MESON_PS_DELAYED_CALLS', + 'MESON_PS_LOADED', + 'MESON_FIND_ROOT_PATH', + 'MESON_CMAKE_SYSROOT', + 'MESON_PATHS_LIST', + 'MESON_CMAKE_ROOT', +] + +def cmake_is_debug(env: 'Environment') -> bool: + if OptionKey('b_vscrt') in env.coredata.options: + is_debug = env.coredata.get_option(OptionKey('buildtype')) == 'debug' + if env.coredata.options[OptionKey('b_vscrt')].value in {'mdd', 'mtd'}: + is_debug = True + return is_debug + else: + # Don't directly assign to is_debug to make mypy happy + debug_opt = env.coredata.get_option(OptionKey('debug')) + assert isinstance(debug_opt, bool) + return debug_opt + class CMakeException(MesonException): pass class CMakeBuildFile: - def __init__(self, file: str, is_cmake: bool, is_temp: bool): + def __init__(self, file: Path, is_cmake: bool, is_temp: bool) -> None: self.file = file self.is_cmake = is_cmake self.is_temp = is_temp - def __repr__(self): - return '<{}: {}; cmake={}; temp={}>'.format(self.__class__.__name__, self.file, self.is_cmake, self.is_temp) + def __repr__(self) -> str: + return f'<{self.__class__.__name__}: {self.file}; cmake={self.is_cmake}; temp={self.is_temp}>' def _flags_to_list(raw: str) -> T.List[str]: # Convert a raw commandline string into a list of strings @@ -60,65 +114,118 @@ res = list(filter(lambda x: len(x) > 0, res)) return res +def cmake_get_generator_args(env: 'Environment') -> T.List[str]: + backend_name = env.coredata.get_option(OptionKey('backend')) + assert isinstance(backend_name, str) + assert backend_name in backend_generator_map + return ['-G', backend_generator_map[backend_name]] + +def cmake_defines_to_args(raw: T.Any, permissive: bool = False) -> T.List[str]: + res = [] # type: T.List[str] + if not isinstance(raw, list): + raw = [raw] + + for i in raw: + if not isinstance(i, dict): + raise MesonException('Invalid CMake defines. Expected a dict, but got a {}'.format(type(i).__name__)) + for key, val in i.items(): + assert isinstance(key, str) + if key in blacklist_cmake_defs: + mlog.warning('Setting', mlog.bold(key), 'is not supported. See the meson docs for cross compilation support:') + mlog.warning(' - URL: https://mesonbuild.com/CMake-module.html#cross-compilation') + mlog.warning(' --> Ignoring this option') + continue + if isinstance(val, (str, int, float)): + res += [f'-D{key}={val}'] + elif isinstance(val, bool): + val_str = 'ON' if val else 'OFF' + res += [f'-D{key}={val_str}'] + else: + raise MesonException('Type "{}" of "{}" is not supported as for a CMake define value'.format(type(val).__name__, key)) + + return res + +# TODO: this functuin will become obsolete once the `cmake_args` kwarg is dropped +def check_cmake_args(args: T.List[str]) -> T.List[str]: + res = [] # type: T.List[str] + dis = ['-D' + x for x in blacklist_cmake_defs] + assert dis # Ensure that dis is not empty. + for i in args: + if any([i.startswith(x) for x in dis]): + mlog.warning('Setting', mlog.bold(i), 'is not supported. See the meson docs for cross compilation support:') + mlog.warning(' - URL: https://mesonbuild.com/CMake-module.html#cross-compilation') + mlog.warning(' --> Ignoring this option') + continue + res += [i] + return res + +class CMakeInclude: + def __init__(self, path: Path, isSystem: bool = False): + self.path = path + self.isSystem = isSystem + + def __repr__(self) -> str: + return f'' + class CMakeFileGroup: - def __init__(self, data: dict): - self.defines = data.get('defines', '') - self.flags = _flags_to_list(data.get('compileFlags', '')) - self.includes = data.get('includePath', []) - self.is_generated = data.get('isGenerated', False) - self.language = data.get('language', 'C') - self.sources = data.get('sources', []) + def __init__(self, data: T.Dict[str, T.Any]) -> None: + self.defines = data.get('defines', '') # type: str + self.flags = _flags_to_list(data.get('compileFlags', '')) # type: T.List[str] + self.is_generated = data.get('isGenerated', False) # type: bool + self.language = data.get('language', 'C') # type: str + self.sources = [Path(x) for x in data.get('sources', [])] # type: T.List[Path] # Fix the include directories - tmp = [] - for i in self.includes: + self.includes = [] # type: T.List[CMakeInclude] + for i in data.get('includePath', []): if isinstance(i, dict) and 'path' in i: - i['isSystem'] = i.get('isSystem', False) - tmp += [i] + isSystem = i.get('isSystem', False) + assert isinstance(isSystem, bool) + assert isinstance(i['path'], str) + self.includes += [CMakeInclude(Path(i['path']), isSystem)] elif isinstance(i, str): - tmp += [{'path': i, 'isSystem': False}] - self.includes = tmp + self.includes += [CMakeInclude(Path(i))] def log(self) -> None: mlog.log('flags =', mlog.bold(', '.join(self.flags))) mlog.log('defines =', mlog.bold(', '.join(self.defines))) - mlog.log('includes =', mlog.bold(', '.join(self.includes))) + mlog.log('includes =', mlog.bold(', '.join([str(x) for x in self.includes]))) mlog.log('is_generated =', mlog.bold('true' if self.is_generated else 'false')) mlog.log('language =', mlog.bold(self.language)) mlog.log('sources:') for i in self.sources: with mlog.nested(): - mlog.log(i) + mlog.log(i.as_posix()) class CMakeTarget: - def __init__(self, data: dict): - self.artifacts = data.get('artifacts', []) - self.src_dir = data.get('sourceDirectory', '') - self.build_dir = data.get('buildDirectory', '') - self.name = data.get('name', '') - self.full_name = data.get('fullName', '') - self.install = data.get('hasInstallRule', False) - self.install_paths = list(set(data.get('installPaths', []))) - self.link_lang = data.get('linkerLanguage', '') - self.link_libraries = _flags_to_list(data.get('linkLibraries', '')) - self.link_flags = _flags_to_list(data.get('linkFlags', '')) - self.link_lang_flags = _flags_to_list(data.get('linkLanguageFlags', '')) - # self.link_path = data.get('linkPath', '') - self.type = data.get('type', 'EXECUTABLE') - # self.is_generator_provided = data.get('isGeneratorProvided', False) - self.files = [] + def __init__(self, data: T.Dict[str, T.Any]) -> None: + self.artifacts = [Path(x) for x in data.get('artifacts', [])] # type: T.List[Path] + self.src_dir = Path(data.get('sourceDirectory', '')) # type: Path + self.build_dir = Path(data.get('buildDirectory', '')) # type: Path + self.name = data.get('name', '') # type: str + self.full_name = data.get('fullName', '') # type: str + self.install = data.get('hasInstallRule', False) # type: bool + self.install_paths = [Path(x) for x in set(data.get('installPaths', []))] # type: T.List[Path] + self.link_lang = data.get('linkerLanguage', '') # type: str + self.link_libraries = _flags_to_list(data.get('linkLibraries', '')) # type: T.List[str] + self.link_flags = _flags_to_list(data.get('linkFlags', '')) # type: T.List[str] + self.link_lang_flags = _flags_to_list(data.get('linkLanguageFlags', '')) # type: T.List[str] + # self.link_path = Path(data.get('linkPath', '')) # type: Path + self.type = data.get('type', 'EXECUTABLE') # type: str + # self.is_generator_provided = data.get('isGeneratorProvided', False) # type: bool + self.files = [] # type: T.List[CMakeFileGroup] for i in data.get('fileGroups', []): self.files += [CMakeFileGroup(i)] def log(self) -> None: - mlog.log('artifacts =', mlog.bold(', '.join(self.artifacts))) - mlog.log('src_dir =', mlog.bold(self.src_dir)) - mlog.log('build_dir =', mlog.bold(self.build_dir)) + mlog.log('artifacts =', mlog.bold(', '.join([x.as_posix() for x in self.artifacts]))) + mlog.log('src_dir =', mlog.bold(self.src_dir.as_posix())) + mlog.log('build_dir =', mlog.bold(self.build_dir.as_posix())) mlog.log('name =', mlog.bold(self.name)) mlog.log('full_name =', mlog.bold(self.full_name)) mlog.log('install =', mlog.bold('true' if self.install else 'false')) - mlog.log('install_paths =', mlog.bold(', '.join(self.install_paths))) + mlog.log('install_paths =', mlog.bold(', '.join([x.as_posix() for x in self.install_paths]))) mlog.log('link_lang =', mlog.bold(self.link_lang)) mlog.log('link_libraries =', mlog.bold(', '.join(self.link_libraries))) mlog.log('link_flags =', mlog.bold(', '.join(self.link_flags))) @@ -127,39 +234,114 @@ mlog.log('type =', mlog.bold(self.type)) # mlog.log('is_generator_provided =', mlog.bold('true' if self.is_generator_provided else 'false')) for idx, i in enumerate(self.files): - mlog.log('Files {}:'.format(idx)) + mlog.log(f'Files {idx}:') with mlog.nested(): i.log() class CMakeProject: - def __init__(self, data: dict): - self.src_dir = data.get('sourceDirectory', '') - self.build_dir = data.get('buildDirectory', '') - self.name = data.get('name', '') - self.targets = [] + def __init__(self, data: T.Dict[str, T.Any]) -> None: + self.src_dir = Path(data.get('sourceDirectory', '')) # type: Path + self.build_dir = Path(data.get('buildDirectory', '')) # type: Path + self.name = data.get('name', '') # type: str + self.targets = [] # type: T.List[CMakeTarget] for i in data.get('targets', []): self.targets += [CMakeTarget(i)] def log(self) -> None: - mlog.log('src_dir =', mlog.bold(self.src_dir)) - mlog.log('build_dir =', mlog.bold(self.build_dir)) + mlog.log('src_dir =', mlog.bold(self.src_dir.as_posix())) + mlog.log('build_dir =', mlog.bold(self.build_dir.as_posix())) mlog.log('name =', mlog.bold(self.name)) for idx, i in enumerate(self.targets): - mlog.log('Target {}:'.format(idx)) + mlog.log(f'Target {idx}:') with mlog.nested(): i.log() class CMakeConfiguration: - def __init__(self, data: dict): - self.name = data.get('name', '') - self.projects = [] + def __init__(self, data: T.Dict[str, T.Any]) -> None: + self.name = data.get('name', '') # type: str + self.projects = [] # type: T.List[CMakeProject] for i in data.get('projects', []): self.projects += [CMakeProject(i)] def log(self) -> None: mlog.log('name =', mlog.bold(self.name)) for idx, i in enumerate(self.projects): - mlog.log('Project {}:'.format(idx)) + mlog.log(f'Project {idx}:') with mlog.nested(): i.log() + +class SingleTargetOptions: + def __init__(self) -> None: + self.opts = {} # type: T.Dict[str, str] + self.lang_args = {} # type: T.Dict[str, T.List[str]] + self.link_args = [] # type: T.List[str] + self.install = 'preserve' + + def set_opt(self, opt: str, val: str) -> None: + self.opts[opt] = val + + def append_args(self, lang: str, args: T.List[str]) -> None: + if lang not in self.lang_args: + self.lang_args[lang] = [] + self.lang_args[lang] += args + + def append_link_args(self, args: T.List[str]) -> None: + self.link_args += args + + def set_install(self, install: bool) -> None: + self.install = 'true' if install else 'false' + + def get_override_options(self, initial: T.List[str]) -> T.List[str]: + res = [] # type: T.List[str] + for i in initial: + opt = i[:i.find('=')] + if opt not in self.opts: + res += [i] + res += [f'{k}={v}' for k, v in self.opts.items()] + return res + + def get_compile_args(self, lang: str, initial: T.List[str]) -> T.List[str]: + if lang in self.lang_args: + return initial + self.lang_args[lang] + return initial + + def get_link_args(self, initial: T.List[str]) -> T.List[str]: + return initial + self.link_args + + def get_install(self, initial: bool) -> bool: + return {'preserve': initial, 'true': True, 'false': False}[self.install] + +class TargetOptions: + def __init__(self) -> None: + self.global_options = SingleTargetOptions() + self.target_options = {} # type: T.Dict[str, SingleTargetOptions] + + def __getitem__(self, tgt: str) -> SingleTargetOptions: + if tgt not in self.target_options: + self.target_options[tgt] = SingleTargetOptions() + return self.target_options[tgt] + + def get_override_options(self, tgt: str, initial: T.List[str]) -> T.List[str]: + initial = self.global_options.get_override_options(initial) + if tgt in self.target_options: + initial = self.target_options[tgt].get_override_options(initial) + return initial + + def get_compile_args(self, tgt: str, lang: str, initial: T.List[str]) -> T.List[str]: + initial = self.global_options.get_compile_args(lang, initial) + if tgt in self.target_options: + initial = self.target_options[tgt].get_compile_args(lang, initial) + return initial + + def get_link_args(self, tgt: str, initial: T.List[str]) -> T.List[str]: + initial = self.global_options.get_link_args(initial) + if tgt in self.target_options: + initial = self.target_options[tgt].get_link_args(initial) + return initial + + def get_install(self, tgt: str, initial: bool) -> bool: + initial = self.global_options.get_install(initial) + if tgt in self.target_options: + initial = self.target_options[tgt].get_install(initial) + return initial diff -Nru meson-0.53.2/mesonbuild/cmake/data/preload.cmake meson-0.61.2/mesonbuild/cmake/data/preload.cmake --- meson-0.53.2/mesonbuild/cmake/data/preload.cmake 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/data/preload.cmake 2021-04-01 21:13:00.000000000 +0000 @@ -4,6 +4,9 @@ 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() @@ -11,6 +14,11 @@ 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}") @@ -31,5 +39,44 @@ _add_custom_target(${ARGV}) endmacro() -set(MESON_PS_DELAYED_CALLS add_custom_command;add_custom_target) +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) diff -Nru meson-0.53.2/mesonbuild/cmake/data/run_ctgt.py meson-0.61.2/mesonbuild/cmake/data/run_ctgt.py --- meson-0.53.2/mesonbuild/cmake/data/run_ctgt.py 2019-12-04 18:45:59.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/data/run_ctgt.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import subprocess -import shutil -import os -import sys - -commands = [[]] -SEPARATOR = ';;;' - -# Generate CMD parameters -parser = argparse.ArgumentParser(description='Wrapper for add_custom_command') -parser.add_argument('-d', '--directory', type=str, metavar='D', required=True, help='Working directory to cwd to') -parser.add_argument('-o', '--outputs', nargs='+', metavar='O', required=True, help='Expected output files') -parser.add_argument('-O', '--original-outputs', nargs='*', metavar='O', default=[], help='Output files expected by CMake') -parser.add_argument('commands', nargs=argparse.REMAINDER, help='A "{}" seperated list of commands'.format(SEPARATOR)) - -# Parse -args = parser.parse_args() - -dummy_target = None -if len(args.outputs) == 1 and len(args.original_outputs) == 0: - dummy_target = args.outputs[0] -elif len(args.outputs) != len(args.original_outputs): - print('Length of output list and original output list differ') - sys.exit(1) - -for i in args.commands: - if i == SEPARATOR: - commands += [[]] - continue - - i = i.replace('"', '') # Remove lefover quotes - commands[-1] += [i] - -# Execute -for i in commands: - # Skip empty lists - if not i: - continue - - try: - os.makedirs(args.directory, exist_ok=True) - subprocess.run(i, cwd=args.directory, check=True) - except subprocess.CalledProcessError: - exit(1) - -if dummy_target: - with open(dummy_target, 'a'): - os.utime(dummy_target, None) - exit(0) - -# Copy outputs -zipped_outputs = zip(args.outputs, args.original_outputs) -for expected, generated in zipped_outputs: - do_copy = False - if not os.path.exists(expected): - if not os.path.exists(generated): - print('Unable to find generated file. This can cause the build to fail:') - print(generated) - do_copy = False - else: - do_copy = True - elif os.path.exists(generated): - if os.path.getmtime(generated) > os.path.getmtime(expected): - do_copy = True - - if do_copy: - if os.path.exists(expected): - os.remove(expected) - shutil.copyfile(generated, expected) diff -Nru meson-0.53.2/mesonbuild/cmake/executor.py meson-0.61.2/mesonbuild/cmake/executor.py --- meson-0.53.2/mesonbuild/cmake/executor.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/executor.py 2021-11-02 19:58:07.000000000 +0000 @@ -15,37 +15,42 @@ # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. -import subprocess +import subprocess as S from pathlib import Path +from threading import Thread import typing as T import re import os -import shutil -import ctypes -import textwrap - -from .. import mlog, mesonlib -from ..mesonlib import PerMachine, Popen_safe, version_compare, MachineChoice -from ..environment import Environment + +from .. import mlog +from ..mesonlib import PerMachine, Popen_safe, version_compare, MachineChoice, is_windows, OptionKey +from ..programs import find_external_program, NonExistingExternalProgram if T.TYPE_CHECKING: - from ..dependencies.base import ExternalProgram + from ..environment import Environment + from ..programs import ExternalProgram +TYPE_result = T.Tuple[int, T.Optional[str], T.Optional[str]] +TYPE_cache_key = T.Tuple[str, T.Tuple[str, ...], str, T.FrozenSet[T.Tuple[str, str]]] class CMakeExecutor: # The class's copy of the CMake path. Avoids having to search for it # multiple times in the same Meson invocation. - class_cmakebin = PerMachine(None, None) - class_cmakevers = PerMachine(None, None) - class_cmake_cache = {} + class_cmakebin = PerMachine(None, None) # type: PerMachine[T.Optional[ExternalProgram]] + class_cmakevers = PerMachine(None, None) # type: PerMachine[T.Optional[str]] + class_cmake_cache = {} # type: T.Dict[T.Any, TYPE_result] - def __init__(self, environment: Environment, version: str, for_machine: MachineChoice, silent: bool = False): + def __init__(self, environment: 'Environment', version: str, for_machine: MachineChoice, silent: bool = False): self.min_version = version self.environment = environment self.for_machine = for_machine self.cmakebin, self.cmakevers = self.find_cmake_binary(self.environment, silent=silent) - if self.cmakebin is False: - self.cmakebin = None + self.always_capture_stderr = True + self.print_cmout = False + self.prefix_paths = [] # type: T.List[str] + self.extra_cmake_args = [] # type: T.List[str] + + if self.cmakebin is None: return if not version_compare(self.cmakevers, self.min_version): @@ -56,45 +61,31 @@ self.cmakebin = None return - def find_cmake_binary(self, environment: Environment, silent: bool = False) -> T.Tuple['ExternalProgram', str]: - from ..dependencies.base import ExternalProgram - - # Create an iterator of options - def search(): - # Lookup in cross or machine file. - potential_cmakepath = environment.binaries[self.for_machine].lookup_entry('cmake') - if potential_cmakepath is not None: - mlog.debug('CMake binary for %s specified from cross file, native file, or env var as %s.', self.for_machine, potential_cmakepath) - yield ExternalProgram.from_entry('cmake', potential_cmakepath) - # We never fallback if the user-specified option is no good, so - # stop returning options. - return - mlog.debug('CMake binary missing from cross or native file, or env var undefined.') - # Fallback on hard-coded defaults. - # TODO prefix this for the cross case instead of ignoring thing. - if environment.machines.matches_build_machine(self.for_machine): - for potential_cmakepath in environment.default_cmake: - mlog.debug('Trying a default CMake fallback at', potential_cmakepath) - yield ExternalProgram(potential_cmakepath, silent=True) + self.prefix_paths = self.environment.coredata.options[OptionKey('cmake_prefix_path', machine=self.for_machine)].value + if self.prefix_paths: + self.extra_cmake_args += ['-DCMAKE_PREFIX_PATH={}'.format(';'.join(self.prefix_paths))] + def find_cmake_binary(self, environment: 'Environment', silent: bool = False) -> T.Tuple[T.Optional['ExternalProgram'], T.Optional[str]]: # Only search for CMake the first time and store the result in the class # definition - if CMakeExecutor.class_cmakebin[self.for_machine] is False: - mlog.debug('CMake binary for %s is cached as not found' % self.for_machine) + if isinstance(CMakeExecutor.class_cmakebin[self.for_machine], NonExistingExternalProgram): + mlog.debug(f'CMake binary for {self.for_machine} is cached as not found') + return None, None elif CMakeExecutor.class_cmakebin[self.for_machine] is not None: - mlog.debug('CMake binary for %s is cached.' % self.for_machine) + mlog.debug(f'CMake binary for {self.for_machine} is cached.') else: assert CMakeExecutor.class_cmakebin[self.for_machine] is None - mlog.debug('CMake binary for %s is not cached' % self.for_machine) - for potential_cmakebin in search(): - mlog.debug('Trying CMake binary {} for machine {} at {}' - .format(potential_cmakebin.name, self.for_machine, potential_cmakebin.command)) + + mlog.debug(f'CMake binary for {self.for_machine} is not cached') + for potential_cmakebin in find_external_program( + environment, self.for_machine, 'cmake', 'CMake', + environment.default_cmake, allow_default_for_cross=False): version_if_ok = self.check_cmake(potential_cmakebin) if not version_if_ok: continue if not silent: mlog.log('Found CMake:', mlog.bold(potential_cmakebin.get_path()), - '(%s)' % version_if_ok) + f'({version_if_ok})') CMakeExecutor.class_cmakebin[self.for_machine] = potential_cmakebin CMakeExecutor.class_cmakevers[self.for_machine] = version_if_ok break @@ -103,14 +94,15 @@ mlog.log('Found CMake:', mlog.red('NO')) # Set to False instead of None to signify that we've already # searched for it and not found it - CMakeExecutor.class_cmakebin[self.for_machine] = False + CMakeExecutor.class_cmakebin[self.for_machine] = NonExistingExternalProgram() CMakeExecutor.class_cmakevers[self.for_machine] = None + return None, None return CMakeExecutor.class_cmakebin[self.for_machine], CMakeExecutor.class_cmakevers[self.for_machine] def check_cmake(self, cmakebin: 'ExternalProgram') -> T.Optional[str]: if not cmakebin.found(): - mlog.log('Did not find CMake {!r}'.format(cmakebin.name)) + mlog.log(f'Did not find CMake {cmakebin.name!r}') return None try: p, out = Popen_safe(cmakebin.get_command() + ['--version'])[0:2] @@ -124,159 +116,116 @@ return None except PermissionError: msg = 'Found CMake {!r} but didn\'t have permissions to run it.'.format(' '.join(cmakebin.get_command())) - if not mesonlib.is_windows(): + if not is_windows(): msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.' mlog.warning(msg) return None - cmvers = re.sub(r'\s*cmake version\s*', '', out.split('\n')[0]).strip() + cmvers = re.search(r'(cmake|cmake3)\s*version\s*([\d.]+)', out).group(2) return cmvers - def _cache_key(self, args: T.List[str], build_dir: str, env): - fenv = frozenset(env.items()) if env is not None else None + def set_exec_mode(self, print_cmout: T.Optional[bool] = None, always_capture_stderr: T.Optional[bool] = None) -> None: + if print_cmout is not None: + self.print_cmout = print_cmout + if always_capture_stderr is not None: + self.always_capture_stderr = always_capture_stderr + + def _cache_key(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_cache_key: + fenv = frozenset(env.items()) if env is not None else frozenset() targs = tuple(args) - return (self.cmakebin, targs, build_dir, fenv) + return (self.cmakebin.get_path(), targs, build_dir.as_posix(), fenv) - def _call_real(self, args: T.List[str], build_dir: str, env) -> T.Tuple[int, str, str]: - os.makedirs(build_dir, exist_ok=True) + def _call_cmout_stderr(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_result: cmd = self.cmakebin.get_command() + args - ret = subprocess.run(cmd, env=env, cwd=build_dir, close_fds=False, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=False) + proc = S.Popen(cmd, stdout=S.PIPE, stderr=S.PIPE, cwd=str(build_dir), env=env) # TODO [PYTHON_37]: drop Path conversion + + # stdout and stderr MUST be read at the same time to avoid pipe + # blocking issues. The easiest way to do this is with a separate + # thread for one of the pipes. + def print_stdout() -> None: + while True: + line = proc.stdout.readline() + if not line: + break + mlog.log(line.decode(errors='ignore').strip('\n')) + proc.stdout.close() + + t = Thread(target=print_stdout) + t.start() + + try: + # Read stderr line by line and log non trace lines + raw_trace = '' + tline_start_reg = re.compile(r'^\s*(.*\.(cmake|txt))\(([0-9]+)\):\s*(\w+)\(.*$') + inside_multiline_trace = False + while True: + line_raw = proc.stderr.readline() + if not line_raw: + break + line = line_raw.decode(errors='ignore') + if tline_start_reg.match(line): + raw_trace += line + inside_multiline_trace = not line.endswith(' )\n') + elif inside_multiline_trace: + raw_trace += line + else: + mlog.warning(line.strip('\n')) + + finally: + proc.stderr.close() + t.join() + proc.wait() + + return proc.returncode, None, raw_trace + + def _call_cmout(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_result: + cmd = self.cmakebin.get_command() + args + proc = S.Popen(cmd, stdout=S.PIPE, stderr=S.STDOUT, cwd=str(build_dir), env=env) # TODO [PYTHON_37]: drop Path conversion + while True: + line = proc.stdout.readline() + if not line: + break + mlog.log(line.decode(errors='ignore').strip('\n')) + proc.stdout.close() + proc.wait() + return proc.returncode, None, None + + def _call_quiet(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_result: + build_dir.mkdir(parents=True, exist_ok=True) + cmd = self.cmakebin.get_command() + args + ret = S.run(cmd, env=env, cwd=str(build_dir), close_fds=False, + stdout=S.PIPE, stderr=S.PIPE, universal_newlines=False) # TODO [PYTHON_37]: drop Path conversion rc = ret.returncode out = ret.stdout.decode(errors='ignore') err = ret.stderr.decode(errors='ignore') - call = ' '.join(cmd) - mlog.debug("Called `{}` in {} -> {}".format(call, build_dir, rc)) return rc, out, err - def call(self, args: T.List[str], build_dir: str, env=None, disable_cache: bool = False): + def _call_impl(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_result: + mlog.debug(f'Calling CMake ({self.cmakebin.get_command()}) in {build_dir} with:') + for i in args: + mlog.debug(f' - "{i}"') + if not self.print_cmout: + return self._call_quiet(args, build_dir, env) + else: + if self.always_capture_stderr: + return self._call_cmout_stderr(args, build_dir, env) + else: + return self._call_cmout(args, build_dir, env) + + def call(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]] = None, disable_cache: bool = False) -> TYPE_result: if env is None: - env = os.environ + env = os.environ.copy() + args = args + self.extra_cmake_args if disable_cache: - return self._call_real(args, build_dir, env) + return self._call_impl(args, build_dir, env) # First check if cached, if not call the real cmake function cache = CMakeExecutor.class_cmake_cache key = self._cache_key(args, build_dir, env) if key not in cache: - cache[key] = self._call_real(args, build_dir, env) + cache[key] = self._call_impl(args, build_dir, env) return cache[key] - def call_with_fake_build(self, args: T.List[str], build_dir: str, env=None): - # First check the cache - cache = CMakeExecutor.class_cmake_cache - key = self._cache_key(args, build_dir, env) - if key in cache: - return cache[key] - - os.makedirs(build_dir, exist_ok=True) - - # Try to set the correct compiler for C and C++ - # This step is required to make try_compile work inside CMake - fallback = os.path.realpath(__file__) # A file used as a fallback wehen everything else fails - compilers = self.environment.coredata.compilers[MachineChoice.BUILD] - - def make_abs(exe: str, lang: str) -> str: - if os.path.isabs(exe): - return exe - - p = shutil.which(exe) - if p is None: - mlog.debug('Failed to find a {} compiler for CMake. This might cause CMake to fail.'.format(lang)) - p = fallback - return p - - def choose_compiler(lang: str) -> T.Tuple[str, str]: - exe_list = [] - if lang in compilers: - exe_list = compilers[lang].get_exelist() - else: - try: - comp_obj = self.environment.compiler_from_language(lang, MachineChoice.BUILD) - if comp_obj is not None: - exe_list = comp_obj.get_exelist() - except Exception: - pass - - if len(exe_list) == 1: - return make_abs(exe_list[0], lang), '' - elif len(exe_list) == 2: - return make_abs(exe_list[1], lang), make_abs(exe_list[0], lang) - else: - mlog.debug('Failed to find a {} compiler for CMake. This might cause CMake to fail.'.format(lang)) - return fallback, '' - - c_comp, c_launcher = choose_compiler('c') - cxx_comp, cxx_launcher = choose_compiler('cpp') - fortran_comp, fortran_launcher = choose_compiler('fortran') - - # on Windows, choose_compiler returns path with \ as separator - replace by / before writing to CMAKE file - c_comp = c_comp.replace('\\', '/') - c_launcher = c_launcher.replace('\\', '/') - cxx_comp = cxx_comp.replace('\\', '/') - cxx_launcher = cxx_launcher.replace('\\', '/') - fortran_comp = fortran_comp.replace('\\', '/') - fortran_launcher = fortran_launcher.replace('\\', '/') - - # Reset the CMake cache - (Path(build_dir) / 'CMakeCache.txt').write_text('CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1\n') - - # Fake the compiler files - comp_dir = Path(build_dir) / 'CMakeFiles' / self.cmakevers - comp_dir.mkdir(parents=True, exist_ok=True) - - c_comp_file = comp_dir / 'CMakeCCompiler.cmake' - cxx_comp_file = comp_dir / 'CMakeCXXCompiler.cmake' - fortran_comp_file = comp_dir / 'CMakeFortranCompiler.cmake' - - if c_comp and not c_comp_file.is_file(): - c_comp_file.write_text(textwrap.dedent('''\ - # Fake CMake file to skip the boring and slow stuff - set(CMAKE_C_COMPILER "{}") # Should be a valid compiler for try_compile, etc. - set(CMAKE_C_COMPILER_LAUNCHER "{}") # The compiler launcher (if presentt) - set(CMAKE_C_COMPILER_ID "GNU") # Pretend we have found GCC - set(CMAKE_COMPILER_IS_GNUCC 1) - set(CMAKE_C_COMPILER_LOADED 1) - set(CMAKE_C_COMPILER_WORKS TRUE) - set(CMAKE_C_ABI_COMPILED TRUE) - set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) - set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) - set(CMAKE_SIZEOF_VOID_P "{}") - '''.format(c_comp, c_launcher, ctypes.sizeof(ctypes.c_voidp)))) - - if cxx_comp and not cxx_comp_file.is_file(): - cxx_comp_file.write_text(textwrap.dedent('''\ - # Fake CMake file to skip the boring and slow stuff - set(CMAKE_CXX_COMPILER "{}") # Should be a valid compiler for try_compile, etc. - set(CMAKE_CXX_COMPILER_LAUNCHER "{}") # The compiler launcher (if presentt) - set(CMAKE_CXX_COMPILER_ID "GNU") # Pretend we have found GCC - set(CMAKE_COMPILER_IS_GNUCXX 1) - set(CMAKE_CXX_COMPILER_LOADED 1) - set(CMAKE_CXX_COMPILER_WORKS TRUE) - set(CMAKE_CXX_ABI_COMPILED TRUE) - set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) - set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP) - set(CMAKE_SIZEOF_VOID_P "{}") - '''.format(cxx_comp, cxx_launcher, ctypes.sizeof(ctypes.c_voidp)))) - - if fortran_comp and not fortran_comp_file.is_file(): - fortran_comp_file.write_text(textwrap.dedent('''\ - # Fake CMake file to skip the boring and slow stuff - set(CMAKE_Fortran_COMPILER "{}") # Should be a valid compiler for try_compile, etc. - set(CMAKE_Fortran_COMPILER_LAUNCHER "{}") # The compiler launcher (if presentt) - set(CMAKE_Fortran_COMPILER_ID "GNU") # Pretend we have found GCC - set(CMAKE_COMPILER_IS_GNUG77 1) - set(CMAKE_Fortran_COMPILER_LOADED 1) - set(CMAKE_Fortran_COMPILER_WORKS TRUE) - set(CMAKE_Fortran_ABI_COMPILED TRUE) - set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) - set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95) - set(CMAKE_SIZEOF_VOID_P "{}") - '''.format(fortran_comp, fortran_launcher, ctypes.sizeof(ctypes.c_voidp)))) - - return self.call(args, build_dir, env) - def found(self) -> bool: return self.cmakebin is not None @@ -286,8 +235,11 @@ def executable_path(self) -> str: return self.cmakebin.get_path() - def get_command(self): + def get_command(self) -> T.List[str]: return self.cmakebin.get_command() + def get_cmake_prefix_paths(self) -> T.List[str]: + return self.prefix_paths + def machine_choice(self) -> MachineChoice: return self.for_machine diff -Nru meson-0.53.2/mesonbuild/cmake/fileapi.py meson-0.61.2/mesonbuild/cmake/fileapi.py --- meson-0.53.2/mesonbuild/cmake/fileapi.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/fileapi.py 2021-11-02 19:58:07.000000000 +0000 @@ -15,21 +15,21 @@ from .common import CMakeException, CMakeBuildFile, CMakeConfiguration import typing as T from .. import mlog -import os +from pathlib import Path import json import re STRIP_KEYS = ['cmake', 'reply', 'backtrace', 'backtraceGraph', 'version'] class CMakeFileAPI: - def __init__(self, build_dir: str): - self.build_dir = build_dir - self.api_base_dir = os.path.join(self.build_dir, '.cmake', 'api', 'v1') - self.request_dir = os.path.join(self.api_base_dir, 'query', 'client-meson') - self.reply_dir = os.path.join(self.api_base_dir, 'reply') - self.cmake_sources = [] - self.cmake_configurations = [] - self.kind_resolver_map = { + def __init__(self, build_dir: Path): + self.build_dir = build_dir + self.api_base_dir = self.build_dir / '.cmake' / 'api' / 'v1' + self.request_dir = self.api_base_dir / 'query' / 'client-meson' + self.reply_dir = self.api_base_dir / 'reply' + self.cmake_sources = [] # type: T.List[CMakeBuildFile] + self.cmake_configurations = [] # type: T.List[CMakeConfiguration] + self.kind_resolver_map = { 'codemodel': self._parse_codemodel, 'cmakeFiles': self._parse_cmakeFiles, } @@ -41,7 +41,7 @@ return self.cmake_configurations def setup_request(self) -> None: - os.makedirs(self.request_dir, exist_ok=True) + self.request_dir.mkdir(parents=True, exist_ok=True) query = { 'requests': [ @@ -50,18 +50,17 @@ ] } - with open(os.path.join(self.request_dir, 'query.json'), 'w') as fp: - json.dump(query, fp, indent=2) + query_file = self.request_dir / 'query.json' + query_file.write_text(json.dumps(query, indent=2), encoding='utf-8') def load_reply(self) -> None: - if not os.path.isdir(self.reply_dir): + if not self.reply_dir.is_dir(): raise CMakeException('No response from the CMake file API') - files = os.listdir(self.reply_dir) root = None reg_index = re.compile(r'^index-.*\.json$') - for i in files: - if reg_index.match(i): + for i in self.reply_dir.iterdir(): + if reg_index.match(i.name): root = i break @@ -74,22 +73,22 @@ index = self._strip_data(index) # Strip unused data (again for loaded files) # Debug output - debug_json = os.path.normpath(os.path.join(self.build_dir, '..', 'fileAPI.json')) - with open(debug_json, 'w') as fp: - json.dump(index, fp, indent=2) - mlog.cmd_ci_include(debug_json) + debug_json = self.build_dir / '..' / 'fileAPI.json' + debug_json = debug_json.resolve() + debug_json.write_text(json.dumps(index, indent=2), encoding='utf-8') + mlog.cmd_ci_include(debug_json.as_posix()) # parse the JSON for i in index['objects']: - assert(isinstance(i, dict)) - assert('kind' in i) - assert(i['kind'] in self.kind_resolver_map) + assert isinstance(i, dict) + assert 'kind' in i + assert i['kind'] in self.kind_resolver_map self.kind_resolver_map[i['kind']](i) - def _parse_codemodel(self, data: dict) -> None: - assert('configurations' in data) - assert('paths' in data) + def _parse_codemodel(self, data: T.Dict[str, T.Any]) -> None: + assert 'configurations' in data + assert 'paths' in data source_dir = data['paths']['source'] build_dir = data['paths']['build'] @@ -100,17 +99,17 @@ # resolved and the resulting data structure is identical # to the CMake serve output. - def helper_parse_dir(dir_entry: dict) -> T.Tuple[str, str]: - src_dir = dir_entry.get('source', '.') - bld_dir = dir_entry.get('build', '.') - src_dir = src_dir if os.path.isabs(src_dir) else os.path.join(source_dir, src_dir) - bld_dir = bld_dir if os.path.isabs(bld_dir) else os.path.join(source_dir, bld_dir) - src_dir = os.path.normpath(src_dir) - bld_dir = os.path.normpath(bld_dir) + def helper_parse_dir(dir_entry: T.Dict[str, T.Any]) -> T.Tuple[Path, Path]: + src_dir = Path(dir_entry.get('source', '.')) + bld_dir = Path(dir_entry.get('build', '.')) + src_dir = src_dir if src_dir.is_absolute() else source_dir / src_dir + bld_dir = bld_dir if bld_dir.is_absolute() else build_dir / bld_dir + src_dir = src_dir.resolve() + bld_dir = bld_dir.resolve() return src_dir, bld_dir - def parse_sources(comp_group: dict, tgt: dict) -> T.Tuple[T.List[str], T.List[str], T.List[int]]: + def parse_sources(comp_group: T.Dict[str, T.Any], tgt: T.Dict[str, T.Any]) -> T.Tuple[T.List[Path], T.List[Path], T.List[int]]: gen = [] src = [] idx = [] @@ -120,21 +119,21 @@ if i >= len(src_list_raw) or 'path' not in src_list_raw[i]: continue if src_list_raw[i].get('isGenerated', False): - gen += [src_list_raw[i]['path']] + gen += [Path(src_list_raw[i]['path'])] else: - src += [src_list_raw[i]['path']] + src += [Path(src_list_raw[i]['path'])] idx += [i] return src, gen, idx - def parse_target(tgt: dict) -> dict: + def parse_target(tgt: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]: src_dir, bld_dir = helper_parse_dir(cnf.get('paths', {})) # Parse install paths (if present) install_paths = [] if 'install' in tgt: - prefix = tgt['install']['prefix']['path'] - install_paths = [os.path.join(prefix, x['path']) for x in tgt['install']['destinations']] + prefix = Path(tgt['install']['prefix']['path']) + install_paths = [prefix / x['path'] for x in tgt['install']['destinations']] install_paths = list(set(install_paths)) # On the first look, it looks really nice that the CMake devs have @@ -160,7 +159,7 @@ # maybe we can make use of that in addition to the # implicit dependency detection tgt_data = { - 'artifacts': [x.get('path', '') for x in tgt.get('artifacts', [])], + 'artifacts': [Path(x.get('path', '')) for x in tgt.get('artifacts', [])], 'sourceDirectory': src_dir, 'buildDirectory': bld_dir, 'name': tgt.get('name', ''), @@ -230,7 +229,7 @@ }] return tgt_data - def parse_project(pro: dict) -> dict: + def parse_project(pro: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]: # Only look at the first directory specified in directoryIndexes # TODO Figure out what the other indexes are there for p_src_dir = source_dir @@ -268,15 +267,15 @@ self.cmake_configurations += [CMakeConfiguration(cnf_data)] - def _parse_cmakeFiles(self, data: dict) -> None: - assert('inputs' in data) - assert('paths' in data) + def _parse_cmakeFiles(self, data: T.Dict[str, T.Any]) -> None: + assert 'inputs' in data + assert 'paths' in data - src_dir = data['paths']['source'] + src_dir = Path(data['paths']['source']) for i in data['inputs']: - path = i['path'] - path = path if os.path.isabs(path) else os.path.join(src_dir, path) + path = Path(i['path']) + path = path if path.is_absolute() else src_dir / path self.cmake_sources += [CMakeBuildFile(path, i.get('isCMake', False), i.get('isGenerated', False))] def _strip_data(self, data: T.Any) -> T.Any: @@ -309,10 +308,13 @@ return data - def _reply_file_content(self, filename: str) -> dict: - real_path = os.path.join(self.reply_dir, filename) - if not os.path.exists(real_path): - raise CMakeException('File "{}" does not exist'.format(real_path)) - - with open(real_path, 'r') as fp: - return json.load(fp) + def _reply_file_content(self, filename: Path) -> T.Dict[str, T.Any]: + real_path = self.reply_dir / filename + if not real_path.exists(): + raise CMakeException(f'File "{real_path}" does not exist') + + data = json.loads(real_path.read_text(encoding='utf-8')) + assert isinstance(data, dict) + for i in data.keys(): + assert isinstance(i, str) + return data diff -Nru meson-0.53.2/mesonbuild/cmake/generator.py meson-0.61.2/mesonbuild/cmake/generator.py --- meson-0.53.2/mesonbuild/cmake/generator.py 2019-08-28 17:15:39.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/generator.py 2021-08-18 11:22:15.000000000 +0000 @@ -13,6 +13,7 @@ # limitations under the License. from .. import mesonlib +import typing as T def parse_generator_expressions(raw: str) -> str: '''Parse CMake generator expressions @@ -22,6 +23,10 @@ use cases. ''' + # Early abort if no generator expression present + if '$<' not in raw: + return raw + out = '' # type: str i = 0 # type: int @@ -73,7 +78,7 @@ 'ANGLE-R': lambda x: '>', 'COMMA': lambda x: ',', 'SEMICOLON': lambda x: ';', - } + } # type: T.Dict[str, T.Callable[[str], str]] # Recursively evaluate generator expressions def eval_generator_expressions() -> str: diff -Nru meson-0.53.2/mesonbuild/cmake/__init__.py meson-0.61.2/mesonbuild/cmake/__init__.py --- meson-0.53.2/mesonbuild/cmake/__init__.py 2020-01-23 21:41:11.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/__init__.py 2021-12-26 16:24:25.000000000 +0000 @@ -18,20 +18,33 @@ __all__ = [ 'CMakeClient', 'CMakeExecutor', + 'CMakeExecScope', 'CMakeException', 'CMakeFileAPI', 'CMakeInterpreter', 'CMakeTarget', + 'CMakeToolchain', 'CMakeTraceLine', 'CMakeTraceParser', + 'SingleTargetOptions', + 'TargetOptions', 'parse_generator_expressions', 'language_map', + 'backend_generator_map', + 'cmake_get_generator_args', + 'cmake_defines_to_args', + 'check_cmake_args', + 'cmake_is_debug', + 'resolve_cmake_trace_targets', + 'ResolvedTarget', ] -from .common import CMakeException +from .common import CMakeException, SingleTargetOptions, TargetOptions, cmake_defines_to_args, language_map, backend_generator_map, cmake_get_generator_args, check_cmake_args, cmake_is_debug from .client import CMakeClient from .executor import CMakeExecutor from .fileapi import CMakeFileAPI from .generator import parse_generator_expressions -from .interpreter import CMakeInterpreter, language_map +from .interpreter import CMakeInterpreter +from .toolchain import CMakeToolchain, CMakeExecScope from .traceparser import CMakeTarget, CMakeTraceLine, CMakeTraceParser +from .tracetargets import resolve_cmake_trace_targets, ResolvedTarget diff -Nru meson-0.53.2/mesonbuild/cmake/interpreter.py meson-0.61.2/mesonbuild/cmake/interpreter.py --- meson-0.53.2/mesonbuild/cmake/interpreter.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/interpreter.py 2022-01-17 10:50:45.000000000 +0000 @@ -15,22 +15,26 @@ # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. -from .common import CMakeException, CMakeTarget -from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCompute, RequestCodeModel +from .common import CMakeException, CMakeTarget, TargetOptions, CMakeConfiguration, language_map, backend_generator_map, cmake_get_generator_args, check_cmake_args +from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCompute, RequestCodeModel, ReplyCMakeInputs, ReplyCodeModel from .fileapi import CMakeFileAPI from .executor import CMakeExecutor +from .toolchain import CMakeToolchain, CMakeExecScope from .traceparser import CMakeTraceParser, CMakeGeneratorTarget -from .. import mlog -from ..environment import Environment -from ..mesonlib import MachineChoice, version_compare -from ..compilers.compilers import lang_suffixes, header_suffixes, obj_suffixes, lib_suffixes, is_header -from subprocess import Popen, PIPE -from threading import Thread +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 ..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 from enum import Enum from functools import lru_cache from pathlib import Path import typing as T -import os, re +import re +import textwrap +from os import environ from ..mparser import ( Token, @@ -50,10 +54,16 @@ if T.TYPE_CHECKING: + from .._typing import ImmutableListProtocol from ..build import Build from ..backend.backends import Backend + from ..environment import Environment -# Disable all warnings automaticall enabled with --trace and friends +TYPE_mixed = T.Union[str, int, bool, Path, BaseNode] +TYPE_mixed_list = T.Union[TYPE_mixed, T.Sequence[TYPE_mixed]] +TYPE_mixed_kwargs = T.Dict[str, TYPE_mixed_list] + +# Disable all warnings automatically enabled with --trace and friends # See https://cmake.org/cmake/help/latest/variable/CMAKE_POLICY_WARNING_CMPNNNN.html disable_policy_warnings = [ 'CMP0025', @@ -65,29 +75,9 @@ 'CMP0067', 'CMP0082', 'CMP0089', + 'CMP0102', ] -backend_generator_map = { - 'ninja': 'Ninja', - 'xcode': 'Xcode', - 'vs2010': 'Visual Studio 10 2010', - 'vs2015': 'Visual Studio 15 2017', - 'vs2017': 'Visual Studio 15 2017', - 'vs2019': 'Visual Studio 16 2019', -} - -language_map = { - 'c': 'C', - 'cpp': 'CXX', - 'cuda': 'CUDA', - 'objc': 'OBJC', - 'objcpp': 'OBJCXX', - 'cs': 'CSharp', - 'java': 'Java', - 'fortran': 'Fortran', - 'swift': 'Swift', -} - target_type_map = { 'STATIC_LIBRARY': 'static_library', 'MODULE_LIBRARY': 'shared_module', @@ -133,13 +123,15 @@ _cmake_name_regex = re.compile(r'[^_a-zA-Z0-9]') def _sanitize_cmake_name(name: str) -> str: name = _cmake_name_regex.sub('_', name) - return 'cm_' + name + if name in FORBIDDEN_TARGET_NAMES or name.startswith('meson'): + name = 'cm_' + name + return name class OutputTargetMap: rm_so_version = re.compile(r'(\.[0-9]+)+$') - def __init__(self, build_dir: str): - self.tgt_map = {} + def __init__(self, build_dir: Path): + self.tgt_map = {} # type: T.Dict[str, T.Union['ConverterTarget', 'ConverterCustomTarget']] self.build_dir = build_dir def add(self, tgt: T.Union['ConverterTarget', 'ConverterCustomTarget']) -> None: @@ -165,6 +157,14 @@ def target(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]: return self._return_first_valid_key([self._target_key(name)]) + def executable(self, name: str) -> T.Optional['ConverterTarget']: + tgt = self.target(name) + if tgt is None or not isinstance(tgt, ConverterTarget): + return None + if tgt.meson_func() != 'executable': + return None + return tgt + def artifact(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]: keys = [] candidates = [name, OutputTargetMap.rm_so_version.sub('', name)] @@ -173,106 +173,133 @@ continue new_name = name[:-len(i) - 1] new_name = OutputTargetMap.rm_so_version.sub('', new_name) - candidates += ['{}.{}'.format(new_name, i)] + candidates += [f'{new_name}.{i}'] for i in candidates: - keys += [self._rel_artifact_key(i), os.path.basename(i), self._base_artifact_key(i)] + keys += [self._rel_artifact_key(Path(i)), Path(i).name, self._base_artifact_key(Path(i))] return self._return_first_valid_key(keys) - def generated(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]: - return self._return_first_valid_key([self._rel_generated_file_key(name), self._base_generated_file_key(name)]) + def generated(self, name: Path) -> T.Optional['ConverterCustomTarget']: + res = self._return_first_valid_key([self._rel_generated_file_key(name), self._base_generated_file_key(name)]) + assert res is None or isinstance(res, ConverterCustomTarget) + return res # Utility functions to generate local keys - def _rel_path(self, fname: str) -> T.Optional[str]: - fname = os.path.normpath(os.path.join(self.build_dir, fname)) - if os.path.commonpath([self.build_dir, fname]) != self.build_dir: - return None - return os.path.relpath(fname, self.build_dir) + def _rel_path(self, fname: Path) -> T.Optional[Path]: + try: + return fname.resolve().relative_to(self.build_dir) + except ValueError: + pass + return None def _target_key(self, tgt_name: str) -> str: - return '__tgt_{}__'.format(tgt_name) + return f'__tgt_{tgt_name}__' - def _rel_generated_file_key(self, fname: str) -> T.Optional[str]: + def _rel_generated_file_key(self, fname: Path) -> T.Optional[str]: path = self._rel_path(fname) - return '__relgen_{}__'.format(path) if path else None + return f'__relgen_{path.as_posix()}__' if path else None - def _base_generated_file_key(self, fname: str) -> str: - return '__gen_{}__'.format(os.path.basename(fname)) + def _base_generated_file_key(self, fname: Path) -> str: + return f'__gen_{fname.name}__' - def _rel_artifact_key(self, fname: str) -> T.Optional[str]: + def _rel_artifact_key(self, fname: Path) -> T.Optional[str]: path = self._rel_path(fname) - return '__relart_{}__'.format(path) if path else None + return f'__relart_{path.as_posix()}__' if path else None - def _base_artifact_key(self, fname: str) -> str: - return '__art_{}__'.format(os.path.basename(fname)) + def _base_artifact_key(self, fname: Path) -> str: + return f'__art_{fname.name}__' class ConverterTarget: - def __init__(self, target: CMakeTarget, env: Environment): - self.env = env - self.artifacts = target.artifacts - self.src_dir = target.src_dir - self.build_dir = target.build_dir - self.name = target.name - self.cmake_name = target.name - self.full_name = target.full_name - self.type = target.type - self.install = target.install - self.install_dir = '' + def __init__(self, target: CMakeTarget, env: 'Environment', for_machine: MachineChoice) -> None: + self.env = env + self.for_machine = for_machine + self.artifacts = target.artifacts + self.src_dir = target.src_dir + self.build_dir = target.build_dir + self.name = target.name + self.cmake_name = target.name + self.full_name = target.full_name + self.type = target.type + self.install = target.install + self.install_dir = None # type: T.Optional[Path] self.link_libraries = target.link_libraries - self.link_flags = target.link_flags + target.link_lang_flags - self.depends_raw = [] - self.depends = [] + self.link_flags = target.link_flags + target.link_lang_flags + self.depends_raw = [] # type: T.List[str] + self.depends = [] # type: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] if target.install_paths: self.install_dir = target.install_paths[0] - self.languages = [] - self.sources = [] - self.generated = [] - self.includes = [] - self.sys_includes = [] - self.link_with = [] - self.object_libs = [] - self.compile_opts = {} - self.public_compile_opts = [] - self.pie = False + self.languages = set() # type: T.Set[str] + self.sources = [] # type: T.List[Path] + self.generated = [] # type: T.List[Path] + self.generated_ctgt = [] # type: T.List[CustomTargetReference] + self.includes = [] # type: T.List[Path] + self.sys_includes = [] # type: T.List[Path] + self.link_with = [] # type: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] + self.object_libs = [] # type: T.List[ConverterTarget] + self.compile_opts = {} # type: T.Dict[str, T.List[str]] + self.public_compile_opts = [] # type: T.List[str] + self.pie = False # Project default override options (c_std, cpp_std, etc.) - self.override_options = [] + self.override_options = [] # type: T.List[str] # Convert the target name to a valid meson target name self.name = _sanitize_cmake_name(self.name) + self.generated_raw = [] # type: T.List[Path] + for i in target.files: - # Determine the meson language + languages = set() # type: T.Set[str] + src_suffixes = set() # type: T.Set[str] + + # Insert suffixes + for j in i.sources: + if not j.suffix: + continue + src_suffixes.add(j.suffix[1:]) + + # Determine the meson language(s) + # Extract the default language from the explicit CMake field lang_cmake_to_meson = {val.lower(): key for key, val in language_map.items()} - lang = lang_cmake_to_meson.get(i.language.lower(), 'c') - if lang not in self.languages: - self.languages += [lang] - if lang not in self.compile_opts: - self.compile_opts[lang] = [] + languages.add(lang_cmake_to_meson.get(i.language.lower(), 'c')) + + # Determine missing languages from the source suffixes + for sfx in src_suffixes: + for key, val in lang_suffixes.items(): + if sfx in val: + languages.add(key) + break + + # Register the new languages and initialize the compile opts array + for lang in languages: + self.languages.add(lang) + if lang not in self.compile_opts: + self.compile_opts[lang] = [] # Add arguments, but avoid duplicates args = i.flags - args += ['-D{}'.format(x) for x in i.defines] - self.compile_opts[lang] += [x for x in args if x not in self.compile_opts[lang]] + args += [f'-D{x}' for x in i.defines] + for lang in languages: + self.compile_opts[lang] += [x for x in args if x not in self.compile_opts[lang]] # Handle include directories - self.includes += [x['path'] for x in i.includes if x not in self.includes and not x['isSystem']] - self.sys_includes += [x['path'] for x in i.includes if x not in self.sys_includes and x['isSystem']] + self.includes += [x.path for x in i.includes if x.path not in self.includes and not x.isSystem] + self.sys_includes += [x.path for x in i.includes if x.path not in self.sys_includes and x.isSystem] # Add sources to the right array if i.is_generated: - self.generated += i.sources + self.generated_raw += i.sources else: self.sources += i.sources def __repr__(self) -> str: - return '<{}: {}>'.format(self.__class__.__name__, self.name) + return f'<{self.__class__.__name__}: {self.name}>' std_regex = re.compile(r'([-]{1,2}std=|/std:v?|[-]{1,2}std:)(.*)') - def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: str, subdir: str, install_prefix: str, trace: CMakeTraceParser) -> None: - # Detect setting the C and C++ standard + def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, subdir: Path, install_prefix: Path, trace: CMakeTraceParser) -> None: + # Detect setting the C and C++ standard and do additional compiler args manipulation for i in ['c', 'cpp']: if i not in self.compile_opts: continue @@ -280,10 +307,27 @@ temp = [] for j in self.compile_opts[i]: m = ConverterTarget.std_regex.match(j) + ctgt = output_target_map.generated(Path(j)) if m: - self.override_options += ['{}_std={}'.format(i, m.group(2))] + std = m.group(2) + supported = self._all_lang_stds(i) + if std not in supported: + mlog.warning( + 'Unknown {0}_std "{1}" -> Ignoring. Try setting the project-' + 'level {0}_std if build errors occur. Known ' + '{0}_stds are: {2}'.format(i, std, ' '.join(supported)), + once=True + ) + continue + self.override_options += [f'{i}_std={std}'] elif j in ['-fPIC', '-fpic', '-fPIE', '-fpie']: self.pie = True + elif isinstance(ctgt, ConverterCustomTarget): + # Sometimes projects pass generated source files as compiler + # flags. Add these as generated sources to ensure that the + # corresponding custom target is run.2 + self.generated_raw += [Path(j)] + temp += [j] elif j in blacklist_compiler_flags: pass else: @@ -299,79 +343,13 @@ tgt = trace.targets.get(self.cmake_name) if tgt: self.depends_raw = trace.targets[self.cmake_name].depends - if self.type.upper() == 'INTERFACE_LIBRARY': - props = tgt.properties - - self.includes += props.get('INTERFACE_INCLUDE_DIRECTORIES', []) - self.public_compile_opts += props.get('INTERFACE_COMPILE_DEFINITIONS', []) - self.public_compile_opts += props.get('INTERFACE_COMPILE_OPTIONS', []) - self.link_flags += props.get('INTERFACE_LINK_OPTIONS', []) - - # TODO refactor this copy paste from CMakeDependency for future releases - reg_is_lib = re.compile(r'^(-l[a-zA-Z0-9_]+|-l?pthread)$') - to_process = [self.cmake_name] - processed = [] - while len(to_process) > 0: - curr = to_process.pop(0) - - if curr in processed or curr not in trace.targets: - continue - tgt = trace.targets[curr] - cfgs = [] - cfg = '' - otherDeps = [] - libraries = [] - mlog.debug(tgt) - - if 'INTERFACE_COMPILE_DEFINITIONS' in tgt.properties: - self.public_compile_opts += ['-D' + re.sub('^-D', '', x) for x in tgt.properties['INTERFACE_COMPILE_DEFINITIONS'] if x] - - if 'INTERFACE_COMPILE_OPTIONS' in tgt.properties: - self.public_compile_opts += [x for x in tgt.properties['INTERFACE_COMPILE_OPTIONS'] if x] - - if 'IMPORTED_CONFIGURATIONS' in tgt.properties: - cfgs += [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x] - cfg = cfgs[0] - - if 'CONFIGURATIONS' in tgt.properties: - cfgs += [x for x in tgt.properties['CONFIGURATIONS'] if x] - cfg = cfgs[0] - - if 'RELEASE' in cfgs: - cfg = 'RELEASE' - - if 'IMPORTED_IMPLIB_{}'.format(cfg) in tgt.properties: - libraries += [x for x in tgt.properties['IMPORTED_IMPLIB_{}'.format(cfg)] if x] - elif 'IMPORTED_IMPLIB' in tgt.properties: - libraries += [x for x in tgt.properties['IMPORTED_IMPLIB'] if x] - elif 'IMPORTED_LOCATION_{}'.format(cfg) in tgt.properties: - libraries += [x for x in tgt.properties['IMPORTED_LOCATION_{}'.format(cfg)] if x] - elif 'IMPORTED_LOCATION' in tgt.properties: - libraries += [x for x in tgt.properties['IMPORTED_LOCATION'] if x] - - if 'LINK_LIBRARIES' in tgt.properties: - otherDeps += [x for x in tgt.properties['LINK_LIBRARIES'] if x] - - if 'INTERFACE_LINK_LIBRARIES' in tgt.properties: - otherDeps += [x for x in tgt.properties['INTERFACE_LINK_LIBRARIES'] if x] - - if 'IMPORTED_LINK_DEPENDENT_LIBRARIES_{}'.format(cfg) in tgt.properties: - otherDeps += [x for x in tgt.properties['IMPORTED_LINK_DEPENDENT_LIBRARIES_{}'.format(cfg)] if x] - elif 'IMPORTED_LINK_DEPENDENT_LIBRARIES' in tgt.properties: - otherDeps += [x for x in tgt.properties['IMPORTED_LINK_DEPENDENT_LIBRARIES'] if x] - - for j in otherDeps: - if j in trace.targets: - to_process += [j] - elif reg_is_lib.match(j) or os.path.exists(j): - libraries += [j] - - for j in libraries: - if j not in self.link_libraries: - self.link_libraries += [j] + rtgt = resolve_cmake_trace_targets(self.cmake_name, trace, self.env) + self.includes += [Path(x) for x in rtgt.include_directories] + self.link_flags += rtgt.link_flags + self.public_compile_opts += rtgt.public_compile_opts + self.link_libraries += rtgt.libraries - processed += [curr] elif self.type.upper() not in ['EXECUTABLE', 'OBJECT_LIBRARY']: mlog.warning('CMake: Target', mlog.bold(self.cmake_name), 'not found in CMake trace. This can lead to build errors') @@ -380,7 +358,7 @@ # Let meson handle this arcane magic if ',-rpath,' in i: continue - if not os.path.isabs(i): + if not Path(i).is_absolute(): link_with = output_target_map.artifact(i) if link_with: self.link_with += [link_with] @@ -390,73 +368,75 @@ self.link_libraries = temp # Filter out files that are not supported by the language - supported = list(header_suffixes) + list(obj_suffixes) + supported = list(assembler_suffixes) + list(header_suffixes) + list(obj_suffixes) for i in self.languages: supported += list(lang_suffixes[i]) - supported = ['.{}'.format(x) for x in supported] - self.sources = [x for x in self.sources if any([x.endswith(y) for y in supported])] - self.generated = [x for x in self.generated if any([x.endswith(y) for y in supported])] + supported = [f'.{x}' for x in supported] + self.sources = [x for x in self.sources if any([x.name.endswith(y) for y in supported])] + self.generated_raw = [x for x in self.generated_raw if any([x.name.endswith(y) for y in supported])] # Make paths relative - def rel_path(x: str, is_header: bool, is_generated: bool) -> T.Optional[str]: - if not os.path.isabs(x): - x = os.path.normpath(os.path.join(self.src_dir, x)) - if not os.path.exists(x) and not any([x.endswith(y) for y in obj_suffixes]) and not is_generated: - mlog.warning('CMake: path', mlog.bold(x), 'does not exist.') - mlog.warning(' --> Ignoring. This can lead to build errors.') + def rel_path(x: Path, is_header: bool, is_generated: bool) -> T.Optional[Path]: + if not x.is_absolute(): + x = self.src_dir / x + x = x.resolve() + assert x.is_absolute() + if not x.exists() and not any([x.name.endswith(y) for y in obj_suffixes]) and not is_generated: + if path_is_in_root(x, Path(self.env.get_build_dir()), resolve=True): + x.mkdir(parents=True, exist_ok=True) + return x.relative_to(Path(self.env.get_build_dir()) / subdir) + else: + mlog.warning('CMake: path', mlog.bold(x.as_posix()), 'does not exist.') + mlog.warning(' --> Ignoring. This can lead to build errors.') + return None + if x in trace.explicit_headers: return None if ( - os.path.isabs(x) - and os.path.commonpath([x, self.env.get_source_dir()]) == self.env.get_source_dir() + path_is_in_root(x, Path(self.env.get_source_dir())) and not ( - os.path.commonpath([x, root_src_dir]) == root_src_dir or - os.path.commonpath([x, self.env.get_build_dir()]) == self.env.get_build_dir() + path_is_in_root(x, root_src_dir) or + path_is_in_root(x, Path(self.env.get_build_dir())) ) ): - mlog.warning('CMake: path', mlog.bold(x), 'is inside the root project but', mlog.bold('not'), 'inside the subproject.') + mlog.warning('CMake: path', mlog.bold(x.as_posix()), 'is inside the root project but', mlog.bold('not'), 'inside the subproject.') mlog.warning(' --> Ignoring. This can lead to build errors.') return None - if os.path.isabs(x) and os.path.commonpath([x, self.env.get_build_dir()]) == self.env.get_build_dir(): - if is_header: - return os.path.relpath(x, os.path.join(self.env.get_build_dir(), subdir)) - else: - return os.path.relpath(x, root_src_dir) - if os.path.isabs(x) and os.path.commonpath([x, root_src_dir]) == root_src_dir: - return os.path.relpath(x, root_src_dir) + if path_is_in_root(x, Path(self.env.get_build_dir())) and is_header: + return x.relative_to(Path(self.env.get_build_dir()) / subdir) + if path_is_in_root(x, root_src_dir): + return x.relative_to(root_src_dir) return x - def custom_target(x: str): - ctgt = output_target_map.generated(x) - if ctgt: - assert(isinstance(ctgt, ConverterCustomTarget)) - ref = ctgt.get_ref(x) - assert(isinstance(ref, CustomTargetReference) and ref.valid()) - return ref - return x - - build_dir_rel = os.path.relpath(self.build_dir, os.path.join(self.env.get_build_dir(), subdir)) - self.includes = list(set([rel_path(x, True, False) for x in set(self.includes)] + [build_dir_rel])) - self.sys_includes = list(set([rel_path(x, True, False) for x in set(self.sys_includes)])) + build_dir_rel = self.build_dir.relative_to(Path(self.env.get_build_dir()) / subdir) + self.generated_raw = [rel_path(x, False, True) for x in self.generated_raw] + self.includes = list(OrderedSet([rel_path(x, True, False) for x in OrderedSet(self.includes)] + [build_dir_rel])) + self.sys_includes = list(OrderedSet([rel_path(x, True, False) for x in OrderedSet(self.sys_includes)])) self.sources = [rel_path(x, False, False) for x in self.sources] - self.generated = [rel_path(x, False, True) for x in self.generated] # Resolve custom targets - self.generated = [custom_target(x) for x in self.generated] + for gen_file in self.generated_raw: + ctgt = output_target_map.generated(gen_file) + if ctgt: + assert isinstance(ctgt, ConverterCustomTarget) + ref = ctgt.get_ref(gen_file) + assert isinstance(ref, CustomTargetReference) and ref.valid() + self.generated_ctgt += [ref] + elif gen_file is not None: + self.generated += [gen_file] # Remove delete entries - self.includes = [x for x in self.includes if x is not None] + self.includes = [x for x in self.includes if x is not None] self.sys_includes = [x for x in self.sys_includes if x is not None] - self.sources = [x for x in self.sources if x is not None] - self.generated = [x for x in self.generated if x is not None] + self.sources = [x for x in self.sources if x is not None] # Make sure '.' is always in the include directories - if '.' not in self.includes: - self.includes += ['.'] + if Path('.') not in self.includes: + self.includes += [Path('.')] # make install dir relative to the install prefix - if self.install_dir and os.path.isabs(self.install_dir): - if os.path.commonpath([self.install_dir, install_prefix]) == install_prefix: - self.install_dir = os.path.relpath(self.install_dir, install_prefix) + if self.install_dir and self.install_dir.is_absolute(): + if path_is_in_root(self.install_dir, install_prefix): + self.install_dir = self.install_dir.relative_to(install_prefix) # Remove blacklisted options and libs def check_flag(flag: str) -> bool: @@ -469,24 +449,35 @@ self.link_libraries = [x for x in self.link_libraries if x.lower() not in blacklist_link_libs] self.link_flags = [x for x in self.link_flags if check_flag(x)] + # Handle OSX frameworks + def handle_frameworks(flags: T.List[str]) -> T.List[str]: + res: T.List[str] = [] + for i in flags: + p = Path(i) + if not p.exists() or not p.name.endswith('.framework'): + res += [i] + continue + res += ['-framework', p.stem] + return res + + self.link_libraries = handle_frameworks(self.link_libraries) + self.link_flags = handle_frameworks(self.link_flags) + # Handle explicit CMake add_dependency() calls for i in self.depends_raw: - tgt = output_target_map.target(i) - if tgt: - self.depends.append(tgt) + dep_tgt = output_target_map.target(i) + if dep_tgt: + self.depends.append(dep_tgt) - def process_object_libs(self, obj_target_list: T.List['ConverterTarget'], linker_workaround: bool): + def process_object_libs(self, obj_target_list: T.List['ConverterTarget'], linker_workaround: bool) -> None: # Try to detect the object library(s) from the generated input sources - temp = [x for x in self.generated if isinstance(x, str)] - temp = [os.path.basename(x) for x in temp] - temp = [x for x in temp if any([x.endswith('.' + y) for y in obj_suffixes])] - temp = [os.path.splitext(x)[0] for x in temp] + temp = [x for x in self.generated if any([x.name.endswith('.' + y) for y in obj_suffixes])] + stem = [x.stem for x in temp] exts = self._all_source_suffixes() # Temp now stores the source filenames of the object files for i in obj_target_list: - source_files = [x for x in i.sources + i.generated if isinstance(x, str)] - source_files = [os.path.basename(x) for x in source_files] - for j in temp: + source_files = [x.name for x in i.sources + i.generated] + for j in stem: # On some platforms (specifically looking at you Windows with vs20xy backend) CMake does # not produce object files with the format `foo.cpp.obj`, instead it skipps the language # suffix and just produces object files like `foo.obj`. Thus we have to do our best to @@ -495,26 +486,28 @@ candidates = [j] # type: T.List[str] if not any([j.endswith('.' + x) for x in exts]): mlog.warning('Object files do not contain source file extensions, thus falling back to guessing them.', once=True) - candidates += ['{}.{}'.format(j, x) for x in exts] + candidates += [f'{j}.{x}' for x in exts] if any([x in source_files for x in candidates]): if linker_workaround: self._append_objlib_sources(i) else: self.includes += i.includes - self.includes = list(set(self.includes)) + self.includes = list(OrderedSet(self.includes)) self.object_libs += [i] break # Filter out object files from the sources - self.generated = [x for x in self.generated if not isinstance(x, str) or not any([x.endswith('.' + y) for y in obj_suffixes])] + self.generated = [x for x in self.generated if not any([x.name.endswith('.' + y) for y in obj_suffixes])] def _append_objlib_sources(self, tgt: 'ConverterTarget') -> None: - self.includes += tgt.includes - self.sources += tgt.sources - self.generated += tgt.generated - self.sources = list(set(self.sources)) - self.generated = list(set(self.generated)) - self.includes = list(set(self.includes)) + self.includes += tgt.includes + self.sources += tgt.sources + self.generated += tgt.generated + self.generated_ctgt += tgt.generated_ctgt + self.includes = list(OrderedSet(self.includes)) + self.sources = list(OrderedSet(self.sources)) + self.generated = list(OrderedSet(self.generated)) + self.generated_ctgt = list(OrderedSet(self.generated_ctgt)) # Inherit compiler arguments since they may be required for building for lang, opts in tgt.compile_opts.items(): @@ -523,13 +516,27 @@ self.compile_opts[lang] += [x for x in opts if x not in self.compile_opts[lang]] @lru_cache(maxsize=None) - def _all_source_suffixes(self) -> T.List[str]: + def _all_source_suffixes(self) -> 'ImmutableListProtocol[str]': suffixes = [] # type: T.List[str] for exts in lang_suffixes.values(): suffixes += [x for x in exts] return suffixes - def process_inter_target_dependencies(self): + @lru_cache(maxsize=None) + def _all_lang_stds(self, lang: str) -> 'ImmutableListProtocol[str]': + try: + res = self.env.coredata.options[OptionKey('std', machine=MachineChoice.BUILD, lang=lang)].choices + except KeyError: + return [] + + # TODO: Get rid of this once we have proper typing for options + assert isinstance(res, list) + for i in res: + assert isinstance(i, str) + + return res + + def process_inter_target_dependencies(self) -> None: # Move the dependencies from all transfer_dependencies_from to the target to_process = list(self.depends) processed = [] @@ -540,9 +547,9 @@ to_process += [x for x in i.depends if x not in processed] else: new_deps += [i] - self.depends = list(set(new_deps)) + self.depends = list(OrderedSet(new_deps)) - def cleanup_dependencies(self): + def cleanup_dependencies(self) -> None: # Clear the dependencies from targets that where moved from if self.meson_func() in transfer_dependencies_from: self.depends = [] @@ -551,12 +558,12 @@ return target_type_map.get(self.type.upper()) def log(self) -> None: - mlog.log('Target', mlog.bold(self.name), '({})'.format(self.cmake_name)) + mlog.log('Target', mlog.bold(self.name), f'({self.cmake_name})') mlog.log(' -- artifacts: ', mlog.bold(str(self.artifacts))) mlog.log(' -- full_name: ', mlog.bold(self.full_name)) mlog.log(' -- type: ', mlog.bold(self.type)) mlog.log(' -- install: ', mlog.bold('true' if self.install else 'false')) - mlog.log(' -- install_dir: ', mlog.bold(self.install_dir)) + mlog.log(' -- install_dir: ', mlog.bold(self.install_dir.as_posix() if self.install_dir else '')) mlog.log(' -- link_libraries: ', mlog.bold(str(self.link_libraries))) mlog.log(' -- link_with: ', mlog.bold(str(self.link_with))) mlog.log(' -- object_libs: ', mlog.bold(str(self.object_libs))) @@ -566,6 +573,7 @@ mlog.log(' -- sys_includes: ', mlog.bold(str(self.sys_includes))) mlog.log(' -- sources: ', mlog.bold(str(self.sources))) mlog.log(' -- generated: ', mlog.bold(str(self.generated))) + mlog.log(' -- generated_ctgt: ', mlog.bold(str(self.generated_ctgt))) mlog.log(' -- pie: ', mlog.bold('true' if self.pie else 'false')) mlog.log(' -- override_opts: ', mlog.bold(str(self.override_options))) mlog.log(' -- depends: ', mlog.bold(str(self.depends))) @@ -574,7 +582,7 @@ mlog.log(' -', key, '=', mlog.bold(str(val))) class CustomTargetReference: - def __init__(self, ctgt: 'ConverterCustomTarget', index: int): + def __init__(self, ctgt: 'ConverterCustomTarget', index: int) -> None: self.ctgt = ctgt # type: ConverterCustomTarget self.index = index # type: int @@ -582,7 +590,7 @@ if self.valid(): return '<{}: {} [{}]>'.format(self.__class__.__name__, self.ctgt.name, self.ctgt.outputs[self.index]) else: - return '<{}: INVALID REFERENCE>'.format(self.__class__.__name__) + return f'<{self.__class__.__name__}: INVALID REFERENCE>' def valid(self) -> bool: return self.ctgt is not None and self.index >= 0 @@ -594,40 +602,43 @@ tgt_counter = 0 # type: int out_counter = 0 # type: int - def __init__(self, target: CMakeGeneratorTarget): - assert(target.current_bin_dir is not None) - assert(target.current_src_dir is not None) + def __init__(self, target: CMakeGeneratorTarget, env: 'Environment', for_machine: MachineChoice) -> None: + assert target.current_bin_dir is not None + assert target.current_src_dir is not None self.name = target.name if not self.name: - self.name = 'custom_tgt_{}'.format(ConverterCustomTarget.tgt_counter) + self.name = f'custom_tgt_{ConverterCustomTarget.tgt_counter}' ConverterCustomTarget.tgt_counter += 1 - self.cmake_name = str(self.name) + self.cmake_name = str(self.name) self.original_outputs = list(target.outputs) - self.outputs = [os.path.basename(x) for x in self.original_outputs] - self.conflict_map = {} - self.command = target.command - self.working_dir = target.working_dir - self.depends_raw = target.depends - self.inputs = [] - self.depends = [] - self.current_bin_dir = Path(target.current_bin_dir) - self.current_src_dir = Path(target.current_src_dir) + self.outputs = [x.name for x in self.original_outputs] + self.conflict_map = {} # type: T.Dict[str, str] + self.command = [] # type: T.List[T.List[T.Union[str, ConverterTarget]]] + self.working_dir = target.working_dir + self.depends_raw = target.depends + self.inputs = [] # type: T.List[T.Union[str, CustomTargetReference]] + self.depends = [] # type: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] + self.current_bin_dir = target.current_bin_dir # type: Path + self.current_src_dir = target.current_src_dir # type: Path + self.env = env + self.for_machine = for_machine + self._raw_target = target # Convert the target name to a valid meson target name self.name = _sanitize_cmake_name(self.name) def __repr__(self) -> str: - return '<{}: {} {}>'.format(self.__class__.__name__, self.name, self.outputs) + return f'<{self.__class__.__name__}: {self.name} {self.outputs}>' - def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: str, subdir: str, all_outputs: T.List[str]) -> None: + def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, all_outputs: T.List[str], trace: CMakeTraceParser) -> None: # Default the working directory to ${CMAKE_CURRENT_BINARY_DIR} - if not self.working_dir: - self.working_dir = self.current_bin_dir.as_posix() + if self.working_dir is None: + self.working_dir = self.current_bin_dir # relative paths in the working directory are always relative # to ${CMAKE_CURRENT_BINARY_DIR} - if not os.path.isabs(self.working_dir): - self.working_dir = (self.current_bin_dir / self.working_dir).as_posix() + if not self.working_dir.is_absolute(): + self.working_dir = self.current_bin_dir / self.working_dir # Modify the original outputs if they are relative. Again, # relative paths are relative to ${CMAKE_CURRENT_BINARY_DIR} @@ -636,7 +647,7 @@ return x else: return self.current_bin_dir / x - self.original_outputs = [ensure_absolute(Path(x)).as_posix() for x in self.original_outputs] + self.original_outputs = [ensure_absolute(x) for x in self.original_outputs] # Ensure that there is no duplicate output in the project so # that meson can handle cases where the same filename is @@ -645,7 +656,7 @@ for i in self.outputs: if i in all_outputs: old = str(i) - i = 'c{}_{}'.format(ConverterCustomTarget.out_counter, i) + i = f'c{ConverterCustomTarget.out_counter}_{i}' ConverterCustomTarget.out_counter += 1 self.conflict_map[old] = i all_outputs += [i] @@ -653,16 +664,31 @@ self.outputs = temp_outputs # Check if the command is a build target - commands = [] - for i in self.command: - assert(isinstance(i, list)) - cmd = [] + commands = [] # type: T.List[T.List[T.Union[str, ConverterTarget]]] + for curr_cmd in self._raw_target.command: + assert isinstance(curr_cmd, list) + cmd = [] # type: T.List[T.Union[str, ConverterTarget]] - for j in i: + for j in curr_cmd: if not j: continue - target = output_target_map.target(j) - cmd += [target] if target else [j] + target = output_target_map.executable(j) + if target: + # When cross compiling, binaries have to be executed with an exe_wrapper (for instance wine for mingw-w64) + if self.env.exe_wrapper is not None and self.env.properties[self.for_machine].get_cmake_use_exe_wrapper(): + assert isinstance(self.env.exe_wrapper, ExternalProgram) + cmd += self.env.exe_wrapper.get_command() + cmd += [target] + continue + elif j in trace.targets: + trace_tgt = trace.targets[j] + if trace_tgt.type == 'EXECUTABLE' and 'IMPORTED_LOCATION' in trace_tgt.properties: + cmd += trace_tgt.properties['IMPORTED_LOCATION'] + continue + mlog.debug(f'CMake: Found invalid CMake target "{j}" --> ignoring \n{trace_tgt}') + + # Fallthrough on error + cmd += [j] commands += [cmd] self.command = commands @@ -673,18 +699,17 @@ self.outputs = [self.name + '.h'] # Check dependencies and input files - root = Path(root_src_dir) for i in self.depends_raw: if not i: continue raw = Path(i) art = output_target_map.artifact(i) tgt = output_target_map.target(i) - gen = output_target_map.generated(i) + gen = output_target_map.generated(raw) rel_to_root = None try: - rel_to_root = raw.relative_to(root) + rel_to_root = raw.relative_to(root_src_dir) except ValueError: rel_to_root = None @@ -693,7 +718,7 @@ # as outputs from other targets. # See https://github.com/mesonbuild/meson/issues/6632 if not raw.is_absolute() and (self.current_src_dir / raw).exists(): - self.inputs += [(self.current_src_dir / raw).relative_to(root).as_posix()] + self.inputs += [(self.current_src_dir / raw).relative_to(root_src_dir).as_posix()] elif raw.is_absolute() and raw.exists() and rel_to_root is not None: self.inputs += [rel_to_root.as_posix()] elif art: @@ -701,9 +726,11 @@ elif tgt: self.depends += [tgt] elif gen: - self.inputs += [gen.get_ref(i)] + ctgt_ref = gen.get_ref(raw) + assert ctgt_ref is not None + self.inputs += [ctgt_ref] - def process_inter_target_dependencies(self): + def process_inter_target_dependencies(self) -> None: # Move the dependencies from all transfer_dependencies_from to the target to_process = list(self.depends) processed = [] @@ -714,20 +741,20 @@ to_process += [x for x in i.depends if x not in processed] else: new_deps += [i] - self.depends = list(set(new_deps)) + self.depends = list(OrderedSet(new_deps)) - def get_ref(self, fname: str) -> T.Optional[CustomTargetReference]: - fname = os.path.basename(fname) + def get_ref(self, fname: Path) -> T.Optional[CustomTargetReference]: + name = fname.name try: - if fname in self.conflict_map: - fname = self.conflict_map[fname] - idx = self.outputs.index(fname) + if name in self.conflict_map: + name = self.conflict_map[name] + idx = self.outputs.index(name) return CustomTargetReference(self, idx) except ValueError: return None def log(self) -> None: - mlog.log('Custom Target', mlog.bold(self.name)) + mlog.log('Custom Target', mlog.bold(self.name), f'({self.cmake_name})') mlog.log(' -- command: ', mlog.bold(str(self.command))) mlog.log(' -- outputs: ', mlog.bold(str(self.outputs))) mlog.log(' -- conflict_map: ', mlog.bold(str(self.conflict_map))) @@ -741,142 +768,118 @@ FILE = 2 class CMakeInterpreter: - def __init__(self, build: 'Build', subdir: str, src_dir: str, install_prefix: str, env: Environment, backend: 'Backend'): - assert(hasattr(backend, 'name')) - self.build = build - self.subdir = subdir - self.src_dir = src_dir - self.build_dir_rel = os.path.join(subdir, '__CMake_build') - self.build_dir = os.path.join(env.get_build_dir(), self.build_dir_rel) + def __init__(self, build: 'Build', subdir: Path, src_dir: Path, install_prefix: Path, env: 'Environment', backend: 'Backend'): + self.build = build + self.subdir = subdir + self.src_dir = src_dir + self.build_dir_rel = subdir / '__CMake_build' + self.build_dir = Path(env.get_build_dir()) / self.build_dir_rel self.install_prefix = install_prefix - self.env = env - self.backend_name = backend.name - self.linkers = set() # type: T.Set[str] - self.cmake_api = CMakeAPI.SERVER - self.client = CMakeClient(self.env) - self.fileapi = CMakeFileAPI(self.build_dir) + self.env = env + self.for_machine = MachineChoice.HOST # TODO make parameter + self.backend_name = backend.name + self.linkers = set() # type: T.Set[str] + self.cmake_api = CMakeAPI.SERVER + self.client = CMakeClient(self.env) + self.fileapi = CMakeFileAPI(self.build_dir) # Raw CMake results - self.bs_files = [] - self.codemodel_configs = None - self.raw_trace = None + self.bs_files = [] # type: T.List[Path] + self.codemodel_configs = None # type: T.Optional[T.List[CMakeConfiguration]] + self.raw_trace = None # type: T.Optional[str] # Analysed data - self.project_name = '' - self.languages = [] - self.targets = [] - self.custom_targets = [] # type: T.List[ConverterCustomTarget] - self.trace = CMakeTraceParser() + self.project_name = '' + self.languages = [] # type: T.List[str] + self.targets = [] # type: T.List[ConverterTarget] + self.custom_targets = [] # type: T.List[ConverterCustomTarget] + self.trace = CMakeTraceParser('', Path('.')) # Will be replaced in analyse self.output_target_map = OutputTargetMap(self.build_dir) # Generated meson data - self.generated_targets = {} - self.internal_name_map = {} + self.generated_targets = {} # type: T.Dict[str, T.Dict[str, T.Optional[str]]] + self.internal_name_map = {} # type: T.Dict[str, str] - def configure(self, extra_cmake_options: T.List[str]) -> None: - for_machine = MachineChoice.HOST # TODO make parameter + # Do some special handling for object libraries for certain configurations + self._object_lib_workaround = False + if self.backend_name.startswith('vs'): + for comp in self.env.coredata.compilers[self.for_machine].values(): + if comp.get_linker_id() == 'link': + self._object_lib_workaround = True + break + + def configure(self, extra_cmake_options: T.List[str]) -> CMakeExecutor: # Find CMake - cmake_exe = CMakeExecutor(self.env, '>=3.7', for_machine) + # TODO: Using MachineChoice.BUILD should always be correct here, but also evaluate the use of self.for_machine + cmake_exe = CMakeExecutor(self.env, '>=3.7', MachineChoice.BUILD) if not cmake_exe.found(): raise CMakeException('Unable to find CMake') + self.trace = CMakeTraceParser(cmake_exe.version(), self.build_dir, permissive=True) - preload_file = Path(__file__).resolve().parent / 'data' / 'preload.cmake' - - # Prefere CMAKE_PROJECT_INCLUDE over CMAKE_TOOLCHAIN_FILE if possible, - # since CMAKE_PROJECT_INCLUDE was actually designed for code injection. - preload_var = 'CMAKE_PROJECT_INCLUDE' - if version_compare(cmake_exe.version(), '<3.15'): - preload_var = 'CMAKE_TOOLCHAIN_FILE' - - generator = backend_generator_map[self.backend_name] - cmake_args = cmake_exe.get_command() - trace_args = ['--trace', '--trace-expand', '--no-warn-unused-cli'] - cmcmp_args = ['-DCMAKE_POLICY_WARNING_{}=OFF'.format(x) for x in disable_policy_warnings] - pload_args = ['-D{}={}'.format(preload_var, str(preload_file))] + preload_file = mesondata['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() + + # TODO: drop this check once the deprecated `cmake_args` kwarg is removed + extra_cmake_options = check_cmake_args(extra_cmake_options) + + cmake_args = [] + cmake_args += cmake_get_generator_args(self.env) + cmake_args += [f'-DCMAKE_INSTALL_PREFIX={self.install_prefix}'] + cmake_args += extra_cmake_options + trace_args = self.trace.trace_args() + cmcmp_args = [f'-DCMAKE_POLICY_WARNING_{x}=OFF' for x in disable_policy_warnings] if version_compare(cmake_exe.version(), '>=3.14'): self.cmake_api = CMakeAPI.FILE self.fileapi.setup_request() + else: + mlog.deprecation(f'Support for CMake <3.14 (Meson found {cmake_exe.version()}) is deprecated since Meson 0.61.0') - # Map meson compiler to CMake variables - for lang, comp in self.env.coredata.compilers[for_machine].items(): - if lang not in language_map: - continue - self.linkers.add(comp.get_linker_id()) - cmake_lang = language_map[lang] - exelist = comp.get_exelist() - if len(exelist) == 1: - cmake_args += ['-DCMAKE_{}_COMPILER={}'.format(cmake_lang, exelist[0])] - elif len(exelist) == 2: - cmake_args += ['-DCMAKE_{}_COMPILER_LAUNCHER={}'.format(cmake_lang, exelist[0]), - '-DCMAKE_{}_COMPILER={}'.format(cmake_lang, exelist[1])] - if hasattr(comp, 'get_linker_exelist') and comp.get_id() == 'clang-cl': - cmake_args += ['-DCMAKE_LINKER={}'.format(comp.get_linker_exelist()[0])] - cmake_args += ['-G', generator] - cmake_args += ['-DCMAKE_INSTALL_PREFIX={}'.format(self.install_prefix)] - cmake_args += extra_cmake_options + if version_compare(cmake_exe.version(), '<3.17.0'): + mlog.warning(textwrap.dedent(f'''\ + The minimum recommended CMake version is 3.17.0. + | + | However, Meson was only able to find CMake {cmake_exe.version()} at {cmake_exe.cmakebin.command}. + | + | Support for all CMake versions below 3.17.0 will be deprecated and + | removed once newer CMake versions are more widely adopted. If you encounter + | any errors please try upgrading CMake to a newer version first. + ''')) # Run CMake mlog.log() with mlog.nested(): mlog.log('Configuring the build directory with', mlog.bold('CMake'), 'version', mlog.cyan(cmake_exe.version())) - mlog.log(mlog.bold('Running:'), ' '.join(cmake_args)) - mlog.log(mlog.bold(' - build directory: '), self.build_dir) - mlog.log(mlog.bold(' - source directory: '), self.src_dir) + mlog.log(mlog.bold('Running CMake with:'), ' '.join(cmake_args)) + mlog.log(mlog.bold(' - build directory: '), self.build_dir.as_posix()) + mlog.log(mlog.bold(' - source directory: '), self.src_dir.as_posix()) + mlog.log(mlog.bold(' - toolchain file: '), toolchain_file.as_posix()) + mlog.log(mlog.bold(' - preload file: '), preload_file.as_posix()) mlog.log(mlog.bold(' - trace args: '), ' '.join(trace_args)) - mlog.log(mlog.bold(' - preload file: '), str(preload_file)) mlog.log(mlog.bold(' - disabled policy warnings:'), '[{}]'.format(', '.join(disable_policy_warnings))) mlog.log() - os.makedirs(self.build_dir, exist_ok=True) - os_env = os.environ.copy() + self.build_dir.mkdir(parents=True, exist_ok=True) + os_env = environ.copy() os_env['LC_ALL'] = 'C' - final_command = cmake_args + trace_args + cmcmp_args + pload_args + [self.src_dir] - proc = Popen(final_command, stdout=PIPE, stderr=PIPE, cwd=self.build_dir, env=os_env) - - def print_stdout(): - while True: - line = proc.stdout.readline() - if not line: - break - mlog.log(line.decode('utf-8').strip('\n')) - proc.stdout.close() - - t = Thread(target=print_stdout) - t.start() - - # Read stderr line by line and log non trace lines - self.raw_trace = '' - tline_start_reg = re.compile(r'^\s*(.*\.(cmake|txt))\(([0-9]+)\):\s*(\w+)\(.*$') - inside_multiline_trace = False - while True: - line = proc.stderr.readline() - if not line: - break - line = line.decode('utf-8') - if tline_start_reg.match(line): - self.raw_trace += line - inside_multiline_trace = not line.endswith(' )\n') - elif inside_multiline_trace: - self.raw_trace += line - else: - mlog.warning(line.strip('\n')) - - proc.stderr.close() - proc.wait() + final_args = cmake_args + trace_args + cmcmp_args + toolchain.get_cmake_args() + [self.src_dir.as_posix()] - t.join() + cmake_exe.set_exec_mode(print_cmout=True, always_capture_stderr=self.trace.requires_stderr()) + rc, _, self.raw_trace = cmake_exe.call(final_args, self.build_dir, env=os_env, disable_cache=True) mlog.log() - h = mlog.green('SUCCEEDED') if proc.returncode == 0 else mlog.red('FAILED') + h = mlog.green('SUCCEEDED') if rc == 0 else mlog.red('FAILED') mlog.log('CMake configuration:', h) - if proc.returncode != 0: + if rc != 0: raise CMakeException('Failed to configure the CMake subproject') + return cmake_exe + def initialise(self, extra_cmake_options: T.List[str]) -> None: # Run configure the old way because doing it # with the server doesn't work for some reason # Additionally, the File API requires a configure anyway - self.configure(extra_cmake_options) + cmake_exe = self.configure(extra_cmake_options) # Continue with the file API If supported if self.cmake_api is CMakeAPI.FILE: @@ -886,14 +889,15 @@ # Load the buildsystem file list cmake_files = self.fileapi.get_cmake_sources() self.bs_files = [x.file for x in cmake_files if not x.is_cmake and not x.is_temp] - self.bs_files = [os.path.relpath(x, self.env.get_source_dir()) for x in self.bs_files] - self.bs_files = list(set(self.bs_files)) + self.bs_files = [relative_to_if_possible(x, Path(self.env.get_source_dir())) for x in self.bs_files] + self.bs_files = [x for x in self.bs_files if not path_is_in_root(x, Path(self.env.get_build_dir()), resolve=True)] + self.bs_files = list(OrderedSet(self.bs_files)) # Load the codemodel configurations self.codemodel_configs = self.fileapi.get_cmake_configurations() return - with self.client.connect(): + with self.client.connect(cmake_exe): generator = backend_generator_map[self.backend_name] self.client.do_handshake(self.src_dir, self.build_dir, generator, 1) @@ -905,14 +909,17 @@ # Get CMake build system files bs_reply = self.client.query_checked(RequestCMakeInputs(), 'Querying build system files') + assert isinstance(bs_reply, ReplyCMakeInputs) # Now get the CMake code model cm_reply = self.client.query_checked(RequestCodeModel(), 'Querying the CMake code model') + assert isinstance(cm_reply, ReplyCodeModel) src_dir = bs_reply.src_dir self.bs_files = [x.file for x in bs_reply.build_files if not x.is_cmake and not x.is_temp] - self.bs_files = [os.path.relpath(os.path.join(src_dir, x), self.env.get_source_dir()) for x in self.bs_files] - self.bs_files = list(set(self.bs_files)) + self.bs_files = [relative_to_if_possible(src_dir / x, Path(self.env.get_source_dir()), resolve=True) for x in self.bs_files] + self.bs_files = [x for x in self.bs_files if not path_is_in_root(x, Path(self.env.get_build_dir()), resolve=True)] + self.bs_files = list(OrderedSet(self.bs_files)) self.codemodel_configs = cm_reply.configs def analyse(self) -> None: @@ -924,79 +931,79 @@ self.languages = [] self.targets = [] self.custom_targets = [] - self.trace = CMakeTraceParser(permissive=True) # Parse the trace self.trace.parse(self.raw_trace) # Find all targets added_target_names = [] # type: T.List[str] - for i in self.codemodel_configs: - for j in i.projects: + for i_0 in self.codemodel_configs: + for j_0 in i_0.projects: if not self.project_name: - self.project_name = j.name - for k in j.targets: + self.project_name = j_0.name + for k_0 in j_0.targets: # Avoid duplicate targets from different configurations and known # dummy CMake internal target types - if k.type not in skip_targets and k.name not in added_target_names: - added_target_names += [k.name] - self.targets += [ConverterTarget(k, self.env)] + if k_0.type not in skip_targets and k_0.name not in added_target_names: + added_target_names += [k_0.name] + self.targets += [ConverterTarget(k_0, self.env, self.for_machine)] # Add interface targets from trace, if not already present. # This step is required because interface targets were removed from # the CMake file API output. api_target_name_list = [x.name for x in self.targets] - for i in self.trace.targets.values(): - if i.type != 'INTERFACE' or i.name in api_target_name_list or i.imported: + for i_1 in self.trace.targets.values(): + if i_1.type != 'INTERFACE' or i_1.name in api_target_name_list or i_1.imported: continue dummy = CMakeTarget({ - 'name': i.name, + 'name': i_1.name, 'type': 'INTERFACE_LIBRARY', 'sourceDirectory': self.src_dir, 'buildDirectory': self.build_dir, }) - self.targets += [ConverterTarget(dummy, self.env)] + self.targets += [ConverterTarget(dummy, self.env, self.for_machine)] - for i in self.trace.custom_targets: - self.custom_targets += [ConverterCustomTarget(i)] + for i_2 in self.trace.custom_targets: + self.custom_targets += [ConverterCustomTarget(i_2, self.env, self.for_machine)] # generate the output_target_map - for i in [*self.targets, *self.custom_targets]: - self.output_target_map.add(i) + for i_3 in [*self.targets, *self.custom_targets]: + assert isinstance(i_3, (ConverterTarget, ConverterCustomTarget)) + self.output_target_map.add(i_3) # First pass: Basic target cleanup object_libs = [] custom_target_outputs = [] # type: T.List[str] - for i in self.custom_targets: - i.postprocess(self.output_target_map, self.src_dir, self.subdir, custom_target_outputs) - for i in self.targets: - i.postprocess(self.output_target_map, self.src_dir, self.subdir, self.install_prefix, self.trace) - if i.type == 'OBJECT_LIBRARY': - object_libs += [i] - self.languages += [x for x in i.languages if x not in self.languages] + for ctgt in self.custom_targets: + ctgt.postprocess(self.output_target_map, self.src_dir, custom_target_outputs, self.trace) + for tgt in self.targets: + tgt.postprocess(self.output_target_map, self.src_dir, self.subdir, self.install_prefix, self.trace) + if tgt.type == 'OBJECT_LIBRARY': + object_libs += [tgt] + self.languages += [x for x in tgt.languages if x not in self.languages] # Second pass: Detect object library dependencies - for i in self.targets: - i.process_object_libs(object_libs, self._object_lib_workaround()) + for tgt in self.targets: + tgt.process_object_libs(object_libs, self._object_lib_workaround) # Third pass: Reassign dependencies to avoid some loops - for i in self.targets: - i.process_inter_target_dependencies() - for i in self.custom_targets: - i.process_inter_target_dependencies() + for tgt in self.targets: + tgt.process_inter_target_dependencies() + for ctgt in self.custom_targets: + ctgt.process_inter_target_dependencies() # Fourth pass: Remove rassigned dependencies - for i in self.targets: - i.cleanup_dependencies() + for tgt in self.targets: + tgt.cleanup_dependencies() mlog.log('CMake project', mlog.bold(self.project_name), 'has', mlog.bold(str(len(self.targets) + len(self.custom_targets))), 'build targets.') - def pretend_to_be_meson(self) -> CodeBlockNode: + def pretend_to_be_meson(self, options: TargetOptions) -> CodeBlockNode: if not self.project_name: raise CMakeException('CMakeInterpreter was not analysed') - def token(tid: str = 'string', val='') -> Token: - return Token(tid, self.subdir, 0, 0, 0, None, val) + def token(tid: str = 'string', val: TYPE_mixed = '') -> Token: + return Token(tid, self.subdir.as_posix(), 0, 0, 0, None, val) def string(value: str) -> StringNode: return StringNode(token(val=value)) @@ -1007,64 +1014,67 @@ def number(value: int) -> NumberNode: return NumberNode(token(val=value)) - def nodeify(value): + def nodeify(value: TYPE_mixed_list) -> BaseNode: if isinstance(value, str): return string(value) + if isinstance(value, Path): + return string(value.as_posix()) elif isinstance(value, bool): - return BooleanNode(token(), value) + return BooleanNode(token(val=value)) elif isinstance(value, int): return number(value) elif isinstance(value, list): return array(value) - return value + elif isinstance(value, BaseNode): + return value + raise RuntimeError('invalid type of value: {} ({})'.format(type(value).__name__, str(value))) def indexed(node: BaseNode, index: int) -> IndexNode: return IndexNode(node, nodeify(index)) - def array(elements) -> ArrayNode: + def array(elements: TYPE_mixed_list) -> ArrayNode: args = ArgumentNode(token()) if not isinstance(elements, list): elements = [args] args.arguments += [nodeify(x) for x in elements if x is not None] return ArrayNode(args, 0, 0, 0, 0) - def function(name: str, args=None, kwargs=None) -> FunctionNode: + def function(name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> FunctionNode: args = [] if args is None else args kwargs = {} if kwargs is None else kwargs args_n = ArgumentNode(token()) if not isinstance(args, list): + assert isinstance(args, (str, int, bool, Path, BaseNode)) args = [args] args_n.arguments = [nodeify(x) for x in args if x is not None] - args_n.kwargs = {k: nodeify(v) for k, v in kwargs.items() if v is not None} - func_n = FunctionNode(self.subdir, 0, 0, 0, 0, name, args_n) + args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} + func_n = FunctionNode(self.subdir.as_posix(), 0, 0, 0, 0, name, args_n) return func_n - def method(obj: BaseNode, name: str, args=None, kwargs=None) -> MethodNode: + def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> MethodNode: args = [] if args is None else args kwargs = {} if kwargs is None else kwargs args_n = ArgumentNode(token()) if not isinstance(args, list): + assert isinstance(args, (str, int, bool, Path, BaseNode)) args = [args] args_n.arguments = [nodeify(x) for x in args if x is not None] - args_n.kwargs = {k: nodeify(v) for k, v in kwargs.items() if v is not None} - return MethodNode(self.subdir, 0, 0, obj, name, args_n) + args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} + return MethodNode(self.subdir.as_posix(), 0, 0, obj, name, args_n) def assign(var_name: str, value: BaseNode) -> AssignmentNode: - return AssignmentNode(self.subdir, 0, 0, var_name, value) + return AssignmentNode(self.subdir.as_posix(), 0, 0, var_name, value) # Generate the root code block and the project function call root_cb = CodeBlockNode(token()) root_cb.lines += [function('project', [self.project_name] + self.languages)] # Add the run script for custom commands - run_script = '{}/data/run_ctgt.py'.format(os.path.dirname(os.path.realpath(__file__))) - run_script_var = 'ctgt_run_script' - root_cb.lines += [assign(run_script_var, function('find_program', [[run_script]], {'required': True}))] # Add the targets - processing = [] - processed = {} - name_map = {} + processing = [] # type: T.List[str] + processed = {} # type: T.Dict[str, T.Dict[str, T.Optional[str]]] + name_map = {} # type: T.Dict[str, str] def extract_tgt(tgt: T.Union[ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> IdNode: tgt_name = None @@ -1072,7 +1082,7 @@ tgt_name = tgt.name elif isinstance(tgt, CustomTargetReference): tgt_name = tgt.ctgt.name - assert(tgt_name is not None and tgt_name in processed) + assert tgt_name is not None and tgt_name in processed res_var = processed[tgt_name]['tgt'] return id_node(res_var) if res_var else None @@ -1081,31 +1091,31 @@ raise CMakeException('Cycle in CMake inputs/dependencies detected') processing.append(tgt.name) - def resolve_ctgt_ref(ref: CustomTargetReference) -> BaseNode: + def resolve_ctgt_ref(ref: CustomTargetReference) -> T.Union[IdNode, IndexNode]: tgt_var = extract_tgt(ref) if len(ref.ctgt.outputs) == 1: return tgt_var else: return indexed(tgt_var, ref.index) - def process_target(tgt: ConverterTarget): + def process_target(tgt: ConverterTarget) -> None: detect_cycle(tgt) # First handle inter target dependencies - link_with = [] - objec_libs = [] # type: T.List[IdNode] - sources = [] - generated = [] - generated_filenames = [] - custom_targets = [] - dependencies = [] + link_with = [] # type: T.List[IdNode] + objec_libs = [] # type: T.List[IdNode] + sources = [] # type: T.List[Path] + generated = [] # type: T.List[T.Union[IdNode, IndexNode]] + generated_filenames = [] # type: T.List[str] + custom_targets = [] # type: T.List[ConverterCustomTarget] + dependencies = [] # type: T.List[IdNode] for i in tgt.link_with: - assert(isinstance(i, ConverterTarget)) + assert isinstance(i, ConverterTarget) if i.name not in processed: process_target(i) link_with += [extract_tgt(i)] for i in tgt.object_libs: - assert(isinstance(i, ConverterTarget)) + assert isinstance(i, ConverterTarget) if i.name not in processed: process_target(i) objec_libs += [extract_tgt(i)] @@ -1117,16 +1127,17 @@ dependencies += [extract_tgt(i)] # Generate the source list and handle generated sources - for i in tgt.sources + tgt.generated: - if isinstance(i, CustomTargetReference): - if i.ctgt.name not in processed: - process_custom_target(i.ctgt) - generated += [resolve_ctgt_ref(i)] - generated_filenames += [i.filename()] - if i.ctgt not in custom_targets: - custom_targets += [i.ctgt] - else: - sources += [i] + sources += tgt.sources + sources += tgt.generated + + for ctgt_ref in tgt.generated_ctgt: + ctgt = ctgt_ref.ctgt + if ctgt.name not in processed: + process_custom_target(ctgt) + generated += [resolve_ctgt_ref(ctgt_ref)] + generated_filenames += [ctgt_ref.filename()] + if ctgt not in custom_targets: + custom_targets += [ctgt] # Add all header files from all used custom targets. This # ensures that all custom targets are built before any @@ -1134,42 +1145,47 @@ # header files are present. This step is necessary because # CMake always ensures that a custom target is executed # before another target if at least one output is used. - for i in custom_targets: - for j in i.outputs: + for ctgt in custom_targets: + for j in ctgt.outputs: if not is_header(j) or j in generated_filenames: continue - generated += [resolve_ctgt_ref(i.get_ref(j))] + generated += [resolve_ctgt_ref(ctgt.get_ref(Path(j)))] generated_filenames += [j] # Determine the meson function to use for the build target tgt_func = tgt.meson_func() if not tgt_func: - raise CMakeException('Unknown target type "{}"'.format(tgt.type)) + raise CMakeException(f'Unknown target type "{tgt.type}"') # Determine the variable names - inc_var = '{}_inc'.format(tgt.name) - dir_var = '{}_dir'.format(tgt.name) - sys_var = '{}_sys'.format(tgt.name) - src_var = '{}_src'.format(tgt.name) - dep_var = '{}_dep'.format(tgt.name) + inc_var = f'{tgt.name}_inc' + dir_var = f'{tgt.name}_dir' + sys_var = f'{tgt.name}_sys' + src_var = f'{tgt.name}_src' + dep_var = f'{tgt.name}_dep' tgt_var = tgt.name + install_tgt = options.get_install(tgt.cmake_name, tgt.install) + # Generate target kwargs tgt_kwargs = { - 'build_by_default': False, - 'link_args': tgt.link_flags + tgt.link_libraries, + 'build_by_default': install_tgt, + 'link_args': options.get_link_args(tgt.cmake_name, tgt.link_flags + tgt.link_libraries), 'link_with': link_with, 'include_directories': id_node(inc_var), - 'install': tgt.install, - 'install_dir': tgt.install_dir, - 'override_options': tgt.override_options, + 'install': install_tgt, + 'override_options': options.get_override_options(tgt.cmake_name, tgt.override_options), 'objects': [method(x, 'extract_all_objects') for x in objec_libs], - } + } # type: TYPE_mixed_kwargs + + # Only set if installed and only override if it is set + if install_tgt and tgt.install_dir: + tgt_kwargs['install_dir'] = tgt.install_dir # Handle compiler args for key, val in tgt.compile_opts.items(): - tgt_kwargs['{}_args'.format(key)] = val + tgt_kwargs[f'{key}_args'] = options.get_compile_args(tgt.cmake_name, key, val) # Handle -fPCI, etc if tgt_func == 'executable': @@ -1183,7 +1199,7 @@ 'link_with': id_node(tgt_var), 'compile_args': tgt.public_compile_opts, 'include_directories': id_node(inc_var), - } + } # type: TYPE_mixed_kwargs if dependencies: generated += dependencies @@ -1201,11 +1217,15 @@ tgt_var = None else: src_node = assign(src_var, function('files', sources)) - tgt_node = assign(tgt_var, function(tgt_func, [tgt_var, [id_node(src_var)] + generated], tgt_kwargs)) + tgt_node = assign(tgt_var, function(tgt_func, [tgt_var, id_node(src_var), *generated], tgt_kwargs)) node_list += [src_node, tgt_node] if tgt_func in ['static_library', 'shared_library']: dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs)) node_list += [dep_node] + elif tgt_func in ['shared_module']: + del dep_kwargs['link_with'] + dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs)) + node_list += [dep_node] else: dep_var = None @@ -1223,7 +1243,7 @@ detect_cycle(tgt) tgt_var = tgt.name # type: str - def resolve_source(x: T.Any) -> T.Any: + def resolve_source(x: T.Union[str, ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> T.Union[str, IdNode, IndexNode]: if isinstance(x, ConverterTarget): if x.name not in processed: process_target(x) @@ -1240,12 +1260,13 @@ return x # Generate the command list - command = [] - command += [id_node(run_script_var)] + command = [] # type: T.List[T.Union[str, IdNode, IndexNode]] + command += mesonlib.get_meson_command() + command += ['--internal', 'cmake_run_ctgt'] command += ['-o', '@OUTPUT@'] if tgt.original_outputs: - command += ['-O'] + tgt.original_outputs - command += ['-d', tgt.working_dir] + command += ['-O'] + [x.as_posix() for x in tgt.original_outputs] + command += ['-d', tgt.working_dir.as_posix()] # Generate the commands. Subcommands are separated by ';;;' for cmd in tgt.command: @@ -1256,19 +1277,19 @@ 'output': tgt.outputs, 'command': command, 'depends': [resolve_source(x) for x in tgt.depends], - } + } # type: TYPE_mixed_kwargs root_cb.lines += [assign(tgt_var, function('custom_target', [tgt.name], tgt_kwargs))] processed[tgt.name] = {'inc': None, 'src': None, 'dep': None, 'tgt': tgt_var, 'func': 'custom_target'} name_map[tgt.cmake_name] = tgt.name # Now generate the target function calls - for i in self.custom_targets: - if i.name not in processed: - process_custom_target(i) - for i in self.targets: - if i.name not in processed: - process_target(i) + for ctgt in self.custom_targets: + if ctgt.name not in processed: + process_custom_target(ctgt) + for tgt in self.targets: + if tgt.name not in processed: + process_target(tgt) self.generated_targets = processed self.internal_name_map = name_map @@ -1283,12 +1304,9 @@ # check if there exists a name mapping if target in self.internal_name_map: target = self.internal_name_map[target] - assert(target in self.generated_targets) + assert target in self.generated_targets return self.generated_targets[target] return None def target_list(self) -> T.List[str]: return list(self.internal_name_map.keys()) - - def _object_lib_workaround(self) -> bool: - return 'link' in self.linkers and self.backend_name.startswith('vs') diff -Nru meson-0.53.2/mesonbuild/cmake/toolchain.py meson-0.61.2/mesonbuild/cmake/toolchain.py --- meson-0.53.2/mesonbuild/cmake/toolchain.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/toolchain.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,258 @@ +# Copyright 2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import Path +from .traceparser import CMakeTraceParser +from ..envconfig import CMakeSkipCompilerTest +from ..mesonlib import MachineChoice +from ..compilers import VisualStudioLikeCompiler +from .common import language_map, cmake_get_generator_args +from .. import mlog + +import shutil +import typing as T +from enum import Enum +from textwrap import dedent + +if T.TYPE_CHECKING: + from .executor import CMakeExecutor + from ..environment import Environment + from ..compilers import Compiler + +class CMakeExecScope(Enum): + SUBPROJECT = 'subproject' + DEPENDENCY = 'dependency' + +class CMakeToolchain: + def __init__(self, cmakebin: 'CMakeExecutor', env: 'Environment', for_machine: MachineChoice, exec_scope: CMakeExecScope, build_dir: Path, preload_file: T.Optional[Path] = None) -> None: + self.env = env + self.cmakebin = cmakebin + self.for_machine = for_machine + self.exec_scope = exec_scope + self.preload_file = preload_file + self.build_dir = build_dir + self.build_dir = self.build_dir.resolve() + self.toolchain_file = build_dir / 'CMakeMesonToolchainFile.cmake' + self.cmcache_file = build_dir / 'CMakeCache.txt' + self.minfo = self.env.machines[self.for_machine] + self.properties = self.env.properties[self.for_machine] + self.compilers = self.env.coredata.compilers[self.for_machine] + self.cmakevars = self.env.cmakevars[self.for_machine] + self.cmakestate = self.env.coredata.cmake_cache[self.for_machine] + + self.variables = self.get_defaults() + self.variables.update(self.cmakevars.get_variables()) + + # Determine whether CMake the compiler test should be skipped + skip_status = self.properties.get_cmake_skip_compiler_test() + self.skip_check = skip_status == CMakeSkipCompilerTest.ALWAYS + if skip_status == CMakeSkipCompilerTest.DEP_ONLY and self.exec_scope == CMakeExecScope.DEPENDENCY: + self.skip_check = True + if not self.properties.get_cmake_defaults(): + self.skip_check = False + + assert self.toolchain_file.is_absolute() + + def write(self) -> Path: + if not self.toolchain_file.parent.exists(): + self.toolchain_file.parent.mkdir(parents=True) + self.toolchain_file.write_text(self.generate(), encoding='utf-8') + self.cmcache_file.write_text(self.generate_cache(), encoding='utf-8') + mlog.cmd_ci_include(self.toolchain_file.as_posix()) + return self.toolchain_file + + def get_cmake_args(self) -> T.List[str]: + args = ['-DCMAKE_TOOLCHAIN_FILE=' + self.toolchain_file.as_posix()] + if self.preload_file is not None: + args += ['-DMESON_PRELOAD_FILE=' + self.preload_file.as_posix()] + return args + + @staticmethod + def _print_vars(vars: T.Dict[str, T.List[str]]) -> str: + res = '' + for key, value in vars.items(): + res += 'set(' + key + for i in value: + res += f' "{i}"' + res += ')\n' + return res + + def generate(self) -> str: + res = dedent('''\ + ###################################### + ### AUTOMATICALLY GENERATED FILE ### + ###################################### + + # This file was generated from the configuration in the + # relevant meson machine file. See the meson documentation + # https://mesonbuild.com/Machine-files.html for more information + + if(DEFINED MESON_PRELOAD_FILE) + include("${MESON_PRELOAD_FILE}") + endif() + + ''') + + # Escape all \ in the values + for key, value in self.variables.items(): + self.variables[key] = [x.replace('\\', '/') for x in value] + + # Set compiler + if self.skip_check: + self.update_cmake_compiler_state() + res += '# CMake compiler state variables\n' + for lang, vars in self.cmakestate: + res += f'# -- Variables for language {lang}\n' + res += self._print_vars(vars) + res += '\n' + res += '\n' + + # Set variables from the current machine config + res += '# Variables from meson\n' + res += self._print_vars(self.variables) + res += '\n' + + # Add the user provided toolchain file + user_file = self.properties.get_cmake_toolchain_file() + if user_file is not None: + res += dedent(''' + # Load the CMake toolchain file specified by the user + include("{}") + + '''.format(user_file.as_posix())) + + return res + + def generate_cache(self) -> str: + if not self.skip_check: + return '' + + res = '' + for name, v in self.cmakestate.cmake_cache.items(): + res += f'{name}:{v.type}={";".join(v.value)}\n' + return res + + def get_defaults(self) -> T.Dict[str, T.List[str]]: + defaults = {} # type: T.Dict[str, T.List[str]] + + # Do nothing if the user does not want automatic defaults + if not self.properties.get_cmake_defaults(): + return defaults + + # Best effort to map the meson system name to CMAKE_SYSTEM_NAME, which + # is not trivial since CMake lacks a list of all supported + # CMAKE_SYSTEM_NAME values. + SYSTEM_MAP = { + 'android': 'Android', + 'linux': 'Linux', + 'windows': 'Windows', + 'freebsd': 'FreeBSD', + 'darwin': 'Darwin', + } # type: T.Dict[str, str] + + # Only set these in a cross build. Otherwise CMake will trip up in native + # builds and thing they are cross (which causes TRY_RUN() to break) + if self.env.is_cross_build(when_building_for=self.for_machine): + defaults['CMAKE_SYSTEM_NAME'] = [SYSTEM_MAP.get(self.minfo.system, self.minfo.system)] + defaults['CMAKE_SYSTEM_PROCESSOR'] = [self.minfo.cpu_family] + + defaults['CMAKE_SIZEOF_VOID_P'] = ['8' if self.minfo.is_64_bit else '4'] + + sys_root = self.properties.get_sys_root() + if sys_root: + defaults['CMAKE_SYSROOT'] = [sys_root] + + def make_abs(exe: str) -> str: + if Path(exe).is_absolute(): + return exe + + p = shutil.which(exe) + if p is None: + return exe + return p + + # Set the compiler variables + for lang, comp_obj in self.compilers.items(): + prefix = 'CMAKE_{}_'.format(language_map.get(lang, lang.upper())) + + exe_list = comp_obj.get_exelist() + if not exe_list: + continue + + if len(exe_list) >= 2 and not self.is_cmdline_option(comp_obj, exe_list[1]): + defaults[prefix + 'COMPILER_LAUNCHER'] = [make_abs(exe_list[0])] + exe_list = exe_list[1:] + + exe_list[0] = make_abs(exe_list[0]) + defaults[prefix + 'COMPILER'] = exe_list + if comp_obj.get_id() == 'clang-cl': + defaults['CMAKE_LINKER'] = comp_obj.get_linker_exelist() + + return defaults + + @staticmethod + def is_cmdline_option(compiler: 'Compiler', arg: str) -> bool: + if isinstance(compiler, VisualStudioLikeCompiler): + return arg.startswith('/') + else: + return arg.startswith('-') + + def update_cmake_compiler_state(self) -> None: + # Check if all variables are already cached + if self.cmakestate.languages.issuperset(self.compilers.keys()): + return + + # Generate the CMakeLists.txt + mlog.debug('CMake Toolchain: Calling CMake once to generate the compiler state') + languages = list(self.compilers.keys()) + lang_ids = [language_map.get(x, x.upper()) for x in languages] + cmake_content = dedent(f''' + cmake_minimum_required(VERSION 3.7) + project(CompInfo {' '.join(lang_ids)}) + ''') + + build_dir = Path(self.env.scratch_dir) / '__CMake_compiler_info__' + build_dir.mkdir(parents=True, exist_ok=True) + cmake_file = build_dir / 'CMakeLists.txt' + cmake_file.write_text(cmake_content, encoding='utf-8') + + # Generate the temporary toolchain file + temp_toolchain_file = build_dir / 'CMakeMesonTempToolchainFile.cmake' + temp_toolchain_file.write_text(CMakeToolchain._print_vars(self.variables), encoding='utf-8') + + # Configure + trace = CMakeTraceParser(self.cmakebin.version(), build_dir) + self.cmakebin.set_exec_mode(print_cmout=False, always_capture_stderr=trace.requires_stderr()) + cmake_args = [] + cmake_args += trace.trace_args() + cmake_args += cmake_get_generator_args(self.env) + cmake_args += [f'-DCMAKE_TOOLCHAIN_FILE={temp_toolchain_file.as_posix()}', '.'] + rc, _, raw_trace = self.cmakebin.call(cmake_args, build_dir=build_dir, disable_cache=True) + + if rc != 0: + mlog.warning('CMake Toolchain: Failed to determine CMake compilers state') + return + + # Parse output + trace.parse(raw_trace) + self.cmakestate.cmake_cache = {**trace.cache} + + vars_by_file = {k.name: v for (k, v) in trace.vars_by_file.items()} + + for lang in languages: + lang_cmake = language_map.get(lang, lang.upper()) + file_name = f'CMake{lang_cmake}Compiler.cmake' + vars = vars_by_file.setdefault(file_name, {}) + vars[f'CMAKE_{lang_cmake}_COMPILER_FORCED'] = ['1'] + self.cmakestate.update(lang, vars) diff -Nru meson-0.53.2/mesonbuild/cmake/traceparser.py meson-0.61.2/mesonbuild/cmake/traceparser.py --- meson-0.53.2/mesonbuild/cmake/traceparser.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/traceparser.py 2021-11-02 19:58:07.000000000 +0000 @@ -18,36 +18,56 @@ from .common import CMakeException from .generator import parse_generator_expressions from .. import mlog +from ..mesonlib import version_compare import typing as T +from pathlib import Path +from functools import lru_cache import re -import os +import json +import textwrap class CMakeTraceLine: - def __init__(self, file, line, func, args): - self.file = file + def __init__(self, file_str: str, line: int, func: str, args: T.List[str]) -> None: + self.file = CMakeTraceLine._to_path(file_str) self.line = line self.func = func.lower() self.args = args - def __repr__(self): + @staticmethod + @lru_cache(maxsize=None) + def _to_path(file_str: str) -> Path: + return Path(file_str) + + def __repr__(self) -> str: s = 'CMake TRACE: {0}:{1} {2}({3})' return s.format(self.file, self.line, self.func, self.args) +class CMakeCacheEntry(T.NamedTuple): + value: T.List[str] + type: str + class CMakeTarget: - def __init__(self, name, target_type, properties=None, imported: bool = False, tline: T.Optional[CMakeTraceLine] = None): + def __init__( + self, + name: str, + target_type: str, + properties: T.Optional[T.Dict[str, T.List[str]]] = None, + imported: bool = False, + tline: T.Optional[CMakeTraceLine] = None + ): if properties is None: properties = {} - self.name = name - self.type = target_type - self.properties = properties - self.imported = imported - self.tline = tline - self.depends = [] - self.current_bin_dir = None - self.current_src_dir = None + self.name = name + self.type = target_type + self.properties = properties + self.imported = imported + self.tline = tline + self.depends = [] # type: T.List[str] + self.current_bin_dir = None # type: T.Optional[Path] + self.current_src_dir = None # type: T.Optional[Path] - def __repr__(self): + def __repr__(self) -> str: s = 'CMake TARGET:\n -- name: {}\n -- type: {}\n -- imported: {}\n -- properties: {{\n{} }}\n -- tline: {}' propSTR = '' for i in self.properties: @@ -60,23 +80,32 @@ return for key, val in self.properties.items(): self.properties[key] = [x.strip() for x in val] + assert all([';' not in x for x in self.properties[key]]) class CMakeGeneratorTarget(CMakeTarget): - def __init__(self, name): + def __init__(self, name: str) -> None: super().__init__(name, 'CUSTOM', {}) - self.outputs = [] # type: T.List[str] + self.outputs = [] # type: T.List[Path] self.command = [] # type: T.List[T.List[str]] - self.working_dir = None # type: T.Optional[str] + self.working_dir = None # type: T.Optional[Path] class CMakeTraceParser: - def __init__(self, permissive: bool = False): - self.vars = {} # type: T.Dict[str, T.List[str]] - self.targets = {} # type: T.Dict[str, CMakeTarget] + def __init__(self, cmake_version: str, build_dir: Path, permissive: bool = True) -> None: + self.vars: T.Dict[str, T.List[str]] = {} + self.vars_by_file: T.Dict[Path, T.Dict[str, T.List[str]]] = {} + self.targets: T.Dict[str, CMakeTarget] = {} + self.cache: T.Dict[str, CMakeCacheEntry] = {} + + self.explicit_headers = set() # type: T.Set[Path] # T.List of targes that were added with add_custom_command to generate files self.custom_targets = [] # type: T.List[CMakeGeneratorTarget] self.permissive = permissive # type: bool + self.cmake_version = cmake_version # type: str + self.trace_file = 'cmake_trace.txt' + self.trace_file_path = build_dir / self.trace_file + self.trace_format = 'json-v1' if version_compare(cmake_version, '>=3.17') else 'human' # State for delayed command execution. Delayed command execution is realised # with a custom CMake file that overrides some functions and adds some @@ -106,12 +135,41 @@ # meaning here in the trace parser. 'meson_ps_execute_delayed_calls': self._meson_ps_execute_delayed_calls, 'meson_ps_reload_vars': self._meson_ps_reload_vars, - } + 'meson_ps_disabled_function': self._meson_ps_disabled_function, + } # type: T.Dict[str, T.Callable[[CMakeTraceLine], None]] + def trace_args(self) -> T.List[str]: + arg_map = { + 'human': ['--trace', '--trace-expand'], + 'json-v1': ['--trace-expand', '--trace-format=json-v1'], + } - def parse(self, trace: str) -> None: - # First parse the trace - lexer1 = self._lex_trace(trace) + base_args = ['--no-warn-unused-cli'] + if not self.requires_stderr(): + base_args += [f'--trace-redirect={self.trace_file}'] + + return arg_map[self.trace_format] + base_args + + def requires_stderr(self) -> bool: + return version_compare(self.cmake_version, '<3.16') + + def parse(self, trace: T.Optional[str] = None) -> None: + # First load the trace (if required) + if not self.requires_stderr(): + if not self.trace_file_path.exists and not self.trace_file_path.is_file(): + raise CMakeException(f'CMake: Trace file "{self.trace_file_path!s}" not found') + trace = self.trace_file_path.read_text(errors='ignore', encoding='utf-8') + if not trace: + raise CMakeException('CMake: The CMake trace was not provided or is empty') + + # Second parse the trace + lexer1 = None + if self.trace_format == 'human': + lexer1 = self._lex_trace_human(trace) + elif self.trace_format == 'json-v1': + lexer1 = self._lex_trace_json(trace) + else: + raise CMakeException(f'CMake: Internal error: Invalid trace format {self.trace_format}. Expected [human, json-v1]') # Primary pass -- parse everything for l in lexer1: @@ -122,7 +180,7 @@ # "Execute" the CMake function if supported fn = self.functions.get(l.func, None) - if(fn): + if fn: fn(l) # Postprocess @@ -150,24 +208,26 @@ return None - def var_to_bool(self, var): - if var not in self.vars: - return False - - if len(self.vars[var]) < 1: + def _str_to_bool(self, expr: T.Union[str, T.List[str]]) -> bool: + if not expr: return False + if isinstance(expr, list): + expr_str = expr[0] + else: + expr_str = expr + expr_str = expr_str.upper() + return expr_str not in ['0', 'OFF', 'NO', 'FALSE', 'N', 'IGNORE'] and not expr_str.endswith('NOTFOUND') - if self.vars[var][0].upper() in ['1', 'ON', 'TRUE']: - return True - return False + def var_to_bool(self, var: str) -> bool: + return self._str_to_bool(self.vars.get(var, [])) def _gen_exception(self, function: str, error: str, tline: CMakeTraceLine) -> None: # Generate an exception if the parser is not in permissive mode if self.permissive: - mlog.debug('CMake trace warning: {}() {}\n{}'.format(function, error, tline)) + mlog.debug(f'CMake trace warning: {function}() {error}\n{tline}') return None - raise CMakeException('CMake: {}() {}\n{}'.format(function, error, tline)) + raise CMakeException(f'CMake: {function}() {error}\n{tline}') def _cmake_set(self, tline: CMakeTraceLine) -> None: """Handler for the CMake set() function in all variaties. @@ -186,6 +246,14 @@ """ # DOC: https://cmake.org/cmake/help/latest/command/set.html + cache_type = None + cache_force = 'FORCE' in tline.args + try: + cache_idx = tline.args.index('CACHE') + cache_type = tline.args[cache_idx + 1] + except (ValueError, IndexError): + pass + # 1st remove PARENT_SCOPE and CACHE from args args = [] for i in tline.args: @@ -208,14 +276,21 @@ identifier = args.pop(0) value = ' '.join(args) + # Write to the CMake cache instead + if cache_type: + # Honor how the CMake FORCE parameter works + if identifier not in self.cache or cache_force: + self.cache[identifier] = CMakeCacheEntry(value.split(';'), cache_type) + if not value: # Same as unset if identifier in self.vars: del self.vars[identifier] else: self.vars[identifier] = value.split(';') + self.vars_by_file.setdefault(tline.file, {})[identifier] = value.split(';') - def _cmake_unset(self, tline: CMakeTraceLine): + def _cmake_unset(self, tline: CMakeTraceLine) -> None: # DOC: https://cmake.org/cmake/help/latest/command/unset.html if len(tline.args) < 1: return self._gen_exception('unset', 'requires at least one argument', tline) @@ -223,11 +298,12 @@ if tline.args[0] in self.vars: del self.vars[tline.args[0]] - def _cmake_add_executable(self, tline: CMakeTraceLine): + def _cmake_add_executable(self, tline: CMakeTraceLine) -> None: # DOC: https://cmake.org/cmake/help/latest/command/add_executable.html args = list(tline.args) # Make a working copy # Make sure the exe is imported + is_imported = True if 'IMPORTED' not in args: return self._gen_exception('add_executable', 'non imported executables are not supported', tline) @@ -236,9 +312,9 @@ if len(args) < 1: return self._gen_exception('add_executable', 'requires at least 1 argument', tline) - self.targets[args[0]] = CMakeTarget(args[0], 'EXECUTABLE', {}) + self.targets[args[0]] = CMakeTarget(args[0], 'EXECUTABLE', {}, tline=tline, imported=is_imported) - def _cmake_add_library(self, tline: CMakeTraceLine): + def _cmake_add_library(self, tline: CMakeTraceLine) -> None: # DOC: https://cmake.org/cmake/help/latest/command/add_library.html args = list(tline.args) # Make a working copy @@ -272,9 +348,9 @@ else: self.targets[args[0]] = CMakeTarget(args[0], 'NORMAL', {}, tline=tline) - def _cmake_add_custom_command(self, tline: CMakeTraceLine, name=None): + def _cmake_add_custom_command(self, tline: CMakeTraceLine, name: T.Optional[str] = None) -> None: # DOC: https://cmake.org/cmake/help/latest/command/add_custom_command.html - args = list(tline.args) # Make a working copy + args = self._flatten_args(list(tline.args)) # Commands can be passed as ';' separated lists if not args: return self._gen_exception('add_custom_command', 'requires at least 1 argument', tline) @@ -290,22 +366,24 @@ target = CMakeGeneratorTarget(name) def handle_output(key: str, target: CMakeGeneratorTarget) -> None: - target.outputs += key.split(';') + target.outputs += [Path(key)] def handle_command(key: str, target: CMakeGeneratorTarget) -> None: if key == 'ARGS': return - target.command[-1] += key.split(';') + target.command[-1] += [key] def handle_depends(key: str, target: CMakeGeneratorTarget) -> None: - target.depends += key.split(';') + target.depends += [key] + working_dir = None def handle_working_dir(key: str, target: CMakeGeneratorTarget) -> None: - if target.working_dir is None: - target.working_dir = key + nonlocal working_dir + if working_dir is None: + working_dir = key else: - target.working_dir += ' ' - target.working_dir += key + working_dir += ' ' + working_dir += key fn = None @@ -327,9 +405,13 @@ if fn is not None: fn(i, target) - target.current_bin_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_BINARY_DIR') - target.current_src_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_SOURCE_DIR') - target.outputs = self._guess_files(target.outputs) + cbinary_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_BINARY_DIR') + csource_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_SOURCE_DIR') + + target.working_dir = Path(working_dir) if working_dir else None + target.current_bin_dir = Path(cbinary_dir) if cbinary_dir else None + target.current_src_dir = Path(csource_dir) if csource_dir else None + target.outputs = [Path(x) for x in self._guess_files([str(y) for y in target.outputs])] target.depends = self._guess_files(target.depends) target.command = [self._guess_files(x) for x in target.command] @@ -337,7 +419,7 @@ if name: self.targets[name] = target - def _cmake_add_custom_target(self, tline: CMakeTraceLine): + def _cmake_add_custom_target(self, tline: CMakeTraceLine) -> None: # DOC: https://cmake.org/cmake/help/latest/command/add_custom_target.html # We only the first parameter (the target name) is interesting if len(tline.args) < 1: @@ -350,9 +432,7 @@ # DOC: https://cmake.org/cmake/help/latest/command/set_property.html args = list(tline.args) - # We only care for TARGET properties - if args.pop(0) != 'TARGET': - return + scope = args.pop(0) append = False targets = [] @@ -367,7 +447,7 @@ if curr == 'PROPERTY': break - targets.append(curr) + targets += curr.split(';') if not args: return self._gen_exception('set_property', 'faild to parse argument list', tline) @@ -377,21 +457,52 @@ return identifier = args.pop(0) - value = ' '.join(args).split(';') + if self.trace_format == 'human': + value = ' '.join(args).split(';') + else: + value = [y for x in args for y in x.split(';')] if not value: return - for i in targets: - if i not in self.targets: - return self._gen_exception('set_property', 'TARGET {} not found'.format(i), tline) - - if identifier not in self.targets[i].properties: - self.targets[i].properties[identifier] = [] + def do_target(t: str) -> None: + if t not in self.targets: + return self._gen_exception('set_property', f'TARGET {t} not found', tline) + + tgt = self.targets[t] + if identifier not in tgt.properties: + tgt.properties[identifier] = [] if append: - self.targets[i].properties[identifier] += value + tgt.properties[identifier] += value else: - self.targets[i].properties[identifier] = value + tgt.properties[identifier] = value + + def do_source(src: str) -> None: + if identifier != 'HEADER_FILE_ONLY' or not self._str_to_bool(value): + return + + current_src_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_SOURCE_DIR') + if not current_src_dir: + mlog.warning(textwrap.dedent('''\ + CMake trace: set_property(SOURCE) called before the preload script was loaded. + Unable to determine CMAKE_CURRENT_SOURCE_DIR. This can lead to build errors. + ''')) + current_src_dir = '.' + + cur_p = Path(current_src_dir) + src_p = Path(src) + + if not src_p.is_absolute(): + src_p = cur_p / src_p + self.explicit_headers.add(src_p) + + if scope == 'TARGET': + for i in targets: + do_target(i) + elif scope == 'SOURCE': + files = self._guess_files(targets) + for i in files: + do_source(i) def _cmake_set_target_properties(self, tline: CMakeTraceLine) -> None: # DOC: https://cmake.org/cmake/help/latest/command/set_target_properties.html @@ -417,26 +528,32 @@ # Neither of these is awesome for obvious reasons. I'm going to try # option 1 first and fall back to 2, as 1 requires less code and less # synchroniztion for cmake changes. + # + # With the JSON output format, introduced in CMake 3.17, spaces are + # handled properly and we don't have to do either options arglist = [] # type: T.List[T.Tuple[str, T.List[str]]] - name = args.pop(0) - values = [] - prop_regex = re.compile(r'^[A-Z_]+$') - for a in args: - if prop_regex.match(a): - if values: - arglist.append((name, ' '.join(values).split(';'))) - name = a - values = [] - else: - values.append(a) - if values: - arglist.append((name, ' '.join(values).split(';'))) + if self.trace_format == 'human': + name = args.pop(0) + values = [] # type: T.List[str] + prop_regex = re.compile(r'^[A-Z_]+$') + for a in args: + if prop_regex.match(a): + if values: + arglist.append((name, ' '.join(values).split(';'))) + name = a + values = [] + else: + values.append(a) + if values: + arglist.append((name, ' '.join(values).split(';'))) + else: + arglist = [(x[0], x[1].split(';')) for x in zip(args[::2], args[1::2])] for name, value in arglist: for i in targets: if i not in self.targets: - return self._gen_exception('set_target_properties', 'TARGET {} not found'.format(i), tline) + return self._gen_exception('set_target_properties', f'TARGET {i} not found', tline) self.targets[i].properties[name] = value @@ -474,7 +591,7 @@ # DOC: https://cmake.org/cmake/help/latest/command/target_link_libraries.html self._parse_common_target_options('target_link_options', 'LINK_LIBRARIES', 'INTERFACE_LINK_LIBRARIES', tline) - def _parse_common_target_options(self, func: str, private_prop: str, interface_prop: str, tline: CMakeTraceLine, ignore: T.Optional[T.List[str]] = None, paths: bool = False): + def _parse_common_target_options(self, func: str, private_prop: str, interface_prop: str, tline: CMakeTraceLine, ignore: T.Optional[T.List[str]] = None, paths: bool = False) -> None: if ignore is None: ignore = ['BEFORE'] @@ -485,7 +602,7 @@ target = args[0] if target not in self.targets: - return self._gen_exception(func, 'TARGET {} not found'.format(target), tline) + return self._gen_exception(func, f'TARGET {target} not found', tline) interface = [] private = [] @@ -500,10 +617,10 @@ continue if mode in ['INTERFACE', 'LINK_INTERFACE_LIBRARIES', 'PUBLIC', 'LINK_PUBLIC']: - interface += [i] + interface += i.split(';') if mode in ['PUBLIC', 'PRIVATE', 'LINK_PRIVATE']: - private += [i] + private += i.split(';') if paths: interface = self._guess_files(interface) @@ -512,16 +629,16 @@ interface = [x for x in interface if x] private = [x for x in private if x] - for i in [(private_prop, private), (interface_prop, interface)]: - if not i[0] in self.targets[target].properties: - self.targets[target].properties[i[0]] = [] + for j in [(private_prop, private), (interface_prop, interface)]: + if not j[0] in self.targets[target].properties: + self.targets[target].properties[j[0]] = [] - self.targets[target].properties[i[0]] += i[1] + self.targets[target].properties[j[0]] += j[1] def _meson_ps_execute_delayed_calls(self, tline: CMakeTraceLine) -> None: for l in self.stored_commands: fn = self.functions.get(l.func, None) - if(fn): + if fn: fn(l) # clear the stored commands @@ -530,7 +647,14 @@ def _meson_ps_reload_vars(self, tline: CMakeTraceLine) -> None: self.delayed_commands = self.get_cmake_var('MESON_PS_DELAYED_CALLS') - def _lex_trace(self, trace): + def _meson_ps_disabled_function(self, tline: CMakeTraceLine) -> None: + args = list(tline.args) + if not args: + mlog.error('Invalid preload.cmake script! At least one argument to `meson_ps_disabled_function` is expected') + return + mlog.warning(f'The CMake function "{args[0]}" was disabled to avoid compatibility issues with Meson.') + + def _lex_trace_human(self, trace: str) -> T.Generator[CMakeTraceLine, None, None]: # The trace format is: '(): ( )\n' reg_tline = re.compile(r'\s*(.*\.(cmake|txt))\(([0-9]+)\):\s*(\w+)\(([\s\S]*?) ?\)\s*\n', re.MULTILINE) reg_other = re.compile(r'[^\n]*\n') @@ -553,38 +677,79 @@ func = mo_file_line.group(4) args = mo_file_line.group(5) args = parse_generator_expressions(args) - args = args.split(' ') - args = list(map(lambda x: x.strip(), args)) + argl = args.split(' ') + argl = list(map(lambda x: x.strip(), argl)) + + yield CMakeTraceLine(file, int(line), func, argl) - yield CMakeTraceLine(file, line, func, args) + def _lex_trace_json(self, trace: str) -> T.Generator[CMakeTraceLine, None, None]: + lines = trace.splitlines(keepends=False) + lines.pop(0) # The first line is the version + for i in lines: + data = json.loads(i) + assert isinstance(data['file'], str) + assert isinstance(data['line'], int) + assert isinstance(data['cmd'], str) + assert isinstance(data['args'], list) + args = data['args'] + for j in args: + assert isinstance(j, str) + args = [parse_generator_expressions(x) for x in args] + yield CMakeTraceLine(data['file'], data['line'], data['cmd'], args) + + def _flatten_args(self, args: T.List[str]) -> T.List[str]: + # Split lists in arguments + res = [] # type: T.List[str] + for i in args: + res += i.split(';') + return res def _guess_files(self, broken_list: T.List[str]) -> T.List[str]: - #Try joining file paths that contain spaces + # Nothing has to be done for newer formats + if self.trace_format != 'human': + return broken_list + + # Try joining file paths that contain spaces - reg_start = re.compile(r'^([A-Za-z]:)?/.*/[^./]+$') + reg_start = re.compile(r'^([A-Za-z]:)?/(.*/)*[^./]+$') reg_end = re.compile(r'^.*\.[a-zA-Z]+$') fixed_list = [] # type: T.List[str] curr_str = None # type: T.Optional[str] + path_found = False # type: bool for i in broken_list: if curr_str is None: curr_str = i - elif os.path.isfile(curr_str): + path_found = False + elif Path(curr_str).is_file(): # Abort concatenation if curr_str is an existing file fixed_list += [curr_str] curr_str = i + path_found = False elif not reg_start.match(curr_str): # Abort concatenation if curr_str no longer matches the regex fixed_list += [curr_str] curr_str = i - elif reg_end.match(i) or os.path.exists('{} {}'.format(curr_str, i)): + path_found = False + elif reg_end.match(i): # File detected - curr_str = '{} {}'.format(curr_str, i) + curr_str = f'{curr_str} {i}' fixed_list += [curr_str] curr_str = None + path_found = False + elif Path(f'{curr_str} {i}').exists(): + # Path detected + curr_str = f'{curr_str} {i}' + path_found = True + elif path_found: + # Add path to fixed_list after ensuring the whole path is in curr_str + fixed_list += [curr_str] + curr_str = i + path_found = False else: - curr_str = '{} {}'.format(curr_str, i) + curr_str = f'{curr_str} {i}' + path_found = False if curr_str: fixed_list += [curr_str] diff -Nru meson-0.53.2/mesonbuild/cmake/tracetargets.py meson-0.61.2/mesonbuild/cmake/tracetargets.py --- meson-0.53.2/mesonbuild/cmake/tracetargets.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/cmake/tracetargets.py 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,117 @@ +# SPDX-License-Identifer: Apache-2.0 +# Copyright 2021 The Meson development team + +from .common import cmake_is_debug +from .. import mlog + +from pathlib import Path +import re +import typing as T + +if T.TYPE_CHECKING: + from .traceparser import CMakeTraceParser + from ..environment import Environment + from ..compilers import Compiler + +class ResolvedTarget: + def __init__(self) -> None: + self.include_directories: T.List[str] = [] + self.link_flags: T.List[str] = [] + self.public_compile_opts: T.List[str] = [] + self.libraries: T.List[str] = [] + +def resolve_cmake_trace_targets(target_name: str, + trace: 'CMakeTraceParser', + env: 'Environment', + *, + clib_compiler: T.Optional['Compiler'] = None, + not_found_warning: T.Callable[[str], None] = lambda x: None) -> ResolvedTarget: + res = ResolvedTarget() + targets = [target_name] + + # recognise arguments we should pass directly to the linker + reg_is_lib = re.compile(r'^(-l[a-zA-Z0-9_]+|-l?pthread)$') + reg_is_maybe_bare_lib = re.compile(r'^[a-zA-Z0-9_]+$') + + is_debug = cmake_is_debug(env) + + processed_targets: T.List[str] = [] + while len(targets) > 0: + curr = targets.pop(0) + + # Skip already processed targets + if curr in processed_targets: + continue + + if curr not in trace.targets: + if reg_is_lib.match(curr): + res.libraries += [curr] + elif Path(curr).is_absolute() and Path(curr).exists(): + res.libraries += [curr] + elif env.machines.build.is_windows() and reg_is_maybe_bare_lib.match(curr) and clib_compiler is not None: + # On Windows, CMake library dependencies can be passed as bare library names, + # CMake brute-forces a combination of prefix/suffix combinations to find the + # right library. Assume any bare argument passed which is not also a CMake + # target must be a system library we should try to link against. + res.libraries += clib_compiler.find_library(curr, env, []) + else: + not_found_warning(curr) + continue + + tgt = trace.targets[curr] + cfgs = [] + cfg = '' + mlog.debug(tgt) + + if 'INTERFACE_INCLUDE_DIRECTORIES' in tgt.properties: + res.include_directories += [x for x in tgt.properties['INTERFACE_INCLUDE_DIRECTORIES'] if x] + + if 'INTERFACE_LINK_OPTIONS' in tgt.properties: + res.link_flags += [x for x in tgt.properties['INTERFACE_LINK_OPTIONS'] if x] + + if 'INTERFACE_COMPILE_DEFINITIONS' in tgt.properties: + res.public_compile_opts += ['-D' + re.sub('^-D', '', x) for x in tgt.properties['INTERFACE_COMPILE_DEFINITIONS'] if x] + + if 'INTERFACE_COMPILE_OPTIONS' in tgt.properties: + res.public_compile_opts += [x for x in tgt.properties['INTERFACE_COMPILE_OPTIONS'] if x] + + if 'IMPORTED_CONFIGURATIONS' in tgt.properties: + cfgs = [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x] + cfg = cfgs[0] + + if is_debug: + if 'DEBUG' in cfgs: + cfg = 'DEBUG' + elif 'RELEASE' in cfgs: + cfg = 'RELEASE' + else: + if 'RELEASE' in cfgs: + cfg = 'RELEASE' + + if f'IMPORTED_IMPLIB_{cfg}' in tgt.properties: + res.libraries += [x for x in tgt.properties[f'IMPORTED_IMPLIB_{cfg}'] if x] + elif 'IMPORTED_IMPLIB' in tgt.properties: + res.libraries += [x for x in tgt.properties['IMPORTED_IMPLIB'] if x] + elif f'IMPORTED_LOCATION_{cfg}' in tgt.properties: + res.libraries += [x for x in tgt.properties[f'IMPORTED_LOCATION_{cfg}'] if x] + elif 'IMPORTED_LOCATION' in tgt.properties: + res.libraries += [x for x in tgt.properties['IMPORTED_LOCATION'] if x] + + if 'LINK_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['LINK_LIBRARIES'] if x] + if 'INTERFACE_LINK_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['INTERFACE_LINK_LIBRARIES'] if x] + + if f'IMPORTED_LINK_DEPENDENT_LIBRARIES_{cfg}' in tgt.properties: + targets += [x for x in tgt.properties[f'IMPORTED_LINK_DEPENDENT_LIBRARIES_{cfg}'] if x] + elif 'IMPORTED_LINK_DEPENDENT_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['IMPORTED_LINK_DEPENDENT_LIBRARIES'] if x] + + processed_targets += [curr] + + res.include_directories = sorted(set(res.include_directories)) + res.link_flags = sorted(set(res.link_flags)) + res.public_compile_opts = sorted(set(res.public_compile_opts)) + res.libraries = sorted(set(res.libraries)) + + return res diff -Nru meson-0.53.2/mesonbuild/compilers/c_function_attributes.py meson-0.61.2/mesonbuild/compilers/c_function_attributes.py --- meson-0.53.2/mesonbuild/compilers/c_function_attributes.py 2019-08-28 17:15:39.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/c_function_attributes.py 2020-08-15 16:27:05.000000000 +0000 @@ -56,6 +56,8 @@ 'int foo(const char * p, ...) __attribute__((format(printf, 1, 2)));', 'format_arg': 'char * foo(const char * p) __attribute__((format_arg(1)));', + 'force_align_arg_pointer': + '__attribute__((force_align_arg_pointer)) int foo(void) { return 0; }', 'gnu_inline': 'inline __attribute__((gnu_inline)) int foo(void) { return 0; }', 'hot': diff -Nru meson-0.53.2/mesonbuild/compilers/compilers.py meson-0.61.2/mesonbuild/compilers/compilers.py --- meson-0.53.2/mesonbuild/compilers/compilers.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/compilers.py 2022-01-02 20:12:32.000000000 +0000 @@ -12,40 +12,48 @@ # See the License for the specific language governing permissions and # limitations under the License. -import contextlib, os.path, re, tempfile -import collections.abc +import abc +import contextlib, os.path, re +import enum +import itertools import typing as T +from functools import lru_cache -from ..linkers import StaticLinker, GnuLikeDynamicLinkerMixin, SolarisDynamicLinker from .. import coredata from .. import mlog from .. import mesonlib from ..mesonlib import ( + HoldableObject, EnvironmentException, MachineChoice, MesonException, - Popen_safe, split_args -) -from ..envconfig import ( - Properties, + Popen_safe, LibType, TemporaryDirectoryWinProof, OptionKey, ) +from ..arglist import CompilerArgs + if T.TYPE_CHECKING: - from ..coredata import OptionDictType + from ..build import BuildTarget + from ..coredata import KeyedOptionDictType from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker # noqa: F401 + from ..linkers import DynamicLinker, RSPFileSyntax + from ..dependencies import Dependency + + CompilerType = T.TypeVar('CompilerType', bound='Compiler') + _T = T.TypeVar('_T') """This file contains the data files of all compilers Meson knows about. To support a new compiler, add its information below. Also add corresponding autodetection code in environment.py.""" -header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di') -obj_suffixes = ('o', 'obj', 'res') -lib_suffixes = ('a', 'lib', 'dll', 'dll.a', 'dylib', 'so') +header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di') # type: T.Tuple[str, ...] +obj_suffixes = ('o', 'obj', 'res') # type: T.Tuple[str, ...] +# To the emscripten compiler, .js files are libraries +lib_suffixes = ('a', 'lib', 'dll', 'dll.a', 'dylib', 'so', 'js') # type: T.Tuple[str, ...] # Mapping of language to suffixes of files that should always be in that language # This means we can't include .h headers here since they could be C, C++, ObjC, etc. lang_suffixes = { 'c': ('c',), - 'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'), + 'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx', 'ino', 'ixx', 'C'), 'cuda': ('cu',), # f90, f95, f03, f08 are for free-form fortran ('f90' recommended) # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended) @@ -58,44 +66,50 @@ 'cs': ('cs',), 'swift': ('swift',), 'java': ('java',), -} + 'cython': ('pyx', ), +} # type: T.Dict[str, T.Tuple[str, ...]] all_languages = lang_suffixes.keys() -cpp_suffixes = lang_suffixes['cpp'] + ('h',) -c_suffixes = lang_suffixes['c'] + ('h',) +cpp_suffixes = lang_suffixes['cpp'] + ('h',) # type: T.Tuple[str, ...] +c_suffixes = lang_suffixes['c'] + ('h',) # type: T.Tuple[str, ...] # List of languages that by default consume and output libraries following the -# C ABI; these can generally be used interchangebly -clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',) +# C ABI; these can generally be used interchangeably +clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',) # type: T.Tuple[str, ...] +# List of assembler suffixes that can be linked with C code directly by the linker +assembler_suffixes: T.Tuple[str, ...] = ('s', 'S') # List of languages that can be linked with C code directly by the linker # used in build.py:process_compilers() and build.py:get_dynamic_linker() -clink_langs = ('d', 'cuda') + clib_langs -clink_suffixes = () +clink_langs = ('d', 'cuda') + clib_langs # type: T.Tuple[str, ...] +clink_suffixes = tuple() # type: T.Tuple[str, ...] for _l in clink_langs + ('vala',): clink_suffixes += lang_suffixes[_l] clink_suffixes += ('h', 'll', 's') +all_suffixes = set(itertools.chain(*lang_suffixes.values(), clink_suffixes)) # type: T.Set[str] +SUFFIX_TO_LANG = dict(itertools.chain(*( + [(suffix, lang) for suffix in v] for lang, v in lang_suffixes.items()))) # type: T.Dict[str, str] # Languages that should use LDFLAGS arguments when linking. -languages_using_ldflags = ('objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda') +LANGUAGES_USING_LDFLAGS = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'} # type: T.Set[str] +# Languages that should use CPPFLAGS arguments when linking. +LANGUAGES_USING_CPPFLAGS = {'c', 'cpp', 'objc', 'objcpp'} # type: T.Set[str] soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') # Environment variables that each lang uses. -cflags_mapping = {'c': 'CFLAGS', - 'cpp': 'CXXFLAGS', - 'cuda': 'CUFLAGS', - 'objc': 'OBJCFLAGS', - 'objcpp': 'OBJCXXFLAGS', - 'fortran': 'FFLAGS', - 'd': 'DFLAGS', - 'vala': 'VALAFLAGS', - 'rust': 'RUSTFLAGS'} - -unixy_compiler_internal_libs = ('m', 'c', 'pthread', 'dl', 'rt') -# execinfo is a compiler lib on FreeBSD and NetBSD -if mesonlib.is_freebsd() or mesonlib.is_netbsd(): - unixy_compiler_internal_libs += ('execinfo',) +CFLAGS_MAPPING: T.Mapping[str, str] = { + 'c': 'CFLAGS', + 'cpp': 'CXXFLAGS', + 'cuda': 'CUFLAGS', + 'objc': 'OBJCFLAGS', + 'objcpp': 'OBJCXXFLAGS', + 'fortran': 'FFLAGS', + 'd': 'DFLAGS', + 'vala': 'VALAFLAGS', + 'rust': 'RUSTFLAGS', + 'cython': 'CYTHONFLAGS', +} # All these are only for C-linkable languages; see `clink_langs` above. -def sort_clink(lang): +def sort_clink(lang: str) -> int: ''' Sorting function to sort the list of languages according to reversed(compilers.clink_langs) and append the unknown langs in the end. @@ -106,36 +120,40 @@ return 1 return -clink_langs.index(lang) -def is_header(fname): - if hasattr(fname, 'fname'): +def is_header(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): fname = fname.fname suffix = fname.split('.')[-1] return suffix in header_suffixes -def is_source(fname): - if hasattr(fname, 'fname'): +def is_source(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): fname = fname.fname suffix = fname.split('.')[-1].lower() return suffix in clink_suffixes -def is_assembly(fname): - if hasattr(fname, 'fname'): +def is_assembly(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): fname = fname.fname return fname.split('.')[-1].lower() == 's' -def is_llvm_ir(fname): - if hasattr(fname, 'fname'): +def is_llvm_ir(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): fname = fname.fname return fname.split('.')[-1] == 'll' -def is_object(fname): - if hasattr(fname, 'fname'): - fname = fname.fname +@lru_cache(maxsize=None) +def cached_by_name(fname: 'mesonlib.FileOrString') -> bool: suffix = fname.split('.')[-1] return suffix in obj_suffixes -def is_library(fname): - if hasattr(fname, 'fname'): +def is_object(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + return cached_by_name(fname) + +def is_library(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): fname = fname.fname if soregex.match(fname): @@ -144,19 +162,35 @@ suffix = fname.split('.')[-1] return suffix in lib_suffixes +def is_known_suffix(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + suffix = fname.split('.')[-1] + + return suffix in all_suffixes + + +class CompileCheckMode(enum.Enum): + + PREPROCESS = 'preprocess' + COMPILE = 'compile' + LINK = 'link' + + cuda_buildtype_args = {'plain': [], - 'debug': [], - 'debugoptimized': [], + 'debug': ['-g', '-G'], + 'debugoptimized': ['-g', '-lineinfo'], 'release': [], 'minsize': [], - } + 'custom': [], + } # type: T.Dict[str, T.List[str]] java_buildtype_args = {'plain': [], 'debug': ['-g'], 'debugoptimized': ['-g'], 'release': [], 'minsize': [], 'custom': [], - } + } # type: T.Dict[str, T.List[str]] rust_buildtype_args = {'plain': [], 'debug': [], @@ -164,31 +198,31 @@ 'release': [], 'minsize': [], 'custom': [], - } + } # type: T.Dict[str, T.List[str]] d_gdc_buildtype_args = {'plain': [], 'debug': [], 'debugoptimized': ['-finline-functions'], - 'release': ['-frelease', '-finline-functions'], + 'release': ['-finline-functions'], 'minsize': [], 'custom': [], - } + } # type: T.Dict[str, T.List[str]] d_ldc_buildtype_args = {'plain': [], 'debug': [], 'debugoptimized': ['-enable-inlining', '-Hkeep-all-bodies'], - 'release': ['-release', '-enable-inlining', '-Hkeep-all-bodies'], + 'release': ['-enable-inlining', '-Hkeep-all-bodies'], 'minsize': [], 'custom': [], - } + } # type: T.Dict[str, T.List[str]] d_dmd_buildtype_args = {'plain': [], 'debug': [], 'debugoptimized': ['-inline'], - 'release': ['-release', '-inline'], + 'release': ['-inline'], 'minsize': [], 'custom': [], - } + } # type: T.Dict[str, T.List[str]] mono_buildtype_args = {'plain': [], 'debug': [], @@ -196,7 +230,7 @@ 'release': ['-optimize+'], 'minsize': [], 'custom': [], - } + } # type: T.Dict[str, T.List[str]] swift_buildtype_args = {'plain': [], 'debug': [], @@ -204,14 +238,14 @@ 'release': [], 'minsize': [], 'custom': [], - } + } # type: T.Dict[str, T.List[str]] gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32', - '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32'] + '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32'] # type: T.List[str] msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib', 'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib', - 'uuid.lib', 'comdlg32.lib', 'advapi32.lib'] + 'uuid.lib', 'comdlg32.lib', 'advapi32.lib'] # type: T.List[str] clike_optimization_args = {'0': [], 'g': [], @@ -219,7 +253,7 @@ '2': ['-O2'], '3': ['-O3'], 's': ['-Os'], - } + } # type: T.Dict[str, T.List[str]] cuda_optimization_args = {'0': [], 'g': ['-O0'], @@ -227,67 +261,86 @@ '2': ['-O2'], '3': ['-O3'], 's': ['-O3'] - } + } # type: T.Dict[str, T.List[str]] cuda_debug_args = {False: [], - True: ['-g']} + True: ['-g']} # type: T.Dict[bool, T.List[str]] clike_debug_args = {False: [], - True: ['-g']} + True: ['-g']} # type: T.Dict[bool, T.List[str]] -base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', True), - 'b_lto': coredata.UserBooleanOption('Use link time optimization', False), - 'b_sanitize': coredata.UserComboOption('Code sanitizer to use', - ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'], - 'none'), - 'b_lundef': coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True), - 'b_asneeded': coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True), - 'b_pgo': coredata.UserComboOption('Use profile guided optimization', - ['off', 'generate', 'use'], - 'off'), - 'b_coverage': coredata.UserBooleanOption('Enable coverage tracking.', - False), - 'b_colorout': coredata.UserComboOption('Use colored output', - ['auto', 'always', 'never'], - 'always'), - 'b_ndebug': coredata.UserComboOption('Disable asserts', - ['true', 'false', 'if-release'], 'false'), - 'b_staticpic': coredata.UserBooleanOption('Build static libraries as position independent', - True), - 'b_pie': coredata.UserBooleanOption('Build executables as position independent', - False), - 'b_bitcode': coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)', - False), - 'b_vscrt': coredata.UserComboOption('VS run-time library type to use.', - ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype'], - 'from_buildtype'), - } +base_options: 'KeyedOptionDictType' = { + OptionKey('b_pch'): coredata.UserBooleanOption('Use precompiled headers', True), + OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), + OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), + OptionKey('b_lto_threads'): coredata.UserIntegerOption('Use multiple threads for Link Time Optimization', (None, None, 0)), + OptionKey('b_lto_mode'): coredata.UserComboOption('Select between different LTO modes.', + ['default', 'thin'], + 'default'), + OptionKey('b_sanitize'): coredata.UserComboOption('Code sanitizer to use', + ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'], + 'none'), + OptionKey('b_lundef'): coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True), + OptionKey('b_asneeded'): coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True), + OptionKey('b_pgo'): coredata.UserComboOption('Use profile guided optimization', + ['off', 'generate', 'use'], + 'off'), + OptionKey('b_coverage'): coredata.UserBooleanOption('Enable coverage tracking.', False), + OptionKey('b_colorout'): coredata.UserComboOption('Use colored output', + ['auto', 'always', 'never'], + 'always'), + OptionKey('b_ndebug'): coredata.UserComboOption('Disable asserts', ['true', 'false', 'if-release'], 'false'), + OptionKey('b_staticpic'): coredata.UserBooleanOption('Build static libraries as position independent', True), + OptionKey('b_pie'): coredata.UserBooleanOption('Build executables as position independent', False), + OptionKey('b_bitcode'): coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)', False), + OptionKey('b_vscrt'): coredata.UserComboOption('VS run-time library type to use.', + ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype', 'static_from_buildtype'], + 'from_buildtype'), +} -def option_enabled(boptions, options, option): +def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType', + option: OptionKey) -> bool: try: if option not in boptions: return False - return options[option].value + ret = options[option].value + assert isinstance(ret, bool), 'must return bool' # could also be str + return ret except KeyError: return False -def get_base_compile_args(options, compiler): - args = [] + +def get_option_value(options: 'KeyedOptionDictType', opt: OptionKey, fallback: '_T') -> '_T': + """Get the value of an option, or the fallback value.""" + try: + v: '_T' = options[opt].value + except KeyError: + return fallback + + assert isinstance(v, type(fallback)), f'Should have {type(fallback)!r} but was {type(v)!r}' + # Mypy doesn't understand that the above assert ensures that v is type _T + return v + + +def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler') -> T.List[str]: + args = [] # type T.List[str] try: - if options['b_lto'].value: - args.extend(compiler.get_lto_compile_args()) + if options[OptionKey('b_lto')].value: + args.extend(compiler.get_lto_compile_args( + threads=get_option_value(options, OptionKey('b_lto_threads'), 0), + mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'))) except KeyError: pass try: - args += compiler.get_colorout_args(options['b_colorout'].value) + args += compiler.get_colorout_args(options[OptionKey('b_colorout')].value) except KeyError: pass try: - args += compiler.sanitizer_compile_args(options['b_sanitize'].value) + args += compiler.sanitizer_compile_args(options[OptionKey('b_sanitize')].value) except KeyError: pass try: - pgo_val = options['b_pgo'].value + pgo_val = options[OptionKey('b_pgo')].value if pgo_val == 'generate': args.extend(compiler.get_profile_generate_args()) elif pgo_val == 'use': @@ -295,23 +348,23 @@ except KeyError: pass try: - if options['b_coverage'].value: + if options[OptionKey('b_coverage')].value: args += compiler.get_coverage_args() except KeyError: pass try: - if (options['b_ndebug'].value == 'true' or - (options['b_ndebug'].value == 'if-release' and - options['buildtype'].value in {'release', 'plain'})): - args += ['-DNDEBUG'] + if (options[OptionKey('b_ndebug')].value == 'true' or + (options[OptionKey('b_ndebug')].value == 'if-release' and + options[OptionKey('buildtype')].value in {'release', 'plain'})): + args += compiler.get_disable_assert_args() except KeyError: pass # This does not need a try...except - if option_enabled(compiler.base_options, options, 'b_bitcode'): + if option_enabled(compiler.base_options, options, OptionKey('b_bitcode')): args.append('-fembed-bitcode') try: - crt_val = options['b_vscrt'].value - buildtype = options['buildtype'].value + crt_val = options[OptionKey('b_vscrt')].value + buildtype = options[OptionKey('buildtype')].value try: args += compiler.get_crt_compile_args(crt_val, buildtype) except AttributeError: @@ -320,19 +373,22 @@ pass return args -def get_base_link_args(options, linker, is_shared_module): - args = [] +def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler', + is_shared_module: bool) -> T.List[str]: + args = [] # type: T.List[str] try: - if options['b_lto'].value: - args.extend(linker.get_lto_link_args()) + if options[OptionKey('b_lto')].value: + args.extend(linker.get_lto_link_args( + threads=get_option_value(options, OptionKey('b_lto_threads'), 0), + mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'))) except KeyError: pass try: - args += linker.sanitizer_link_args(options['b_sanitize'].value) + args += linker.sanitizer_link_args(options[OptionKey('b_sanitize')].value) except KeyError: pass try: - pgo_val = options['b_pgo'].value + pgo_val = options[OptionKey('b_pgo')].value if pgo_val == 'generate': args.extend(linker.get_profile_generate_args()) elif pgo_val == 'use': @@ -340,13 +396,13 @@ except KeyError: pass try: - if options['b_coverage'].value: + if options[OptionKey('b_coverage')].value: args += linker.get_coverage_link_args() except KeyError: pass - as_needed = option_enabled(linker.base_options, options, 'b_asneeded') - bitcode = option_enabled(linker.base_options, options, 'b_bitcode') + as_needed = option_enabled(linker.base_options, options, OptionKey('b_asneeded')) + bitcode = option_enabled(linker.base_options, options, OptionKey('b_bitcode')) # Shared modules cannot be built with bitcode_bundle because # -bitcode_bundle is incompatible with -undefined and -bundle if bitcode and not is_shared_module: @@ -355,18 +411,19 @@ # -Wl,-dead_strip_dylibs is incompatible with bitcode args.extend(linker.get_asneeded_args()) - # Apple's ld (the only one that supports bitcode) does not like any - # -undefined arguments at all, so don't pass these when using bitcode + # Apple's ld (the only one that supports bitcode) does not like -undefined + # arguments or -headerpad_max_install_names when bitcode is enabled if not bitcode: + args.extend(linker.headerpad_args()) if (not is_shared_module and - option_enabled(linker.base_options, options, 'b_lundef')): + option_enabled(linker.base_options, options, OptionKey('b_lundef'))): args.extend(linker.no_undefined_link_args()) else: args.extend(linker.get_allow_undefined_link_args()) try: - crt_val = options['b_vscrt'].value - buildtype = options['buildtype'].value + crt_val = options[OptionKey('b_vscrt')].value + buildtype = options[OptionKey('buildtype')].value try: args += linker.get_crt_link_args(crt_val, buildtype) except AttributeError: @@ -379,318 +436,58 @@ class CrossNoRunException(MesonException): pass -class RunResult: - def __init__(self, compiled, returncode=999, stdout='UNDEFINED', stderr='UNDEFINED'): +class RunResult(HoldableObject): + def __init__(self, compiled: bool, returncode: int = 999, + stdout: str = 'UNDEFINED', stderr: str = 'UNDEFINED'): self.compiled = compiled self.returncode = returncode self.stdout = stdout self.stderr = stderr -class CompilerArgs(collections.abc.MutableSequence): - ''' - List-like class that manages a list of compiler arguments. Should be used - while constructing compiler arguments from various sources. Can be - operated with ordinary lists, so this does not need to be used - everywhere. - - All arguments must be inserted and stored in GCC-style (-lfoo, -Idir, etc) - and can converted to the native type of each compiler by using the - .to_native() method to which you must pass an instance of the compiler or - the compiler class. - - New arguments added to this class (either with .append(), .extend(), or +=) - are added in a way that ensures that they override previous arguments. - For example: - - >>> a = ['-Lfoo', '-lbar'] - >>> a += ['-Lpho', '-lbaz'] - >>> print(a) - ['-Lpho', '-Lfoo', '-lbar', '-lbaz'] - - Arguments will also be de-duped if they can be de-duped safely. - - Note that because of all this, this class is not commutative and does not - preserve the order of arguments if it is safe to not. For example: - >>> ['-Ifoo', '-Ibar'] + ['-Ifez', '-Ibaz', '-Werror'] - ['-Ifez', '-Ibaz', '-Ifoo', '-Ibar', '-Werror'] - >>> ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifoo', '-Ibar'] - ['-Ifoo', '-Ibar', '-Ifez', '-Ibaz', '-Werror'] - - ''' - # NOTE: currently this class is only for C-like compilers, but it can be - # extended to other languages easily. Just move the following to the - # compiler class and initialize when self.compiler is set. - - # Arg prefixes that override by prepending instead of appending - prepend_prefixes = ('-I', '-L') - # Arg prefixes and args that must be de-duped by returning 2 - dedup2_prefixes = ('-I', '-isystem', '-L', '-D', '-U') - dedup2_suffixes = () - dedup2_args = () - # Arg prefixes and args that must be de-duped by returning 1 - # - # NOTE: not thorough. A list of potential corner cases can be found in - # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 - dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic') - dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') - # Match a .so of the form path/to/libfoo.so.0.1.0 - # Only UNIX shared libraries require this. Others have a fixed extension. - dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') - dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread') - # In generate_link() we add external libs without de-dup, but we must - # *always* de-dup these because they're special arguments to the linker - always_dedup_args = tuple('-l' + lib for lib in unixy_compiler_internal_libs) - - def __init__(self, compiler: T.Union['Compiler', StaticLinker], - iterable: T.Optional[T.Iterable[str]] = None): - self.compiler = compiler - self.__container = list(iterable) if iterable is not None else [] # type: T.List[str] - - @T.overload # noqa: F811 - def __getitem__(self, index: int) -> str: # noqa: F811 - pass - - @T.overload # noqa: F811 - def __getitem__(self, index: slice) -> T.List[str]: # noqa: F811 - pass - - def __getitem__(self, index): # noqa: F811 - return self.__container[index] - - @T.overload # noqa: F811 - def __setitem__(self, index: int, value: str) -> None: # noqa: F811 - pass - - @T.overload # noqa: F811 - def __setitem__(self, index: slice, value: T.List[str]) -> None: # noqa: F811 - pass - def __setitem__(self, index, value) -> None: # noqa: F811 - self.__container[index] = value +class CompileResult(HoldableObject): - def __delitem__(self, index: T.Union[int, slice]) -> None: - del self.__container[index] + """The result of Compiler.compiles (and friends).""" - def __len__(self) -> int: - return len(self.__container) - - def insert(self, index: int, value: str) -> None: - self.__container.insert(index, value) - - def copy(self) -> 'CompilerArgs': - return CompilerArgs(self.compiler, self.__container.copy()) - - @classmethod - def _can_dedup(cls, arg): - ''' - Returns whether the argument can be safely de-duped. This is dependent - on three things: - - a) Whether an argument can be 'overridden' by a later argument. For - example, -DFOO defines FOO and -UFOO undefines FOO. In this case, we - can safely remove the previous occurrence and add a new one. The same - is true for include paths and library paths with -I and -L. For - these we return `2`. See `dedup2_prefixes` and `dedup2_args`. - b) Arguments that once specified cannot be undone, such as `-c` or - `-pipe`. New instances of these can be completely skipped. For these - we return `1`. See `dedup1_prefixes` and `dedup1_args`. - c) Whether it matters where or how many times on the command-line - a particular argument is present. This can matter for symbol - resolution in static or shared libraries, so we cannot de-dup or - reorder them. For these we return `0`. This is the default. - - In addition to these, we handle library arguments specially. - With GNU ld, we surround library arguments with -Wl,--start/end-group - to recursively search for symbols in the libraries. This is not needed - with other linkers. - ''' - # A standalone argument must never be deduplicated because it is - # defined by what comes _after_ it. Thus dedupping this: - # -D FOO -D BAR - # would yield either - # -D FOO BAR - # or - # FOO -D BAR - # both of which are invalid. - if arg in cls.dedup2_prefixes: - return 0 - if arg in cls.dedup2_args or \ - arg.startswith(cls.dedup2_prefixes) or \ - arg.endswith(cls.dedup2_suffixes): - return 2 - if arg in cls.dedup1_args or \ - arg.startswith(cls.dedup1_prefixes) or \ - arg.endswith(cls.dedup1_suffixes) or \ - re.search(cls.dedup1_regex, arg): - return 1 - return 0 - - @classmethod - def _should_prepend(cls, arg): - if arg.startswith(cls.prepend_prefixes): - return True - return False - - def to_native(self, copy: bool = False) -> T.List[str]: - # Check if we need to add --start/end-group for circular dependencies - # between static libraries, and for recursively searching for symbols - # needed by static libraries that are provided by object files or - # shared libraries. - if copy: - new = self.copy() - else: - new = self - # This covers all ld.bfd, ld.gold, ld.gold, and xild on Linux, which - # all act like (or are) gnu ld - # TODO: this could probably be added to the DynamicLinker instead - if (isinstance(self.compiler, Compiler) and - self.compiler.linker is not None and - isinstance(self.compiler.linker, (GnuLikeDynamicLinkerMixin, SolarisDynamicLinker))): - group_start = -1 - group_end = -1 - for i, each in enumerate(new): - if not each.startswith(('-Wl,-l', '-l')) and not each.endswith('.a') and \ - not soregex.match(each): - continue - group_end = i - if group_start < 0: - # First occurrence of a library - group_start = i - if group_start >= 0: - # Last occurrence of a library - new.insert(group_end + 1, '-Wl,--end-group') - new.insert(group_start, '-Wl,--start-group') - # Remove system/default include paths added with -isystem - if hasattr(self.compiler, 'get_default_include_dirs'): - default_dirs = self.compiler.get_default_include_dirs() - bad_idx_list = [] # type: T.List[int] - for i, each in enumerate(new): - # Remove the -isystem and the path if the path is a default path - if (each == '-isystem' and - i < (len(new) - 1) and - new[i + 1] in default_dirs): - bad_idx_list += [i, i + 1] - elif each.startswith('-isystem=') and each[9:] in default_dirs: - bad_idx_list += [i] - elif each.startswith('-isystem') and each[8:] in default_dirs: - bad_idx_list += [i] - for i in reversed(bad_idx_list): - new.pop(i) - return self.compiler.unix_args_to_native(new.__container) - - def append_direct(self, arg: str) -> None: - ''' - Append the specified argument without any reordering or de-dup except - for absolute paths to libraries, etc, which can always be de-duped - safely. - ''' - if os.path.isabs(arg): - self.append(arg) - else: - self.__container.append(arg) - - def extend_direct(self, iterable: T.Iterable[str]) -> None: - ''' - Extend using the elements in the specified iterable without any - reordering or de-dup except for absolute paths where the order of - include search directories is not relevant - ''' - for elem in iterable: - self.append_direct(elem) - - def extend_preserving_lflags(self, iterable: T.Iterable[str]) -> None: - normal_flags = [] - lflags = [] - for i in iterable: - if i not in self.always_dedup_args and (i.startswith('-l') or i.startswith('-L')): - lflags.append(i) - else: - normal_flags.append(i) - self.extend(normal_flags) - self.extend_direct(lflags) - - def __add__(self, args: T.Iterable[str]) -> 'CompilerArgs': - new = self.copy() - new += args - return new - - def __iadd__(self, args: T.Iterable[str]) -> 'CompilerArgs': - ''' - Add two CompilerArgs while taking into account overriding of arguments - and while preserving the order of arguments as much as possible - ''' - pre = [] # type: T.List[str] - post = [] # type: T.List[str] - if not isinstance(args, collections.abc.Iterable): - raise TypeError('can only concatenate Iterable[str] (not "{}") to CompilerArgs'.format(args)) - for arg in args: - # If the argument can be de-duped, do it either by removing the - # previous occurrence of it and adding a new one, or not adding the - # new occurrence. - dedup = self._can_dedup(arg) - if dedup == 1: - # Argument already exists and adding a new instance is useless - if arg in self or arg in pre or arg in post: - continue - if dedup == 2: - # Remove all previous occurrences of the arg and add it anew - if arg in self: - self.remove(arg) - if arg in pre: - pre.remove(arg) - if arg in post: - post.remove(arg) - if self._should_prepend(arg): - pre.append(arg) - else: - post.append(arg) - # Insert at the beginning - self[:0] = pre - # Append to the end - self.__container += post - return self - - def __radd__(self, args: T.Iterable[str]): - new = CompilerArgs(self.compiler, args) - new += self - return new - - def __eq__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]: - # Only allow equality checks against other CompilerArgs and lists instances - if isinstance(other, CompilerArgs): - return self.compiler == other.compiler and self.__container == other.__container - elif isinstance(other, list): - return self.__container == other - return NotImplemented - - def append(self, arg: str) -> None: - self.__iadd__([arg]) - - def extend(self, args: T.Iterable[str]) -> None: - self.__iadd__(args) + def __init__(self, stdo: T.Optional[str] = None, stde: T.Optional[str] = None, + args: T.Optional[T.List[str]] = None, + returncode: int = 999, pid: int = -1, + text_mode: bool = True, + input_name: T.Optional[str] = None, + output_name: T.Optional[str] = None, + command: T.Optional[T.List[str]] = None, cached: bool = False): + self.stdout = stdo + self.stderr = stde + self.input_name = input_name + self.output_name = output_name + self.command = command or [] + self.args = args or [] + self.cached = cached + self.returncode = returncode + self.pid = pid + self.text_mode = text_mode - def __repr__(self) -> str: - return 'CompilerArgs({!r}, {!r})'.format(self.compiler, self.__container) -class Compiler: +class Compiler(HoldableObject, metaclass=abc.ABCMeta): # Libraries to ignore in find_library() since they are provided by the # compiler or the C library. Currently only used for MSVC. - ignore_libs = () + ignore_libs = [] # type: T.List[str] # Libraries that are internal compiler implementations, and must not be # manually searched. - internal_libs = () + internal_libs = [] # type: T.List[str] LINKER_PREFIX = None # type: T.Union[None, str, T.List[str]] INVOKES_LINKER = True - def __init__(self, exelist, version, for_machine: MachineChoice, info: 'MachineInfo', - linker: T.Optional['DynamicLinker'] = None, **kwargs): - if isinstance(exelist, str): - self.exelist = [exelist] - elif isinstance(exelist, list): - self.exelist = exelist - else: - raise TypeError('Unknown argument to Compiler') + language: str + id: str + warn_args: T.Dict[str, T.List[str]] + + def __init__(self, exelist: T.List[str], version: str, + for_machine: MachineChoice, info: 'MachineInfo', + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, is_cross: bool = False): + self.exelist = exelist # In case it's been overridden by a child class already if not hasattr(self, 'file_suffixes'): self.file_suffixes = lang_suffixes[self.language] @@ -698,27 +495,26 @@ self.can_compile_suffixes = set(self.file_suffixes) self.default_suffix = self.file_suffixes[0] self.version = version - if 'full_version' in kwargs: - self.full_version = kwargs['full_version'] - else: - self.full_version = None + self.full_version = full_version self.for_machine = for_machine - self.base_options = [] + self.base_options: T.Set[OptionKey] = set() self.linker = linker self.info = info + self.is_cross = is_cross - def __repr__(self): + def __repr__(self) -> str: repr_str = "<{0}: v{1} `{2}`>" return repr_str.format(self.__class__.__name__, self.version, ' '.join(self.exelist)) - def can_compile(self, src) -> bool: - if hasattr(src, 'fname'): + @lru_cache(maxsize=None) + def can_compile(self, src: 'mesonlib.FileOrString') -> bool: + if isinstance(src, mesonlib.File): src = src.fname - suffix = os.path.splitext(src)[1].lower() - if suffix and suffix[1:] in self.can_compile_suffixes: - return True - return False + suffix = os.path.splitext(src)[1] + if suffix != '.C': + suffix = suffix.lower() + return bool(suffix) and suffix[1:] in self.can_compile_suffixes def get_id(self) -> str: return self.id @@ -748,42 +544,59 @@ def get_default_suffix(self) -> str: return self.default_suffix - def get_define(self, dname, prefix, env, extra_args, dependencies) -> T.Tuple[str, bool]: + def get_define(self, dname: str, prefix: str, env: 'Environment', + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.List['Dependency'], + disable_cache: bool = False) -> T.Tuple[str, bool]: raise EnvironmentException('%s does not support get_define ' % self.get_id()) - def compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies) -> int: + def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], + guess: T.Optional[int], prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']]) -> int: raise EnvironmentException('%s does not support compute_int ' % self.get_id()) - def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id()) - def has_members(self, typename, membernames, prefix, env, *, - extra_args=None, dependencies=None) -> T.Tuple[bool, bool]: + def has_members(self, typename: str, membernames: T.List[str], + prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: raise EnvironmentException('%s does not support has_member(s) ' % self.get_id()) - def has_type(self, typename, prefix, env, extra_args, *, - dependencies=None) -> T.Tuple[bool, bool]: + def has_type(self, typename: str, prefix: str, env: 'Environment', + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], *, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: raise EnvironmentException('%s does not support has_type ' % self.get_id()) - def symbols_have_underscore_prefix(self, env) -> bool: + def symbols_have_underscore_prefix(self, env: 'Environment') -> bool: raise EnvironmentException('%s does not support symbols_have_underscore_prefix ' % self.get_id()) - def get_exelist(self): - return self.exelist[:] + def get_exelist(self) -> T.List[str]: + return self.exelist.copy() def get_linker_exelist(self) -> T.List[str]: return self.linker.get_exelist() + @abc.abstractmethod + def get_output_args(self, outputname: str) -> T.List[str]: + pass + def get_linker_output_args(self, outputname: str) -> T.List[str]: return self.linker.get_output_args(outputname) - def get_builtin_define(self, *args, **kwargs): + def get_linker_search_args(self, dirname: str) -> T.List[str]: + return self.linker.get_search_args(dirname) + + def get_builtin_define(self, define: str) -> T.Optional[str]: raise EnvironmentException('%s does not support get_builtin_define.' % self.id) - def has_builtin_define(self, *args, **kwargs): + def has_builtin_define(self, define: str) -> bool: raise EnvironmentException('%s does not support has_builtin_define.' % self.id) - def get_always_args(self): + def get_always_args(self) -> T.List[str]: return [] def can_linker_accept_rsp(self) -> bool: @@ -792,78 +605,114 @@ """ return self.linker.get_accepts_rsp() - def get_linker_always_args(self): + def get_linker_always_args(self) -> T.List[str]: return self.linker.get_always_args() - def get_linker_lib_prefix(self): + def get_linker_lib_prefix(self) -> str: return self.linker.get_lib_prefix() - def gen_import_library_args(self, implibname): + def gen_import_library_args(self, implibname: str) -> T.List[str]: """ Used only on Windows for libraries that need an import library. This currently means C, C++, Fortran. """ return [] - def get_linker_args_from_envvars(self) -> T.List[str]: - return self.linker.get_args_from_envvars() - - def get_options(self) -> T.Dict[str, coredata.UserOption]: + def get_options(self) -> 'KeyedOptionDictType': return {} - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] - def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]: + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return self.linker.get_option_args(options) - def check_header(self, *args, **kwargs) -> T.Tuple[bool, bool]: + def check_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + """Check that header is usable. + + Returns a two item tuple of bools. The first bool is whether the + check succeeded, the second is whether the result was cached (True) + or run fresh (False). + """ raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) - def has_header(self, *args, **kwargs) -> T.Tuple[bool, bool]: + def has_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + disable_cache: bool = False) -> T.Tuple[bool, bool]: + """Check that header is exists. + + This check will return true if the file exists, even if it contains: + + ```c + # error "You thought you could use this, LOLZ!" + ``` + + Use check_header if your header only works in some cases. + + Returns a two item tuple of bools. The first bool is whether the + check succeeded, the second is whether the result was cached (True) + or run fresh (False). + """ raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) - def has_header_symbol(self, *args, **kwargs) -> T.Tuple[bool, bool]: + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) - def compiles(self, *args, **kwargs) -> T.Tuple[bool, bool]: - raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language()) - - def links(self, *args, **kwargs) -> T.Tuple[bool, bool]: - raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language()) - - def run(self, *args, **kwargs) -> RunResult: + def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) - def sizeof(self, *args, **kwargs) -> int: + def sizeof(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language()) - def alignment(self, *args, **kwargs) -> int: + def alignment(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) - def has_function(self, *args, **kwargs) -> T.Tuple[bool, bool]: + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + """See if a function exists. + + Returns a two item tuple of bools. The first bool is whether the + check succeeded, the second is whether the result was cached (True) + or run fresh (False). + """ raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) - @classmethod - def unix_args_to_native(cls, args): + def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: "Always returns a copy that can be independently mutated" - return args[:] + return args.copy() @classmethod def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]: "Always returns a copy that can be independently mutated" - return args[:] + return args.copy() - def find_library(self, *args, **kwargs): - raise EnvironmentException('Language {} does not support library finding.'.format(self.get_display_language())) + def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: + raise EnvironmentException(f'Language {self.get_display_language()} does not support library finding.') - def get_library_dirs(self, *args, **kwargs): - return () + def get_library_naming(self, env: 'Environment', libtype: LibType, + strict: bool = False) -> T.Optional[T.Tuple[str, ...]]: + raise EnvironmentException( + 'Language {} does not support get_library_naming.'.format( + self.get_display_language())) - def get_program_dirs(self, *args, **kwargs): + def get_program_dirs(self, env: 'Environment') -> T.List[str]: return [] - def has_multi_arguments(self, args, env) -> T.Tuple[bool, bool]: + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: raise EnvironmentException( 'Language {} does not support has_multi_arguments.'.format( self.get_display_language())) @@ -871,7 +720,8 @@ def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: return self.linker.has_multi_arguments(args, env) - def _get_compile_output(self, dirname, mode): + def _get_compile_output(self, dirname: str, mode: str) -> str: + # TODO: mode should really be an enum # In pre-processor mode, the output is sent to stdout and discarded if mode == 'preprocess': return None @@ -883,112 +733,128 @@ suffix = 'obj' return os.path.join(dirname, 'output.' + suffix) - def get_compiler_args_for_mode(self, mode): - args = [] + def get_compiler_args_for_mode(self, mode: CompileCheckMode) -> T.List[str]: + # TODO: mode should really be an enum + args = [] # type: T.List[str] args += self.get_always_args() - if mode == 'compile': + if mode is CompileCheckMode.COMPILE: args += self.get_compile_only_args() - if mode == 'preprocess': + elif mode is CompileCheckMode.PREPROCESS: args += self.get_preprocess_only_args() + else: + assert mode is CompileCheckMode.LINK return args + def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs: + """Return an appropriate CompilerArgs instance for this class.""" + return CompilerArgs(self, args) + @contextlib.contextmanager - def compile(self, code, extra_args=None, *, mode='link', want_output=False, temp_dir=None): + def compile(self, code: 'mesonlib.FileOrString', + extra_args: T.Union[None, CompilerArgs, T.List[str]] = None, + *, mode: str = 'link', want_output: bool = False, + temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]: + # TODO: there isn't really any reason for this to be a contextmanager if extra_args is None: extra_args = [] - try: - with tempfile.TemporaryDirectory(dir=temp_dir) as tmpdirname: - if isinstance(code, str): - srcname = os.path.join(tmpdirname, - 'testfile.' + self.default_suffix) - with open(srcname, 'w') as ofile: - ofile.write(code) - elif isinstance(code, mesonlib.File): - srcname = code.fname - - # Construct the compiler command-line - commands = CompilerArgs(self) - commands.append(srcname) - # Preprocess mode outputs to stdout, so no output args - if mode != 'preprocess': - output = self._get_compile_output(tmpdirname, mode) - commands += self.get_output_args(output) - commands.extend(self.get_compiler_args_for_mode(mode)) - # extra_args must be last because it could contain '/link' to - # pass args to VisualStudio's linker. In that case everything - # in the command line after '/link' is given to the linker. + + with TemporaryDirectoryWinProof(dir=temp_dir) as tmpdirname: + no_ccache = False + if isinstance(code, str): + srcname = os.path.join(tmpdirname, + 'testfile.' + self.default_suffix) + with open(srcname, 'w', encoding='utf-8') as ofile: + ofile.write(code) + # ccache would result in a cache miss + no_ccache = True + contents = code + else: + srcname = code.fname + if not is_object(code.fname): + with open(code.fname, encoding='utf-8') as f: + contents = f.read() + else: + contents = '' + + # Construct the compiler command-line + commands = self.compiler_args() + commands.append(srcname) + + # Preprocess mode outputs to stdout, so no output args + output = self._get_compile_output(tmpdirname, mode) + if mode != 'preprocess': + commands += self.get_output_args(output) + commands.extend(self.get_compiler_args_for_mode(CompileCheckMode(mode))) + + # extra_args must be last because it could contain '/link' to + # pass args to VisualStudio's linker. In that case everything + # in the command line after '/link' is given to the linker. + if extra_args: commands += extra_args - # Generate full command-line with the exelist - commands = self.get_exelist() + commands.to_native() - mlog.debug('Running compile:') - mlog.debug('Working directory: ', tmpdirname) - mlog.debug('Command line: ', ' '.join(commands), '\n') - mlog.debug('Code:\n', code) - os_env = os.environ.copy() - os_env['LC_ALL'] = 'C' - p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname, env=os_env) - mlog.debug('Compiler stdout:\n', p.stdo) - mlog.debug('Compiler stderr:\n', p.stde) - p.commands = commands - p.input_name = srcname - if want_output: - p.output_name = output - p.cached = False # Make sure that the cached attribute always exists - yield p - except OSError: - # On Windows antivirus programs and the like hold on to files so - # they can't be deleted. There's not much to do in this case. Also, - # catch OSError because the directory is then no longer empty. - pass + # Generate full command-line with the exelist + command_list = self.get_exelist() + commands.to_native() + mlog.debug('Running compile:') + mlog.debug('Working directory: ', tmpdirname) + mlog.debug('Command line: ', ' '.join(command_list), '\n') + mlog.debug('Code:\n', contents) + os_env = os.environ.copy() + os_env['LC_ALL'] = 'C' + if no_ccache: + os_env['CCACHE_DISABLE'] = '1' + p, stdo, stde = Popen_safe(command_list, cwd=tmpdirname, env=os_env) + mlog.debug('Compiler stdout:\n', stdo) + mlog.debug('Compiler stderr:\n', stde) + + result = CompileResult(stdo, stde, list(commands), p.returncode, p.pid, input_name=srcname) + if want_output: + result.output_name = output + yield result @contextlib.contextmanager - def cached_compile(self, code, cdata: coredata.CoreData, *, extra_args=None, mode: str = 'link', temp_dir=None): - assert(isinstance(cdata, coredata.CoreData)) + def cached_compile(self, code: 'mesonlib.FileOrString', cdata: coredata.CoreData, *, + extra_args: T.Union[None, T.List[str], CompilerArgs] = None, + mode: str = 'link', + temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]: + # TODO: There's isn't really any reason for this to be a context manager # Calculate the key - textra_args = tuple(extra_args) if extra_args is not None else None - key = (tuple(self.exelist), self.version, code, textra_args, mode) + textra_args = tuple(extra_args) if extra_args is not None else tuple() # type: T.Tuple[str, ...] + key = (tuple(self.exelist), self.version, code, textra_args, mode) # type: coredata.CompilerCheckCacheKey - # Check if not cached - if key not in cdata.compiler_check_cache: + # Check if not cached, and generate, otherwise get from the cache + if key in cdata.compiler_check_cache: + p = cdata.compiler_check_cache[key] # type: CompileResult + p.cached = True + mlog.debug('Using cached compile:') + mlog.debug('Cached command line: ', ' '.join(p.command), '\n') + mlog.debug('Code:\n', code) + mlog.debug('Cached compiler stdout:\n', p.stdout) + mlog.debug('Cached compiler stderr:\n', p.stderr) + yield p + else: with self.compile(code, extra_args=extra_args, mode=mode, want_output=False, temp_dir=temp_dir) as p: - # Remove all attributes except the following - # This way the object can be serialized - tokeep = ['args', 'commands', 'input_name', 'output_name', - 'pid', 'returncode', 'stdo', 'stde', 'text_mode'] - todel = [x for x in vars(p).keys() if x not in tokeep] - for i in todel: - delattr(p, i) - p.cached = False cdata.compiler_check_cache[key] = p yield p - return - - # Return cached - p = cdata.compiler_check_cache[key] - p.cached = True - mlog.debug('Using cached compile:') - mlog.debug('Cached command line: ', ' '.join(p.commands), '\n') - mlog.debug('Code:\n', code) - mlog.debug('Cached compiler stdout:\n', p.stdo) - mlog.debug('Cached compiler stderr:\n', p.stde) - yield p - def get_colorout_args(self, colortype): + def get_colorout_args(self, colortype: str) -> T.List[str]: + # TODO: colortype can probably be an emum return [] # Some compilers (msvc) write debug info to a separate file. # These args specify where it should be written. - def get_compile_debugfile_args(self, rel_obj, **kwargs): + def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]: return [] + def get_link_debugfile_name(self, targetfile: str) -> str: + return self.linker.get_debugfile_name(targetfile) + def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: return self.linker.get_debugfile_args(targetfile) def get_std_shared_lib_link_args(self) -> T.List[str]: return self.linker.get_std_shared_lib_args() - def get_std_shared_module_link_args(self, options: 'OptionDictType') -> T.List[str]: + def get_std_shared_module_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return self.linker.get_std_shared_module_args(options) def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: @@ -1000,49 +866,64 @@ def no_undefined_link_args(self) -> T.List[str]: return self.linker.no_undefined_args() - # Compiler arguments needed to enable the given instruction set. - # May be [] meaning nothing needed or None meaning the given set - # is not supported. - def get_instruction_set_args(self, instruction_set): + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + """Compiler arguments needed to enable the given instruction set. + + Return type ay be an empty list meaning nothing needed or None + meaning the given set is not supported. + """ return None def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, - rpath_paths: str, build_rpath: str, - install_rpath: str) -> T.List[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) - def thread_flags(self, env): + def thread_flags(self, env: 'Environment') -> T.List[str]: return [] - def openmp_flags(self): + def thread_link_flags(self, env: 'Environment') -> T.List[str]: + return self.linker.thread_flags(env) + + def openmp_flags(self) -> T.List[str]: raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language()) - def language_stdlib_only_link_flags(self): - return [] + def openmp_link_flags(self) -> T.List[str]: + return self.openmp_flags() - def gnu_symbol_visibility_args(self, vistype): + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: return [] - def get_gui_app_args(self, value): + def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]: return [] - def has_func_attribute(self, name, env): + def get_gui_app_args(self, value: bool) -> T.List[str]: + # Only used on Windows + return self.linker.get_gui_app_args(value) + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + # By default the dynamic linker is going to return an empty + # array in case it either doesn't support Windows subsystems + # or does not target Windows + return self.linker.get_win_subsystem_args(value) + + def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]: raise EnvironmentException( - 'Language {} does not support function attributes.'.format(self.get_display_language())) + f'Language {self.get_display_language()} does not support function attributes.') - def get_pic_args(self): + def get_pic_args(self) -> T.List[str]: m = 'Language {} does not support position-independent code' raise EnvironmentException(m.format(self.get_display_language())) - def get_pie_args(self): + def get_pie_args(self) -> T.List[str]: m = 'Language {} does not support position-independent executable' raise EnvironmentException(m.format(self.get_display_language())) def get_pie_link_args(self) -> T.List[str]: return self.linker.get_pie_args() - def get_argument_syntax(self): + def get_argument_syntax(self) -> str: """Returns the argument family type. Compilers fall into families if they try to emulate the command line @@ -1053,22 +934,19 @@ """ return 'other' - def get_profile_generate_args(self): + def get_profile_generate_args(self) -> T.List[str]: raise EnvironmentException( '%s does not support get_profile_generate_args ' % self.get_id()) - def get_profile_use_args(self): + def get_profile_use_args(self) -> T.List[str]: raise EnvironmentException( '%s does not support get_profile_use_args ' % self.get_id()) - def get_undefined_link_args(self) -> T.List[str]: - return self.linker.get_undefined_link_args() - - def remove_linkerlike_args(self, args): + def remove_linkerlike_args(self, args: T.List[str]) -> T.List[str]: rm_exact = ('-headerpad_max_install_names',) rm_prefixes = ('-Wl,', '-L',) - rm_next = ('-L',) - ret = [] + rm_next = ('-L', '-framework',) + ret = [] # T.List[str] iargs = iter(args) for arg in iargs: # Remove this argument @@ -1085,10 +963,10 @@ ret.append(arg) return ret - def get_lto_compile_args(self) -> T.List[str]: + def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: return [] - def get_lto_link_args(self) -> T.List[str]: + def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: return self.linker.get_lto_args() def sanitizer_compile_args(self, value: str) -> T.List[str]: @@ -1100,30 +978,32 @@ def get_asneeded_args(self) -> T.List[str]: return self.linker.get_asneeded_args() + def headerpad_args(self) -> T.List[str]: + return self.linker.headerpad_args() + def bitcode_args(self) -> T.List[str]: return self.linker.bitcode_args() - def get_linker_debug_crt_args(self) -> T.List[str]: - return self.linker.get_debug_crt_args() + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not implement get_buildtype_args') def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: return self.linker.get_buildtype_args(buildtype) def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, suffix: str, soversion: str, - darwin_versions: T.Tuple[str, str], - is_shared_module: bool) -> T.List[str]: + darwin_versions: T.Tuple[str, str]) -> T.List[str]: return self.linker.get_soname_args( env, prefix, shlib_name, suffix, soversion, - darwin_versions, is_shared_module) + darwin_versions) - def get_target_link_args(self, target): + def get_target_link_args(self, target: 'BuildTarget') -> T.List[str]: return target.link_args - def get_dependency_compile_args(self, dep): + def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: return dep.get_compile_args() - def get_dependency_link_args(self, dep): + def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]: return dep.get_link_args() @classmethod @@ -1132,105 +1012,296 @@ """ return [] + def get_coverage_args(self) -> T.List[str]: + return [] -def get_largefile_args(compiler): - ''' - Enable transparent large-file-support for 32-bit UNIX systems - ''' - if not (compiler.info.is_windows() or compiler.info.is_darwin()): - # Enable large-file support unconditionally on all platforms other - # than macOS and Windows. macOS is now 64-bit-only so it doesn't - # need anything special, and Windows doesn't have automatic LFS. - # You must use the 64-bit counterparts explicitly. - # glibc, musl, and uclibc, and all BSD libcs support this. On Android, - # support for transparent LFS is available depending on the version of - # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs - # https://code.google.com/p/android/issues/detail?id=64613 - # - # If this breaks your code, fix it! It's been 20+ years! - return ['-D_FILE_OFFSET_BITS=64'] - # We don't enable -D_LARGEFILE64_SOURCE since that enables - # transitionary features and must be enabled by programs that use - # those features explicitly. - return [] - - -def get_args_from_envvars(lang: str, use_linker_args: bool) -> T.Tuple[T.List[str], T.List[str]]: - """ - Returns a tuple of (compile_flags, link_flags) for the specified language - from the inherited environment - """ - def log_var(var, val: T.Optional[str]): - if val: - mlog.log('Appending {} from environment: {!r}'.format(var, val)) + def get_coverage_link_args(self) -> T.List[str]: + return self.linker.get_coverage_args() + + def get_disable_assert_args(self) -> T.List[str]: + return [] + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + raise EnvironmentException('This compiler does not support Windows CRT selection') + + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + raise EnvironmentException('This compiler does not support Windows CRT selection') + + def get_compile_only_args(self) -> T.List[str]: + return [] + + def get_preprocess_only_args(self) -> T.List[str]: + raise EnvironmentException('This compiler does not have a preprocessor') + + def get_default_include_dirs(self) -> T.List[str]: + # TODO: This is a candidate for returning an immutable list + return [] + + def get_largefile_args(self) -> T.List[str]: + '''Enable transparent large-file-support for 32-bit UNIX systems''' + if not (self.get_argument_syntax() == 'msvc' or self.info.is_darwin()): + # Enable large-file support unconditionally on all platforms other + # than macOS and MSVC. macOS is now 64-bit-only so it doesn't + # need anything special, and MSVC doesn't have automatic LFS. + # You must use the 64-bit counterparts explicitly. + # glibc, musl, and uclibc, and all BSD libcs support this. On Android, + # support for transparent LFS is available depending on the version of + # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs + # https://code.google.com/p/android/issues/detail?id=64613 + # + # If this breaks your code, fix it! It's been 20+ years! + return ['-D_FILE_OFFSET_BITS=64'] + # We don't enable -D_LARGEFILE64_SOURCE since that enables + # transitionary features and must be enabled by programs that use + # those features explicitly. + return [] + + def get_library_dirs(self, env: 'Environment', + elf_class: T.Optional[int] = None) -> T.List[str]: + return [] + + def get_return_value(self, + fname: str, + rtype: str, + prefix: str, + env: 'Environment', + extra_args: T.Optional[T.List[str]], + dependencies: T.Optional[T.List['Dependency']]) -> T.Union[str, int]: + raise EnvironmentException(f'{self.id} does not support get_return_value') + + def find_framework(self, + name: str, + env: 'Environment', + extra_dirs: T.List[str], + allow_system: bool = True) -> T.Optional[T.List[str]]: + raise EnvironmentException(f'{self.id} does not support find_framework') + + def find_framework_paths(self, env: 'Environment') -> T.List[str]: + raise EnvironmentException(f'{self.id} does not support find_framework_paths') + + def attribute_check_func(self, name: str) -> str: + raise EnvironmentException(f'{self.id} does not support attribute checks') + + def get_pch_suffix(self) -> str: + raise EnvironmentException(f'{self.id} does not support pre compiled headers') + + def get_pch_name(self, name: str) -> str: + raise EnvironmentException(f'{self.id} does not support pre compiled headers') + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not support pre compiled headers') + + def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not support function attributes') + + def name_string(self) -> str: + return ' '.join(self.exelist) + + @abc.abstractmethod + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + """Check that this compiler actually works. + + This should provide a simple compile/link test. Something as simple as: + ```python + main(): return 0 + ``` + is good enough here. + """ + + def split_shlib_to_parts(self, fname: str) -> T.Tuple[T.Optional[str], str]: + return None, fname + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return [] + + def get_std_exe_link_args(self) -> T.List[str]: + # TODO: is this a linker property? + return [] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + return [] + + def depfile_for_object(self, objfile: str) -> str: + return objfile + '.' + self.get_depfile_suffix() + + def get_depfile_suffix(self) -> str: + raise EnvironmentException(f'{self.id} does not implement get_depfile_suffix') + + def get_no_stdinc_args(self) -> T.List[str]: + """Arguments to turn off default inclusion of standard libraries.""" + return [] + + def get_warn_args(self, level: str) -> T.List[str]: + return [] + + def get_werror_args(self) -> T.List[str]: + return [] + + @abc.abstractmethod + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + pass + + def get_module_incdir_args(self) -> T.Tuple[str, ...]: + raise EnvironmentException(f'{self.id} does not implement get_module_incdir_args') + + def get_module_outdir_args(self, path: str) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not implement get_module_outdir_args') + + def module_name_to_filename(self, module_name: str) -> str: + raise EnvironmentException(f'{self.id} does not implement module_name_to_filename') + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + """Arguments to pass the compiler and/or linker for checks. + + The default implementation turns off optimizations. + + Examples of things that go here: + - extra arguments for error checking + - Arguments required to make the compiler exit with a non-zero status + when something is wrong. + """ + return self.get_no_optimization_args() + + def get_no_optimization_args(self) -> T.List[str]: + """Arguments to the compiler to turn off all optimizations.""" + return [] + + def build_wrapper_args(self, env: 'Environment', + extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']], + mode: CompileCheckMode = CompileCheckMode.COMPILE) -> CompilerArgs: + """Arguments to pass the build_wrapper helper. + + This generally needs to be set on a per-language baises. It provides + a hook for languages to handle dependencies and extra args. The base + implementation handles the most common cases, namely adding the + check_arguments, unwrapping dependencies, and appending extra args. + """ + if callable(extra_args): + extra_args = extra_args(mode) + if extra_args is None: + extra_args = [] + if dependencies is None: + dependencies = [] + + # Collect compiler arguments + args = self.compiler_args(self.get_compiler_check_args(mode)) + for d in dependencies: + # Add compile flags needed by dependencies + args += d.get_compile_args() + if mode is CompileCheckMode.LINK: + # Add link flags needed to find dependencies + args += d.get_link_args() + + if mode is CompileCheckMode.COMPILE: + # Add DFLAGS from the env + args += env.coredata.get_external_args(self.for_machine, self.language) + elif mode is CompileCheckMode.LINK: + # Add LDFLAGS from the env + args += env.coredata.get_external_link_args(self.for_machine, self.language) + # extra_args must override all other arguments, so we add them last + args += extra_args + return args + + @contextlib.contextmanager + def _build_wrapper(self, code: 'mesonlib.FileOrString', env: 'Environment', + extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + mode: str = 'compile', want_output: bool = False, + disable_cache: bool = False, + temp_dir: str = None) -> T.Iterator[T.Optional[CompileResult]]: + """Helper for getting a cacched value when possible. + + This method isn't meant to be called externally, it's mean to be + wrapped by other methods like compiles() and links(). + """ + args = self.build_wrapper_args(env, extra_args, dependencies, CompileCheckMode(mode)) + if disable_cache or want_output: + with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) as r: + yield r else: - mlog.debug('No {} in the environment, not changing global flags.'.format(var)) + with self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir) as r: + yield r + + def compiles(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + mode: str = 'compile', + disable_cache: bool = False) -> T.Tuple[bool, bool]: + with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: + return p.returncode == 0, p.cached + + def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + compiler: T.Optional['Compiler'] = None, + extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + mode: str = 'compile', + disable_cache: bool = False) -> T.Tuple[bool, bool]: + if compiler: + with compiler._build_wrapper(code, env, dependencies=dependencies, want_output=True) as r: + objfile = mesonlib.File.from_absolute_file(r.output_name) + return self.compiles(objfile, env, extra_args=extra_args, + dependencies=dependencies, mode='link', disable_cache=True) + + return self.compiles(code, env, extra_args=extra_args, + dependencies=dependencies, mode='link', disable_cache=disable_cache) + + def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: + """Used by D for extra language features.""" + # TODO: using a TypeDict here would improve this + raise EnvironmentException(f'{self.id} does not implement get_feature_args') + + def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not know how to do prelinking.') + + def rsp_file_syntax(self) -> 'RSPFileSyntax': + """The format of the RSP file that this compiler supports. + + If `self.can_linker_accept_rsp()` returns True, then this needs to + be implemented + """ + return self.linker.rsp_file_syntax() + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + """Arguments required for a debug build.""" + return [] + + def get_no_warn_args(self) -> T.List[str]: + """Arguments to completely disable warnings.""" + return [] - if lang not in cflags_mapping: - return [], [] - compile_flags = [] # type: T.List[str] - link_flags = [] # type: T.List[str] +def get_global_options(lang: str, + comp: T.Type[Compiler], + for_machine: MachineChoice, + env: 'Environment') -> 'KeyedOptionDictType': + """Retrieve options that apply to all compilers for a given language.""" + description = f'Extra arguments passed to the {lang}' + argkey = OptionKey('args', lang=lang, machine=for_machine) + largkey = argkey.evolve('link_args') + envkey = argkey.evolve('env_args') + + comp_key = argkey if argkey in env.options else envkey + + comp_options = env.options.get(comp_key, []) + link_options = env.options.get(largkey, []) + + cargs = coredata.UserArrayOption( + description + ' compiler', + comp_options, split_args=True, user_input=True, allow_dups=True) + + largs = coredata.UserArrayOption( + description + ' linker', + link_options, split_args=True, user_input=True, allow_dups=True) + + if comp.INVOKES_LINKER and comp_key == envkey: + # If the compiler acts as a linker driver, and we're using the + # environment variable flags for both the compiler and linker + # arguments, then put the compiler flags in the linker flags as well. + # This is how autotools works, and the env vars freature is for + # autotools compatibility. + largs.extend_value(comp_options) - env_compile_flags = os.environ.get(cflags_mapping[lang]) - log_var(cflags_mapping[lang], env_compile_flags) - if env_compile_flags is not None: - compile_flags += split_args(env_compile_flags) - - # Link flags (same for all languages) - if lang in languages_using_ldflags: - # This is duplicated between the linkers, but I'm not sure how else - # to handle this - env_link_flags = split_args(os.environ.get('LDFLAGS', '')) - else: - env_link_flags = [] - log_var('LDFLAGS', env_link_flags) - link_flags += env_link_flags - if use_linker_args: - # When the compiler is used as a wrapper around the linker (such as - # with GCC and Clang), the compile flags can be needed while linking - # too. This is also what Autotools does. However, we don't want to do - # this when the linker is stand-alone such as with MSVC C/C++, etc. - link_flags = compile_flags + link_flags - - # Pre-processor flags for certain languages - if lang in {'c', 'cpp', 'objc', 'objcpp'}: - env_preproc_flags = os.environ.get('CPPFLAGS') - log_var('CPPFLAGS', env_preproc_flags) - if env_preproc_flags is not None: - compile_flags += split_args(env_preproc_flags) - - return compile_flags, link_flags - - -def get_global_options(lang: str, comp: T.Type[Compiler], - properties: Properties) -> T.Dict[str, coredata.UserOption]: - """Retreive options that apply to all compilers for a given language.""" - description = 'Extra arguments passed to the {}'.format(lang) - opts = { - lang + '_args': coredata.UserArrayOption( - description + ' compiler', - [], split_args=True, user_input=True, allow_dups=True), - lang + '_link_args': coredata.UserArrayOption( - description + ' linker', - [], split_args=True, user_input=True, allow_dups=True), - } - - if properties.fallback: - # Get from env vars. - # XXX: True here is a hack - compile_args, link_args = get_args_from_envvars(lang, comp.INVOKES_LINKER) - else: - compile_args = [] - link_args = [] - - for k, o in opts.items(): - if k in properties: - # Get from configuration files. - o.set_value(properties[k]) - elif k == lang + '_args': - o.set_value(compile_args) - elif k == lang + '_link_args': - o.set_value(link_args) + opts: 'KeyedOptionDictType' = {argkey: cargs, largkey: largs} return opts diff -Nru meson-0.53.2/mesonbuild/compilers/cpp.py meson-0.61.2/mesonbuild/compilers/cpp.py --- meson-0.53.2/mesonbuild/compilers/cpp.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/cpp.py 2022-01-17 10:50:45.000000000 +0000 @@ -19,31 +19,40 @@ from .. import coredata from .. import mlog -from ..mesonlib import MesonException, MachineChoice, version_compare +from ..mesonlib import MesonException, MachineChoice, version_compare, OptionKey from .compilers import ( gnu_winlibs, msvc_winlibs, Compiler, + CompileCheckMode, ) from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES from .mixins.clike import CLikeCompiler from .mixins.ccrx import CcrxCompiler +from .mixins.c2000 import C2000Compiler from .mixins.arm import ArmCompiler, ArmclangCompiler -from .mixins.visualstudio import VisualStudioLikeCompiler +from .mixins.visualstudio import MSVCCompiler, ClangClCompiler from .mixins.gnu import GnuCompiler from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler from .mixins.clang import ClangCompiler from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler -from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin from .mixins.emscripten import EmscriptenMixin if T.TYPE_CHECKING: + from ..coredata import KeyedOptionDictType + from ..dependencies import Dependency from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers import DynamicLinker + from ..programs import ExternalProgram + CompilerMixinBase = CLikeCompiler +else: + CompilerMixinBase = object -def non_msvc_eh_options(eh, args): +def non_msvc_eh_options(eh: str, args: T.List[str]) -> None: if eh == 'none': args.append('-fno-exceptions') elif eh == 's' or eh == 'c': @@ -53,38 +62,45 @@ class CPPCompiler(CLikeCompiler, Compiler): @classmethod - def attribute_check_func(cls, name): + def attribute_check_func(cls, name: str) -> str: try: return CXX_FUNC_ATTRIBUTES.get(name, C_FUNC_ATTRIBUTES[name]) except KeyError: - raise MesonException('Unknown function attribute "{}"'.format(name)) + raise MesonException(f'Unknown function attribute "{name}"') language = 'cpp' - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrap: T.Optional[str] = None, **kwargs): + 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): # If a child ObjCPP class has already set it, don't set it ourselves - Compiler.__init__(self, exelist, version, for_machine, info, **kwargs) - CLikeCompiler.__init__(self, is_cross, exe_wrap) + Compiler.__init__(self, exelist, version, for_machine, info, + is_cross=is_cross, linker=linker, + full_version=full_version) + CLikeCompiler.__init__(self, exe_wrapper) @staticmethod - def get_display_language(): + def get_display_language() -> str: return 'C++' - def get_no_stdinc_args(self): + def get_no_stdinc_args(self) -> T.List[str]: return ['-nostdinc++'] - def sanity_check(self, work_dir, environment): + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: code = 'class breakCCompiler;int main(void) { return 0; }\n' - return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code) + return self._sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code) - def get_compiler_check_args(self): + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: # -fpermissive allows non-conforming code to compile which is necessary # for many C++ checks. Particularly, the has_header_symbol check is # too strict without this and always fails. - return super().get_compiler_check_args() + ['-fpermissive'] + return super().get_compiler_check_args(mode) + ['-fpermissive'] - def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None): + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: # Check if it's a C-like symbol found, cached = super().has_header_symbol(hname, symbol, prefix, env, extra_args=extra_args, @@ -94,17 +110,16 @@ # Check if it's a class or a template if extra_args is None: extra_args = [] - fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} - t = '''{prefix} - #include <{header}> + t = f'''{prefix} + #include <{hname}> using {symbol}; int main(void) {{ return 0; }}''' - return self.compiles(t.format(**fargs), env, extra_args=extra_args, + return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies) - def _test_cpp_std_arg(self, cpp_std_value): + def _test_cpp_std_arg(self, cpp_std_value: str) -> bool: # Test whether the compiler understands a -std=XY argument - assert(cpp_std_value.startswith('-std=')) + assert cpp_std_value.startswith('-std=') # This test does not use has_multi_arguments() for two reasons: # 1. has_multi_arguments() requires an env argument, which the compiler @@ -114,14 +129,14 @@ CPP_TEST = 'int i = static_cast(0);' with self.compile(CPP_TEST, extra_args=[cpp_std_value], mode='compile') as p: if p.returncode == 0: - mlog.debug('Compiler accepts {}:'.format(cpp_std_value), 'YES') + mlog.debug(f'Compiler accepts {cpp_std_value}:', 'YES') return True else: - mlog.debug('Compiler accepts {}:'.format(cpp_std_value), 'NO') + mlog.debug(f'Compiler accepts {cpp_std_value}:', 'NO') return False @functools.lru_cache() - def _find_best_cpp_std(self, cpp_std): + def _find_best_cpp_std(self, cpp_std: str) -> str: # The initial version mapping approach to make falling back # from '-std=c++14' to '-std=c++1y' was too brittle. For instance, # Apple's Clang uses a different versioning scheme to upstream LLVM, @@ -134,11 +149,13 @@ 'c++14': 'c++1y', 'gnu++14': 'gnu++1y', 'c++17': 'c++1z', - 'gnu++17': 'gnu++1z' + 'gnu++17': 'gnu++1z', + 'c++20': 'c++2a', + 'gnu++20': 'gnu++2a', } # 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']) if cpp_std not in CPP_FALLBACKS: # 'c++03' and 'c++98' don't have fallback types @@ -149,80 +166,142 @@ if self._test_cpp_std_arg(cpp_std_value): return cpp_std_value - raise MesonException('C++ Compiler does not support -std={}'.format(cpp_std)) + raise MesonException(f'C++ Compiler does not support -std={cpp_std}') + + def get_options(self) -> 'KeyedOptionDictType': + opts = super().get_options() + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key: coredata.UserComboOption( + 'C++ language standard to use', + ['none'], + 'none', + ), + }) + return opts class ClangCPPCompiler(ClangCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, **kwargs) - ClangCompiler.__init__(self) + info, exe_wrapper, linker=linker, full_version=full_version) + ClangCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], '1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CPPCompiler.get_options(self) - opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default'), - 'cpp_rtti': coredata.UserBooleanOption('Enable RTTI', True), - 'cpp_std': coredata.UserComboOption('C++ language standard to use', - ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', - 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'], - 'none')}) + key = OptionKey('key', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), + }) + opts[key.evolve('std')].choices = [ + 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', + 'c++2a', 'c++20', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', + 'gnu++2a', 'gnu++20', + ] + if self.info.is_windows() or self.info.is_cygwin(): + opts.update({ + key.evolve('winlibs'): coredata.UserArrayOption( + 'Standard Win libraries to link against', + gnu_winlibs, + ), + }) return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['cpp_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': args.append(self._find_best_cpp_std(std.value)) - non_msvc_eh_options(options['cpp_eh'].value, args) + non_msvc_eh_options(options[key.evolve('eh')].value, args) - if not options['cpp_rtti'].value: + if not options[key.evolve('rtti')].value: args.append('-fno-rtti') return args - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + if self.info.is_windows() or self.info.is_cygwin(): + # without a typedict mypy can't understand this. + key = OptionKey('winlibs', machine=self.for_machine, lang=self.language) + libs = options[key].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs return [] - def language_stdlib_only_link_flags(self): - return ['-lstdc++'] + 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 + # be passed to a different compiler with a different set of default + # search paths, such as when using Clang for C/C++ and gfortran for + # fortran, + search_dir = self._get_search_dirs(env) + search_dirs: T.List[str] = [] + if search_dir is not None: + for d in search_dir.split()[-1][len('libraries: ='):].split(':'): + search_dirs.append(f'-L{d}') + return search_dirs + ['-lstdc++'] class AppleClangCPPCompiler(ClangCPPCompiler): - - pass - - -class EmscriptenCPPCompiler(LinkerEnvVarsMixin, EmscriptenMixin, BasicLinkerIsCompilerMixin, ClangCPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs): + 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 + # be passed to a different compiler with a different set of default + # search paths, such as when using Clang for C/C++ and gfortran for + # fortran, + search_dir = self._get_search_dirs(env) + search_dirs: T.List[str] = [] + if search_dir is not None: + for d in search_dir.split()[-1][len('libraries: ='):].split(':'): + search_dirs.append(f'-L{d}') + return search_dirs + ['-lc++'] + + +class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): if not is_cross: raise MesonException('Emscripten compiler can only be used for cross compilation.') - ClangCPPCompiler.__init__(self, exelist=exelist, version=version, - for_machine=for_machine, is_cross=is_cross, - info=info, exe_wrapper=exe_wrapper, **kwargs) + 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): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['cpp_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': args.append(self._find_best_cpp_std(std.value)) return args class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): - CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) + 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): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) ArmclangCompiler.__init__(self) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], @@ -230,35 +309,45 @@ '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CPPCompiler.get_options(self) - opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default'), - 'cpp_std': coredata.UserComboOption('C++ language standard to use', - ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', - 'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17'], - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + }) + opts[key].choices = [ + 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'gnu++98', + 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', + ] return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['cpp_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': args.append('-std=' + std.value) - non_msvc_eh_options(options['cpp_eh'].value, args) + non_msvc_eh_options(options[key.evolve('eh')].value, args) return args - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] class GnuCPPCompiler(GnuCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap, defines, **kwargs): - CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrap, **kwargs) + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) GnuCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], @@ -266,84 +355,149 @@ '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': + key = OptionKey('std', machine=self.for_machine, lang=self.language) opts = CPPCompiler.get_options(self) - opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default'), - 'cpp_rtti': coredata.UserBooleanOption('Enable RTTI', True), - 'cpp_std': coredata.UserComboOption('C++ language standard to use', - ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', - 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'], - 'none'), - 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode', - False)}) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), + key.evolve('debugstl'): coredata.UserBooleanOption( + 'STL debug mode', + False, + ) + }) + opts[key].choices = [ + 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', + 'c++2a', 'c++20', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', + 'gnu++1z', 'gnu++2a', 'gnu++20', + ] if self.info.is_windows() or self.info.is_cygwin(): opts.update({ - 'cpp_winlibs': coredata.UserArrayOption('Standard Win libraries to link against', - gnu_winlibs), }) + key.evolve('winlibs'): coredata.UserArrayOption( + 'Standard Win libraries to link against', + gnu_winlibs, + ), + }) return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['cpp_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': args.append(self._find_best_cpp_std(std.value)) - non_msvc_eh_options(options['cpp_eh'].value, args) + non_msvc_eh_options(options[key.evolve('eh')].value, args) - if not options['cpp_rtti'].value: + if not options[key.evolve('rtti')].value: args.append('-fno-rtti') - if options['cpp_debugstl'].value: + if options[key.evolve('debugstl')].value: args.append('-D_GLIBCXX_DEBUG=1') return args - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: if self.info.is_windows() or self.info.is_cygwin(): - return options['cpp_winlibs'].value[:] + # without a typedict mypy can't understand this. + key = OptionKey('winlibs', machine=self.for_machine, lang=self.language) + libs = options[key].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs return [] - def get_pch_use_args(self, pch_dir, header): + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: return ['-fpch-preprocess', '-include', os.path.basename(header)] - def language_stdlib_only_link_flags(self): + 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 + # be passed to a different compiler with a different set of default + # search paths, such as when using Clang for C/C++ and gfortran for + # fortran, + search_dir = self._get_search_dirs(env) + search_dirs: T.List[str] = [] + if search_dir is not None: + for d in search_dir.split()[-1][len('libraries: ='):].split(':'): + search_dirs.append(f'-L{d}') return ['-lstdc++'] class PGICPPCompiler(PGICompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): - CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs) + 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): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) PGICompiler.__init__(self) -class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - defines=None, **kwargs): - GnuCPPCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, defines, - **kwargs) +class NvidiaHPC_CPPCompiler(PGICompiler, CPPCompiler): + 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): + CPPCompiler.__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 ElbrusCPPCompiler(ElbrusCompiler, CPPCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) ElbrusCompiler.__init__(self) - # It does not support c++/gnu++ 17 and 1z, but still does support 0x, 1y, and gnu++98. - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CPPCompiler.get_options(self) - opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default'), - 'cpp_std': coredata.UserComboOption('C++ language standard to use', - ['none', 'c++98', 'c++03', 'c++0x', 'c++11', 'c++14', 'c++1y', - 'gnu++98', 'gnu++03', 'gnu++0x', 'gnu++11', 'gnu++14', 'gnu++1y'], - 'none'), - 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode', - False)}) + + cpp_stds = ['none', 'c++98', 'gnu++98'] + if version_compare(self.version, '>=1.20.00'): + cpp_stds += ['c++03', 'c++0x', 'c++11', 'gnu++03', 'gnu++0x', 'gnu++11'] + if version_compare(self.version, '>=1.21.00') and version_compare(self.version, '<1.22.00'): + cpp_stds += ['c++14', 'gnu++14', 'c++1y', 'gnu++1y'] + if version_compare(self.version, '>=1.22.00'): + cpp_stds += ['c++14', 'gnu++14'] + if version_compare(self.version, '>=1.23.00'): + cpp_stds += ['c++1y', 'gnu++1y'] + if version_compare(self.version, '>=1.24.00'): + cpp_stds += ['c++1z', 'c++17', 'gnu++1z', 'gnu++17'] + if version_compare(self.version, '>=1.25.00'): + cpp_stds += ['c++2a', 'gnu++2a'] + if version_compare(self.version, '>=1.26.00'): + cpp_stds += ['c++20', 'gnu++20'] + + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('debugstl'): coredata.UserBooleanOption( + 'STL debug mode', + False, + ), + }) + opts[key].choices = cpp_stds return opts # Elbrus C++ compiler does not have lchmod, but there is only linker warning, not compiler error. # So we should explicitly fail at this case. - def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None): + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: if funcname == 'lchmod': return False, False else: @@ -352,24 +506,27 @@ dependencies=dependencies) # Elbrus C++ compiler does not support RTTI, so don't check for it. - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['cpp_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': args.append(self._find_best_cpp_std(std.value)) - non_msvc_eh_options(options['cpp_eh'].value, args) + non_msvc_eh_options(options[key.evolve('eh')].value, args) - if options['cpp_debugstl'].value: + if options[key.evolve('debugstl')].value: args.append('-D_GLIBCXX_DEBUG=1') return args class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap, **kwargs): + 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): CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrap, **kwargs) + info, exe_wrapper, linker=linker, full_version=full_version) IntelGnuLikeCompiler.__init__(self) self.lang_header = 'c++-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', @@ -379,7 +536,7 @@ '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CPPCompiler.get_options(self) # Every Unix compiler under the sun seems to accept -std=c++03, # with the exception of ICC. Instead of preventing the user from @@ -393,39 +550,46 @@ c_stds += ['c++17'] if version_compare(self.version, '>=17.0.0'): g_stds += ['gnu++14'] - opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default'), - 'cpp_rtti': coredata.UserBooleanOption('Enable RTTI', True), - 'cpp_std': coredata.UserComboOption('C++ language standard to use', - ['none'] + c_stds + g_stds, - 'none'), - 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode', - False)}) + if version_compare(self.version, '>=19.1.0'): + c_stds += ['c++2a'] + g_stds += ['gnu++2a'] + + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), + key.evolve('debugstl'): coredata.UserBooleanOption('STL debug mode', False), + }) + opts[key].choices = ['none'] + c_stds + g_stds return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['cpp_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': remap_cpp03 = { 'c++03': 'c++98', 'gnu++03': 'gnu++98' } args.append('-std=' + remap_cpp03.get(std.value, std.value)) - if options['cpp_eh'].value == 'none': + if options[key.evolve('eh')].value == 'none': args.append('-fno-exceptions') - if not options['cpp_rtti'].value: + if not options[key.evolve('rtti')].value: args.append('-fno-rtti') - if options['cpp_debugstl'].value: + if options[key.evolve('debugstl')].value: args.append('-D_GLIBCXX_DEBUG=1') return args - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] -class VisualStudioLikeCPPCompilerMixin: +class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase): """Mixin for C++ specific method overrides in MSVC-like compilers.""" @@ -434,32 +598,42 @@ 'vc++11': (True, 11), 'vc++14': (True, 14), 'vc++17': (True, 17), + 'vc++20': (True, 20), 'vc++latest': (True, "latest"), 'c++11': (False, 11), 'c++14': (False, 14), 'c++17': (False, 17), + 'c++20': (False, 20), 'c++latest': (False, "latest"), } - def get_option_link_args(self, options): - return options['cpp_winlibs'].value[:] - - def _get_options_impl(self, opts, cpp_stds: T.List[str]): - opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default'), - 'cpp_rtti': coredata.UserBooleanOption('Enable RTTI', True), - 'cpp_std': coredata.UserComboOption('C++ language standard to use', - cpp_stds, - 'none'), - 'cpp_winlibs': coredata.UserArrayOption('Windows libs to link against.', - msvc_winlibs)}) + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + # need a typeddict for this + key = OptionKey('winlibs', machine=self.for_machine, lang=self.language) + return T.cast(T.List[str], options[key].value[:]) + + def _get_options_impl(self, opts: 'KeyedOptionDictType', cpp_stds: T.List[str]) -> 'KeyedOptionDictType': + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), + key.evolve('winlibs'): coredata.UserArrayOption( + 'Windows libs to link against.', + msvc_winlibs, + ), + }) + opts[key.evolve('std')].choices = cpp_stds return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) - eh = options['cpp_eh'] + eh = options[key.evolve('eh')] if eh.value == 'default': args.append('/EHsc') elif eh.value == 'none': @@ -467,59 +641,63 @@ else: args.append('/EH' + eh.value) - if not options['cpp_rtti'].value: + if not options[key.evolve('rtti')].value: args.append('/GR-') - permissive, ver = self.VC_VERSION_MAP[options['cpp_std'].value] + permissive, ver = self.VC_VERSION_MAP[options[key].value] if ver is not None: - args.append('/std:c++{}'.format(ver)) + args.append(f'/std:c++{ver}') if not permissive: args.append('/permissive-') return args - def get_compiler_check_args(self): + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: # XXX: this is a hack because so much GnuLike stuff is in the base CPPCompiler class. - return CLikeCompiler.get_compiler_check_args(self) + return Compiler.get_compiler_check_args(self, mode) -class CPP11AsCPP14Mixin: +class CPP11AsCPP14Mixin(CompilerMixinBase): """Mixin class for VisualStudio and ClangCl to replace C++11 std with C++14. This is a limitation of Clang and MSVC that ICL doesn't share. """ - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: # Note: there is no explicit flag for supporting C++11; we attempt to do the best we can # which means setting the C++ standard version to C++14, in compilers that support it # (i.e., after VS2015U3) # if one is using anything before that point, one cannot set the standard. - if options['cpp_std'].value in {'vc++11', 'c++11'}: + key = OptionKey('std', machine=self.for_machine, lang=self.language) + if options[key].value in {'vc++11', 'c++11'}: mlog.warning(self.id, 'does not support C++11;', 'attempting best effort; setting the standard to C++14', once=True) # Don't mutate anything we're going to change, we need to use # deepcopy since we're messing with members, and we can't simply # copy the members because the option proxy doesn't support it. options = copy.deepcopy(options) - if options['cpp_std'].value == 'vc++11': - options['cpp_std'].value = 'vc++14' + if options[key].value == 'vc++11': + options[key].value = 'vc++14' else: - options['cpp_std'].value = 'c++14' + options[key].value = 'c++14' return super().get_option_compile_args(options) -class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross: bool, info: 'MachineInfo', exe_wrap, target, **kwargs): - CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrap, **kwargs) - VisualStudioLikeCompiler.__init__(self, target) - self.base_options = ['b_pch', 'b_vscrt'] # FIXME add lto, pgo and the like +class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, MSVCCompiler, CPPCompiler): + 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, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + 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): + def get_options(self) -> 'KeyedOptionDictType': cpp_stds = ['none', 'c++11', 'vc++11'] # Visual Studio 2015 and later if version_compare(self.version, '>=19'): @@ -527,13 +705,16 @@ # Visual Studio 2017 and later if version_compare(self.version, '>=19.11'): cpp_stds.extend(['vc++14', 'c++17', 'vc++17']) + if version_compare(self.version, '>=19.29'): + cpp_stds.extend(['c++20', 'vc++20']) return self._get_options_impl(super().get_options(), cpp_stds) - def get_option_compile_args(self, options): - if options['cpp_std'].value != 'none' and version_compare(self.version, '<19.00.24210'): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + key = OptionKey('std', machine=self.for_machine, lang=self.language) + if options[key].value != 'none' and version_compare(self.version, '<19.00.24210'): mlog.warning('This version of MSVC does not support cpp_std arguments') options = copy.copy(options) - options['cpp_std'].value = 'none' + options[key].value = 'none' args = super().get_option_compile_args(options) @@ -545,85 +726,133 @@ del args[i] return args -class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap, target, **kwargs): +class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, ClangClCompiler, CPPCompiler): + 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, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrap, **kwargs) - VisualStudioLikeCompiler.__init__(self, target) + info, exe_wrapper, linker=linker, full_version=full_version) + ClangClCompiler.__init__(self, target) self.id = 'clang-cl' - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest'] return self._get_options_impl(super().get_options(), cpp_stds) class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap, target, **kwargs): + 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, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrap, **kwargs) + info, exe_wrapper, linker=linker, full_version=full_version) IntelVisualStudioLikeCompiler.__init__(self, target) - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': # This has only been tested with version 19.0, cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest'] return self._get_options_impl(super().get_options(), cpp_stds) + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + # XXX: this is a hack because so much GnuLike stuff is in the base CPPCompiler class. + return IntelVisualStudioLikeCompiler.get_compiler_check_args(self, mode) + class ArmCPPCompiler(ArmCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap=None, **kwargs): + 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): CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrap, **kwargs) + info, exe_wrapper, linker=linker, full_version=full_version) ArmCompiler.__init__(self) - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CPPCompiler.get_options(self) - opts.update({'cpp_std': coredata.UserComboOption('C++ language standard to use', - ['none', 'c++03', 'c++11'], - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c++03', 'c++11'] return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['cpp_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value == 'c++11': args.append('--cpp11') elif std.value == 'c++03': args.append('--cpp') return args - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] - def get_compiler_check_args(self): + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: return [] class CcrxCPPCompiler(CcrxCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap=None, **kwargs): + 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): CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrap, **kwargs) + info, exe_wrapper, linker=linker, full_version=full_version) CcrxCompiler.__init__(self) # Override CCompiler.get_always_args - def get_always_args(self): + def get_always_args(self) -> T.List[str]: return ['-nologo', '-lang=cpp'] - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] - def get_compile_only_args(self): + def get_compile_only_args(self) -> T.List[str]: return [] - def get_output_args(self, target): - return ['-output=obj=%s' % target] + def get_output_args(self, target: str) -> T.List[str]: + return [f'-output=obj={target}'] - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] - def get_compiler_check_args(self): + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: return [] + +class C2000CPPCompiler(C2000Compiler, CPPCompiler): + 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): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + C2000Compiler.__init__(self) + + def get_options(self) -> 'KeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c++03'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('--' + std.value) + return args + + def get_no_optimization_args(self) -> T.List[str]: + return ['-Ooff'] + + def get_output_args(self, target: str) -> T.List[str]: + return [f'--output_file={target}'] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + return ['--include_path=' + path] diff -Nru meson-0.53.2/mesonbuild/compilers/c.py meson-0.61.2/mesonbuild/compilers/c.py --- meson-0.53.2/mesonbuild/compilers/c.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/c.py 2022-01-17 10:50:45.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright 2012-2017 The Meson development team +# Copyright 2012-2020 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,18 +16,21 @@ import typing as T from .. import coredata -from ..mesonlib import MachineChoice, MesonException, mlog, version_compare +from .. import mlog +from ..mesonlib import MachineChoice, MesonException, version_compare, OptionKey from .c_function_attributes import C_FUNC_ATTRIBUTES from .mixins.clike import CLikeCompiler from .mixins.ccrx import CcrxCompiler +from .mixins.xc16 import Xc16Compiler +from .mixins.compcert import CompCertCompiler +from .mixins.c2000 import C2000Compiler from .mixins.arm import ArmCompiler, ArmclangCompiler -from .mixins.visualstudio import VisualStudioLikeCompiler +from .mixins.visualstudio import MSVCCompiler, ClangClCompiler from .mixins.gnu import GnuCompiler from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler from .mixins.clang import ClangCompiler from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler -from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin from .mixins.emscripten import EmscriptenMixin from .compilers import ( gnu_winlibs, @@ -36,34 +39,50 @@ ) if T.TYPE_CHECKING: + from ..coredata import KeyedOptionDictType + from ..dependencies import Dependency from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers import DynamicLinker + from ..programs import ExternalProgram + from .compilers import CompileCheckMode + + CompilerMixinBase = Compiler +else: + CompilerMixinBase = object class CCompiler(CLikeCompiler, Compiler): @staticmethod - def attribute_check_func(name): + def attribute_check_func(name: str) -> str: try: return C_FUNC_ATTRIBUTES[name] except KeyError: - raise MesonException('Unknown function attribute "{}"'.format(name)) + raise MesonException(f'Unknown function attribute "{name}"') language = 'c' - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional[str] = None, **kwargs): + 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): # If a child ObjC or CPP class has already set it, don't set it ourselves - Compiler.__init__(self, exelist, version, for_machine, info, **kwargs) - CLikeCompiler.__init__(self, is_cross, exe_wrapper) + Compiler.__init__(self, exelist, version, for_machine, info, + is_cross=is_cross, full_version=full_version, linker=linker) + CLikeCompiler.__init__(self, exe_wrapper) - def get_no_stdinc_args(self): + def get_no_stdinc_args(self) -> T.List[str]: return ['-nostdinc'] - def sanity_check(self, work_dir, environment): + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: code = 'int main(void) { int class=0; return class; }\n' - return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) + return self._sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) - def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None): + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} t = '''{prefix} #include <{header}> @@ -77,24 +96,32 @@ return self.compiles(t.format(**fargs), env, extra_args=extra_args, dependencies=dependencies) + def get_options(self) -> 'KeyedOptionDictType': + opts = super().get_options() + opts.update({ + OptionKey('std', machine=self.for_machine, lang=self.language): coredata.UserComboOption( + 'C language standard to use', + ['none'], + 'none', + ) + }) + return opts + + +class _ClangCStds(CompilerMixinBase): -class ClangCCompiler(ClangCompiler, CCompiler): + """Mixin class for clang based compilers for setting C standards. + + This is used by both ClangCCompiler and ClangClCompiler, as they share + the same versions + """ _C17_VERSION = '>=6.0.0' _C18_VERSION = '>=8.0.0' + _C2X_VERSION = '>=9.0.0' - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): - CCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs) - ClangCompiler.__init__(self) - default_warn_args = ['-Wall', '-Winvalid-pch'] - self.warn_args = {'0': [], - '1': default_warn_args, - '2': default_warn_args + ['-Wextra'], - '3': default_warn_args + ['-Wextra', '-Wpedantic']} - - def get_options(self): - opts = CCompiler.get_options(self) + def get_options(self) -> 'KeyedOptionDictType': + opts = super().get_options() c_stds = ['c89', 'c99', 'c11'] g_stds = ['gnu89', 'gnu99', 'gnu11'] # https://releases.llvm.org/6.0.0/tools/clang/docs/ReleaseNotes.html @@ -105,19 +132,54 @@ if version_compare(self.version, self._C18_VERSION): c_stds += ['c18'] g_stds += ['gnu18'] - opts.update({'c_std': coredata.UserComboOption('C language standard to use', - ['none'] + c_stds + g_stds, - 'none')}) + if version_compare(self.version, self._C2X_VERSION): + c_stds += ['c2x'] + g_stds += ['gnu2x'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + g_stds return opts - def get_option_compile_args(self, options): + +class ClangCCompiler(_ClangCStds, ClangCompiler, CCompiler): + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, linker=linker, full_version=full_version) + ClangCompiler.__init__(self, defines) + default_warn_args = ['-Wall', '-Winvalid-pch'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic']} + + def get_options(self) -> 'KeyedOptionDictType': + opts = super().get_options() + if self.info.is_windows() or self.info.is_cygwin(): + opts.update({ + OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption( + 'Standard Win libraries to link against', + gnu_winlibs, + ), + }) + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['c_std'] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] if std.value != 'none': args.append('-std=' + std.value) return args - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + if self.info.is_windows() or self.info.is_cygwin(): + # without a typedict mypy can't understand this. + libs = options[OptionKey('winlibs', machine=self.for_machine, lang=self.language)].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs return [] @@ -131,24 +193,30 @@ _C17_VERSION = '>=10.0.0' _C18_VERSION = '>=11.0.0' + _C2X_VERSION = '>=11.0.0' -class EmscriptenCCompiler(LinkerEnvVarsMixin, EmscriptenMixin, BasicLinkerIsCompilerMixin, ClangCCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs): +class EmscriptenCCompiler(EmscriptenMixin, ClangCCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): if not is_cross: raise MesonException('Emscripten compiler can only be used for cross compilation.') - ClangCCompiler.__init__(self, exelist=exelist, version=version, - for_machine=for_machine, is_cross=is_cross, - info=info, exe_wrapper=exe_wrapper, **kwargs) + 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): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + 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): CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, **kwargs) + info, exe_wrapper, linker=linker, full_version=full_version) ArmclangCompiler.__init__(self) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -156,100 +224,137 @@ '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CCompiler.get_options(self) - opts.update({'c_std': coredata.UserComboOption('C language standard to use', - ['none', 'c90', 'c99', 'c11', - 'gnu90', 'gnu99', 'gnu11'], - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11'] return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['c_std'] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] if std.value != 'none': args.append('-std=' + std.value) return args - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] class GnuCCompiler(GnuCompiler, CCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - defines=None, **kwargs): - CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, **kwargs) + + _C18_VERSION = '>=8.0.0' + _C2X_VERSION = '>=9.0.0' + _INVALID_PCH_VERSION = ">=3.4.0" + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, linker=linker, full_version=full_version) GnuCompiler.__init__(self, defines) - default_warn_args = ['-Wall', '-Winvalid-pch'] + default_warn_args = ['-Wall'] + if version_compare(self.version, self._INVALID_PCH_VERSION): + default_warn_args += ['-Winvalid-pch'] self.warn_args = {'0': [], '1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CCompiler.get_options(self) c_stds = ['c89', 'c99', 'c11'] g_stds = ['gnu89', 'gnu99', 'gnu11'] - v = '>=8.0.0' - if version_compare(self.version, v): + if version_compare(self.version, self._C18_VERSION): c_stds += ['c17', 'c18'] g_stds += ['gnu17', 'gnu18'] - opts.update({'c_std': coredata.UserComboOption('C language standard to use', - ['none'] + c_stds + g_stds, - 'none')}) + if version_compare(self.version, self._C2X_VERSION): + c_stds += ['c2x'] + g_stds += ['gnu2x'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + c_stds + g_stds if self.info.is_windows() or self.info.is_cygwin(): opts.update({ - 'c_winlibs': coredata.UserArrayOption('Standard Win libraries to link against', - gnu_winlibs), }) + key.evolve('winlibs'): coredata.UserArrayOption( + 'Standard Win libraries to link against', + gnu_winlibs, + ), + }) return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['c_std'] + std = options[OptionKey('std', lang=self.language, machine=self.for_machine)] if std.value != 'none': args.append('-std=' + std.value) return args - def get_option_link_args(self, options): + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: if self.info.is_windows() or self.info.is_cygwin(): - return options['c_winlibs'].value[:] + # without a typeddict mypy can't figure this out + libs: T.List[str] = options[OptionKey('winlibs', lang=self.language, machine=self.for_machine)].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs return [] - def get_pch_use_args(self, pch_dir, header): + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: return ['-fpch-preprocess', '-include', os.path.basename(header)] class PGICCompiler(PGICompiler, CCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + 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): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + PGICompiler.__init__(self) + + +class NvidiaHPC_CCompiler(PGICompiler, CCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, **kwargs) + info, exe_wrapper, linker=linker, full_version=full_version) PGICompiler.__init__(self) + self.id = 'nvidia_hpc' -class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - defines=None, **kwargs): - GnuCCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, defines, **kwargs) +class ElbrusCCompiler(ElbrusCompiler, CCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) ElbrusCompiler.__init__(self) - # It does support some various ISO standards and c/gnu 90, 9x, 1x in addition to those which GNU CC supports. - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CCompiler.get_options(self) - opts.update({'c_std': coredata.UserComboOption('C language standard to use', - ['none', 'c89', 'c90', 'c9x', 'c99', 'c1x', 'c11', - 'gnu89', 'gnu90', 'gnu9x', 'gnu99', 'gnu1x', 'gnu11', - 'iso9899:2011', 'iso9899:1990', 'iso9899:199409', 'iso9899:1999'], - 'none')}) + stds = ['c89', 'c9x', 'c99', 'gnu89', 'gnu9x', 'gnu99'] + stds += ['iso9899:1990', 'iso9899:199409', 'iso9899:1999'] + if version_compare(self.version, '>=1.20.00'): + stds += ['c11', 'gnu11'] + if version_compare(self.version, '>=1.21.00') and version_compare(self.version, '<1.22.00'): + stds += ['c90', 'c1x', 'gnu90', 'gnu1x', 'iso9899:2011'] + if version_compare(self.version, '>=1.23.00'): + stds += ['c90', 'c1x', 'gnu90', 'gnu1x', 'iso9899:2011'] + if version_compare(self.version, '>=1.26.00'): + stds += ['c17', 'c18', 'iso9899:2017', 'iso9899:2018', 'gnu17', 'gnu18'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + stds return opts # Elbrus C compiler does not have lchmod, but there is only linker warning, not compiler error. # So we should explicitly fail at this case. - def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None): + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: if funcname == 'lchmod': return False, False else: @@ -259,10 +364,12 @@ class IntelCCompiler(IntelGnuLikeCompiler, CCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + 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): CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, **kwargs) + info, exe_wrapper, linker=linker, full_version=full_version) IntelGnuLikeCompiler.__init__(self) self.lang_header = 'c-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark'] @@ -271,152 +378,344 @@ '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CCompiler.get_options(self) c_stds = ['c89', 'c99'] g_stds = ['gnu89', 'gnu99'] if version_compare(self.version, '>=16.0.0'): c_stds += ['c11'] - opts.update({'c_std': coredata.UserComboOption('C language standard to use', - ['none'] + c_stds + g_stds, - 'none')}) + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + g_stds return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['c_std'] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] if std.value != 'none': args.append('-std=' + std.value) return args -class VisualStudioLikeCCompilerMixin: +class VisualStudioLikeCCompilerMixin(CompilerMixinBase): """Shared methods that apply to MSVC-like C compilers.""" - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = super().get_options() - opts.update({'c_winlibs': coredata.UserArrayOption('Windows libs to link against.', - msvc_winlibs)}) + opts.update({ + OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption( + 'Windows libs to link against.', + msvc_winlibs, + ), + }) return opts - def get_option_link_args(self, options): - return options['c_winlibs'].value[:] - + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + # need a TypeDict to make this work + key = OptionKey('winlibs', machine=self.for_machine, lang=self.language) + libs = options[key].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs + + +class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompiler): + + _C11_VERSION = '>=19.28' + _C17_VERSION = '>=19.28' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, + full_version=full_version) + MSVCCompiler.__init__(self, target) -class VisualStudioCCompiler(VisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): + def get_options(self) -> 'KeyedOptionDictType': + opts = super().get_options() + c_stds = ['c89', 'c99'] + # Need to have these to be compatible with projects + # that set c_std to e.g. gnu99. + # https://github.com/mesonbuild/meson/issues/7611 + g_stds = ['gnu89', 'gnu90', 'gnu9x', 'gnu99'] + if version_compare(self.version, self._C11_VERSION): + c_stds += ['c11'] + g_stds += ['gnu1x', 'gnu11'] + if version_compare(self.version, self._C17_VERSION): + c_stds += ['c17', 'c18'] + g_stds += ['gnu17', 'gnu18'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + c_stds + g_stds + return opts - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap, target: str, - **kwargs): - CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrap, **kwargs) - VisualStudioLikeCompiler.__init__(self, target) - self.id = 'msvc' + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value.startswith('gnu'): + mlog.log_once( + 'cl.exe does not actually support gnu standards, and meson ' + 'will instead demote to the nearest ISO C standard. This ' + 'may cause compilation to fail.') + # As of MVSC 16.8, /std:c11 and /std:c17 are the only valid C standard options. + if std.value in {'c11', 'gnu1x', 'gnu11'}: + args.append('/std:c11') + elif std.value in {'c17', 'c18', 'gnu17', 'gnu18'}: + args.append('/std:c17') + return args -class ClangClCCompiler(VisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap, target, **kwargs): +class ClangClCCompiler(_ClangCStds, ClangClCompiler, VisualStudioLikeCCompilerMixin, CCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrap, **kwargs) - VisualStudioLikeCompiler.__init__(self, target) - self.id = 'clang-cl' + info, exe_wrapper, linker=linker, + full_version=full_version) + ClangClCompiler.__init__(self, target) + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key].value + if std != "none": + return [f'/clang:-std={std}'] + return [] class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): """Intel "ICL" compiler abstraction.""" - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrap, target, **kwargs): + 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, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrap, **kwargs) + info, exe_wrapper, linker=linker, + full_version=full_version) IntelVisualStudioLikeCompiler.__init__(self, target) - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = super().get_options() - c_stds = ['none', 'c89', 'c99', 'c11'] - opts.update({'c_std': coredata.UserComboOption('C language standard to use', - c_stds, - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99', 'c11'] return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['c_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value == 'c89': - mlog.warning("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.", once=True) + mlog.log_once("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.") elif std.value != 'none': args.append('/Qstd:' + std.value) return args class ArmCCompiler(ArmCompiler, CCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + 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): CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, **kwargs) + info, exe_wrapper, linker=linker, + full_version=full_version) ArmCompiler.__init__(self) - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CCompiler.get_options(self) - opts.update({'c_std': coredata.UserComboOption('C language standard to use', - ['none', 'c90', 'c99'], - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99', 'c11'] return opts - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['c_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': args.append('--' + std.value) return args class CcrxCCompiler(CcrxCompiler, CCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + 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): CCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, **kwargs) + info, exe_wrapper, linker=linker, full_version=full_version) CcrxCompiler.__init__(self) # Override CCompiler.get_always_args - def get_always_args(self): + def get_always_args(self) -> T.List[str]: return ['-nologo'] - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = CCompiler.get_options(self) - opts.update({'c_std': coredata.UserComboOption('C language standard to use', - ['none', 'c89', 'c99'], - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99'] return opts - def get_no_stdinc_args(self): + def get_no_stdinc_args(self) -> T.List[str]: return [] - def get_option_compile_args(self, options): + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['c_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value == 'c89': args.append('-lang=c') elif std.value == 'c99': args.append('-lang=c99') return args - def get_compile_only_args(self): + def get_compile_only_args(self) -> T.List[str]: return [] - def get_no_optimization_args(self): + def get_no_optimization_args(self) -> T.List[str]: return ['-optimize=0'] - def get_output_args(self, target): - return ['-output=obj=%s' % target] + def get_output_args(self, target: str) -> T.List[str]: + return [f'-output=obj={target}'] - def get_werror_args(self): + def get_werror_args(self) -> T.List[str]: return ['-change_message=error'] - def get_include_args(self, path, is_system): + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: if path == '': path = '.' return ['-include=' + path] + + +class Xc16CCompiler(Xc16Compiler, CCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + Xc16Compiler.__init__(self) + + def get_options(self) -> 'KeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99', 'gnu89', 'gnu99'] + return opts + + def get_no_stdinc_args(self) -> T.List[str]: + return [] + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('-ansi') + args.append('-std=' + std.value) + return args + + def get_compile_only_args(self) -> T.List[str]: + return [] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-O0'] + + def get_output_args(self, target: str) -> T.List[str]: + return [f'-o{target}'] + + def get_werror_args(self) -> T.List[str]: + return ['-change_message=error'] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + return ['-I' + path] + +class CompCertCCompiler(CompCertCompiler, CCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + CompCertCompiler.__init__(self) + + def get_options(self) -> 'KeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-O0'] + + def get_output_args(self, target: str) -> T.List[str]: + return [f'-o{target}'] + + def get_werror_args(self) -> T.List[str]: + return ['-Werror'] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + return ['-I' + path] + +class C2000CCompiler(C2000Compiler, CCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + C2000Compiler.__init__(self) + + # Override CCompiler.get_always_args + def get_always_args(self) -> T.List[str]: + return [] + + def get_options(self) -> 'KeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99', 'c11'] + return opts + + def get_no_stdinc_args(self) -> T.List[str]: + return [] + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('--' + std.value) + return args + + def get_compile_only_args(self) -> T.List[str]: + return [] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-Ooff'] + + def get_output_args(self, target: str) -> T.List[str]: + return [f'--output_file={target}'] + + def get_werror_args(self) -> T.List[str]: + return ['-change_message=error'] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + return ['--include_path=' + path] diff -Nru meson-0.53.2/mesonbuild/compilers/cs.py meson-0.61.2/mesonbuild/compilers/cs.py --- meson-0.53.2/mesonbuild/compilers/cs.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/cs.py 2022-01-17 10:50:45.000000000 +0000 @@ -13,15 +13,18 @@ # limitations under the License. import os.path, subprocess +import textwrap import typing as T from ..mesonlib import EnvironmentException +from ..linkers import RSPFileSyntax from .compilers import Compiler, MachineChoice, mono_buildtype_args from .mixins.islinker import BasicLinkerIsCompilerMixin if T.TYPE_CHECKING: from ..envconfig import MachineInfo + from ..environment import Environment cs_optimization_args = {'0': [], 'g': [], @@ -29,64 +32,43 @@ '2': ['-optimize+'], '3': ['-optimize+'], 's': ['-optimize+'], - } + } # type: T.Dict[str, T.List[str]] class CsCompiler(BasicLinkerIsCompilerMixin, Compiler): language = 'cs' - def __init__(self, exelist, version, for_machine: MachineChoice, - info: 'MachineInfo', comp_id, runner=None): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', comp_id: str, runner: T.Optional[str] = None): super().__init__(exelist, version, for_machine, info) self.id = comp_id - self.is_cross = False self.runner = runner @classmethod - def get_display_language(cls): + def get_display_language(cls) -> str: return 'C sharp' - def get_always_args(self): + def get_always_args(self) -> T.List[str]: return ['/nologo'] - def get_linker_always_args(self): + def get_linker_always_args(self) -> T.List[str]: return ['/nologo'] - def get_output_args(self, fname): + def get_output_args(self, fname: str) -> T.List[str]: return ['-out:' + fname] - def get_link_args(self, fname): + def get_link_args(self, fname: str) -> T.List[str]: return ['-r:' + fname] - def get_werror_args(self): + def get_werror_args(self) -> T.List[str]: return ['-warnaserror'] - def split_shlib_to_parts(self, fname): - return None, fname - - def get_dependency_gen_args(self, outtarget, outfile): - return [] - - def get_linker_exelist(self): - return self.exelist[:] - - def get_compile_only_args(self): - return [] - - def get_coverage_args(self): - return [] - - def get_std_exe_link_args(self): + def get_pic_args(self) -> T.List[str]: return [] - def get_include_args(self, path): - return [] - - def get_pic_args(self): - return [] - - def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): if i[:2] == '-L': parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) @@ -95,29 +77,27 @@ return parameter_list - def name_string(self): - return ' '.join(self.exelist) - - def get_pch_use_args(self, pch_dir, header): + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: return [] - def get_pch_name(self, header_name): + def get_pch_name(self, header_name: str) -> str: return '' - def sanity_check(self, work_dir, environment): + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: src = 'sanity.cs' obj = 'sanity.exe' source_name = os.path.join(work_dir, src) - with open(source_name, 'w') as ofile: - ofile.write('''public class Sanity { - static public void Main () { - } -} -''') + with open(source_name, 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent(''' + public class Sanity { + static public void Main () { + } + } + ''')) pc = subprocess.Popen(self.exelist + self.get_always_args() + [src], cwd=work_dir) pc.wait() if pc.returncode != 0: - raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string()) + raise EnvironmentException('C# compiler %s can not compile programs.' % self.name_string()) if self.runner: cmdlist = [self.runner, obj] else: @@ -127,32 +107,35 @@ if pe.returncode != 0: raise EnvironmentException('Executables created by Mono compiler %s are not runnable.' % self.name_string()) - def needs_static_linker(self): + def needs_static_linker(self) -> bool: return False - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> T.List[str]: return mono_buildtype_args[buildtype] - def get_debug_args(self, is_debug): + def get_debug_args(self, is_debug: bool) -> T.List[str]: return ['-debug'] if is_debug else [] - def get_optimization_args(self, optimization_level): + def get_optimization_args(self, optimization_level: str) -> T.List[str]: return cs_optimization_args[optimization_level] class MonoCompiler(CsCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo'): super().__init__(exelist, version, for_machine, info, 'mono', runner='mono') + def rsp_file_syntax(self) -> 'RSPFileSyntax': + return RSPFileSyntax.GCC + class VisualStudioCsCompiler(CsCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo'): super().__init__(exelist, version, for_machine, info, 'csc') - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> T.List[str]: res = mono_buildtype_args[buildtype] if not self.info.is_windows(): tmp = [] @@ -162,3 +145,6 @@ tmp.append(flag) res = tmp return res + + def rsp_file_syntax(self) -> 'RSPFileSyntax': + return RSPFileSyntax.MSVC diff -Nru meson-0.53.2/mesonbuild/compilers/cuda.py meson-0.61.2/mesonbuild/compilers/cuda.py --- meson-0.53.2/mesonbuild/compilers/cuda.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/cuda.py 2022-01-17 10:50:45.000000000 +0000 @@ -12,19 +12,34 @@ # See the License for the specific language governing permissions and # limitations under the License. +import enum import os.path +import string import typing as T -from functools import partial from .. import coredata from .. import mlog -from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe, OptionOverrideProxy, is_windows, LibType +from ..mesonlib import ( + EnvironmentException, MachineChoice, Popen_safe, OptionOverrideProxy, + is_windows, LibType, OptionKey, +) from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args, - cuda_debug_args) + cuda_debug_args, CompileCheckMode) if T.TYPE_CHECKING: + from ..build import BuildTarget + from ..coredata import KeyedOptionDictType + from ..dependencies import Dependency from ..environment import Environment # noqa: F401 from ..envconfig import MachineInfo + from ..linkers import DynamicLinker + from ..programs import ExternalProgram + + +class _Phase(enum.Enum): + + COMPILER = 'compiler' + LINKER = 'linker' class CudaCompiler(Compiler): @@ -32,12 +47,138 @@ LINKER_PREFIX = '-Xlinker=' language = 'cuda' - _universal_flags = {'compiler': ['-I', '-D', '-U', '-E'], 'linker': ['-l', '-L']} - - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, exe_wrapper, host_compiler, info: 'MachineInfo', **kwargs): - super().__init__(exelist, version, for_machine, info, **kwargs) - self.is_cross = is_cross + # NVCC flags taking no arguments. + _FLAG_PASSTHRU_NOARGS = { + # NVCC --long-option, NVCC -short-option CUDA Toolkit 11.2.1 Reference + '--objdir-as-tempdir', '-objtemp', # 4.2.1.2 + '--generate-dependency-targets', '-MP', # 4.2.1.12 + '--allow-unsupported-compiler', '-allow-unsupported-compiler', # 4.2.1.14 + '--link', # 4.2.2.1 + '--lib', '-lib', # 4.2.2.2 + '--device-link', '-dlink', # 4.2.2.3 + '--device-c', '-dc', # 4.2.2.4 + '--device-w', '-dw', # 4.2.2.5 + '--cuda', '-cuda', # 4.2.2.6 + '--compile', '-c', # 4.2.2.7 + '--fatbin', '-fatbin', # 4.2.2.8 + '--cubin', '-cubin', # 4.2.2.9 + '--ptx', '-ptx', # 4.2.2.10 + '--preprocess', '-E', # 4.2.2.11 + '--generate-dependencies', '-M', # 4.2.2.12 + '--generate-nonsystem-dependencies', '-MM', # 4.2.2.13 + '--generate-dependencies-with-compile', '-MD', # 4.2.2.14 + '--generate-nonsystem-dependencies-with-compile', '-MMD', # 4.2.2.15 + '--run', # 4.2.2.16 + '--profile', '-pg', # 4.2.3.1 + '--debug', '-g', # 4.2.3.2 + '--device-debug', '-G', # 4.2.3.3 + '--extensible-whole-program', '-ewp', # 4.2.3.4 + '--generate-line-info', '-lineinfo', # 4.2.3.5 + '--dlink-time-opt', '-dlto', # 4.2.3.8 + '--no-exceptions', '-noeh', # 4.2.3.11 + '--shared', '-shared', # 4.2.3.12 + '--no-host-device-initializer-list', '-nohdinitlist', # 4.2.3.15 + '--expt-relaxed-constexpr', '-expt-relaxed-constexpr', # 4.2.3.16 + '--extended-lambda', '-extended-lambda', # 4.2.3.17 + '--expt-extended-lambda', '-expt-extended-lambda', # 4.2.3.18 + '--m32', '-m32', # 4.2.3.20 + '--m64', '-m64', # 4.2.3.21 + '--forward-unknown-to-host-compiler', '-forward-unknown-to-host-compiler', # 4.2.5.1 + '--forward-unknown-to-host-linker', '-forward-unknown-to-host-linker', # 4.2.5.2 + '--dont-use-profile', '-noprof', # 4.2.5.3 + '--dryrun', '-dryrun', # 4.2.5.5 + '--verbose', '-v', # 4.2.5.6 + '--keep', '-keep', # 4.2.5.7 + '--save-temps', '-save-temps', # 4.2.5.9 + '--clean-targets', '-clean', # 4.2.5.10 + '--no-align-double', # 4.2.5.16 + '--no-device-link', '-nodlink', # 4.2.5.17 + '--allow-unsupported-compiler', '-allow-unsupported-compiler', # 4.2.5.18 + '--use_fast_math', '-use_fast_math', # 4.2.7.7 + '--extra-device-vectorization', '-extra-device-vectorization', # 4.2.7.12 + '--compile-as-tools-patch', '-astoolspatch', # 4.2.7.13 + '--keep-device-functions', '-keep-device-functions', # 4.2.7.14 + '--disable-warnings', '-w', # 4.2.8.1 + '--source-in-ptx', '-src-in-ptx', # 4.2.8.2 + '--restrict', '-restrict', # 4.2.8.3 + '--Wno-deprecated-gpu-targets', '-Wno-deprecated-gpu-targets', # 4.2.8.4 + '--Wno-deprecated-declarations', '-Wno-deprecated-declarations', # 4.2.8.5 + '--Wreorder', '-Wreorder', # 4.2.8.6 + '--Wdefault-stream-launch', '-Wdefault-stream-launch', # 4.2.8.7 + '--Wext-lambda-captures-this', '-Wext-lambda-captures-this', # 4.2.8.8 + '--display-error-number', '-err-no', # 4.2.8.10 + '--resource-usage', '-res-usage', # 4.2.8.14 + '--help', '-h', # 4.2.8.15 + '--version', '-V', # 4.2.8.16 + '--list-gpu-code', '-code-ls', # 4.2.8.20 + '--list-gpu-arch', '-arch-ls', # 4.2.8.21 + } + # Dictionary of NVCC flags taking either one argument or a comma-separated list. + # Maps --long to -short options, because the short options are more GCC-like. + _FLAG_LONG2SHORT_WITHARGS = { + '--output-file': '-o', # 4.2.1.1 + '--pre-include': '-include', # 4.2.1.3 + '--library': '-l', # 4.2.1.4 + '--define-macro': '-D', # 4.2.1.5 + '--undefine-macro': '-U', # 4.2.1.6 + '--include-path': '-I', # 4.2.1.7 + '--system-include': '-isystem', # 4.2.1.8 + '--library-path': '-L', # 4.2.1.9 + '--output-directory': '-odir', # 4.2.1.10 + '--dependency-output': '-MF', # 4.2.1.11 + '--compiler-bindir': '-ccbin', # 4.2.1.13 + '--archiver-binary': '-arbin', # 4.2.1.15 + '--cudart': '-cudart', # 4.2.1.16 + '--cudadevrt': '-cudadevrt', # 4.2.1.17 + '--libdevice-directory': '-ldir', # 4.2.1.18 + '--target-directory': '-target-dir', # 4.2.1.19 + '--optimization-info': '-opt-info', # 4.2.3.6 + '--optimize': '-O', # 4.2.3.7 + '--ftemplate-backtrace-limit': '-ftemplate-backtrace-limit', # 4.2.3.9 + '--ftemplate-depth': '-ftemplate-depth', # 4.2.3.10 + '--x': '-x', # 4.2.3.13 + '--std': '-std', # 4.2.3.14 + '--machine': '-m', # 4.2.3.19 + '--compiler-options': '-Xcompiler', # 4.2.4.1 + '--linker-options': '-Xlinker', # 4.2.4.2 + '--archive-options': '-Xarchive', # 4.2.4.3 + '--ptxas-options': '-Xptxas', # 4.2.4.4 + '--nvlink-options': '-Xnvlink', # 4.2.4.5 + '--threads': '-t', # 4.2.5.4 + '--keep-dir': '-keep-dir', # 4.2.5.8 + '--run-args': '-run-args', # 4.2.5.11 + '--input-drive-prefix': '-idp', # 4.2.5.12 + '--dependency-drive-prefix': '-ddp', # 4.2.5.13 + '--drive-prefix': '-dp', # 4.2.5.14 + '--dependency-target-name': '-MT', # 4.2.5.15 + '--default-stream': '-default-stream', # 4.2.6.1 + '--gpu-architecture': '-arch', # 4.2.7.1 + '--gpu-code': '-code', # 4.2.7.2 + '--generate-code': '-gencode', # 4.2.7.3 + '--relocatable-device-code': '-rdc', # 4.2.7.4 + '--entries': '-e', # 4.2.7.5 + '--maxrregcount': '-maxrregcount', # 4.2.7.6 + '--ftz': '-ftz', # 4.2.7.8 + '--prec-div': '-prec-div', # 4.2.7.9 + '--prec-sqrt': '-prec-sqrt', # 4.2.7.10 + '--fmad': '-fmad', # 4.2.7.11 + '--Werror': '-Werror', # 4.2.8.9 + '--diag-error': '-diag-error', # 4.2.8.11 + '--diag-suppress': '-diag-suppress', # 4.2.8.12 + '--diag-warn': '-diag-warn', # 4.2.8.13 + '--options-file': '-optf', # 4.2.8.17 + '--time': '-time', # 4.2.8.18 + '--qpp-config': '-qpp-config', # 4.2.8.19 + } + # Reverse map -short to --long options. + _FLAG_SHORT2LONG_WITHARGS = {v: k for k, v in _FLAG_LONG2SHORT_WITHARGS.items()} + + 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', + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + super().__init__(exelist, version, for_machine, info, linker=linker, full_version=full_version, is_cross=is_cross) self.exe_wrapper = exe_wrapper self.host_compiler = host_compiler self.base_options = host_compiler.base_options @@ -45,29 +186,296 @@ self.warn_args = {level: self._to_host_flags(flags) for level, flags in host_compiler.warn_args.items()} @classmethod - def _to_host_flags(cls, flags, phase='compiler'): - return list(map(partial(cls._to_host_flag, phase=phase), flags)) + def _shield_nvcc_list_arg(cls, arg: str, listmode: bool = True) -> str: + r""" + Shield an argument against both splitting by NVCC's list-argument + parse logic, and interpretation by any shell. + + NVCC seems to consider every comma , that is neither escaped by \ nor inside + a double-quoted string a split-point. Single-quotes do not provide protection + against splitting; In fact, after splitting they are \-escaped. Unfortunately, + double-quotes don't protect against shell expansion. What follows is a + complex dance to accommodate everybody. + """ + + SQ = "'" + DQ = '"' + CM = "," + BS = "\\" + DQSQ = DQ+SQ+DQ + quotable = set(string.whitespace+'"$`\\') + + if CM not in arg or not listmode: + if SQ not in arg: + # If any of the special characters "$`\ or whitespace are present, single-quote. + # Otherwise return bare. + if set(arg).intersection(quotable): + return SQ+arg+SQ + else: + return arg # Easy case: no splits, no quoting. + else: + # There are single quotes. Double-quote them, and single-quote the + # strings between them. + l = [cls._shield_nvcc_list_arg(s) for s in arg.split(SQ)] + l = sum([[s, DQSQ] for s in l][:-1], []) # Interleave l with DQSQs + return ''.join(l) + else: + # A comma is present, and list mode was active. + # We apply (what we guess is) the (primitive) NVCC splitting rule: + l = [''] + instring = False + argit = iter(arg) + for c in argit: + if c == CM and not instring: + l.append('') + elif c == DQ: + l[-1] += c + instring = not instring + elif c == BS: + try: + l[-1] += next(argit) + except StopIteration: + break + else: + l[-1] += c + + # Shield individual strings, without listmode, then return them with + # escaped commas between them. + l = [cls._shield_nvcc_list_arg(s, listmode=False) for s in l] + return r'\,'.join(l) @classmethod - def _to_host_flag(cls, flag, phase): - if not flag[0] in ['-', '/'] or flag[:2] in cls._universal_flags[phase]: - return flag - - return '-X{}={}'.format(phase, flag) + def _merge_flags(cls, flags: T.List[str]) -> T.List[str]: + r""" + The flags to NVCC gets exceedingly verbose and unreadable when too many of them + are shielded with -Xcompiler. Merge consecutive -Xcompiler-wrapped arguments + into one. + """ + if len(flags) <= 1: + return flags + flagit = iter(flags) + xflags = [] + + def is_xcompiler_flag_isolated(flag: str) -> bool: + return flag == '-Xcompiler' + def is_xcompiler_flag_glued(flag: str) -> bool: + return flag.startswith('-Xcompiler=') + def is_xcompiler_flag(flag: str) -> bool: + return is_xcompiler_flag_isolated(flag) or is_xcompiler_flag_glued(flag) + def get_xcompiler_val(flag: str, flagit: T.Iterator[str]) -> str: + if is_xcompiler_flag_glued(flag): + return flag[len('-Xcompiler='):] + else: + try: + return next(flagit) + except StopIteration: + return "" + + ingroup = False + for flag in flagit: + if not is_xcompiler_flag(flag): + ingroup = False + xflags.append(flag) + elif ingroup: + xflags[-1] += ',' + xflags[-1] += get_xcompiler_val(flag, flagit) + elif is_xcompiler_flag_isolated(flag): + ingroup = True + xflags.append(flag) + xflags.append(get_xcompiler_val(flag, flagit)) + elif is_xcompiler_flag_glued(flag): + ingroup = True + xflags.append(flag) + else: + raise ValueError("-Xcompiler flag merging failed, unknown argument form!") + return xflags - def needs_static_linker(self): - return False + def _to_host_flags(self, flags: T.List[str], phase: _Phase = _Phase.COMPILER) -> T.List[str]: + """ + Translate generic "GCC-speak" plus particular "NVCC-speak" flags to NVCC flags. + + NVCC's "short" flags have broad similarities to the GCC standard, but have + gratuitous, irritating differences. + """ + + xflags = [] + flagit = iter(flags) + + for flag in flagit: + # The CUDA Toolkit Documentation, in 4.1. Command Option Types and Notation, + # specifies that NVCC does not parse the standard flags as GCC does. It has + # its own strategy, to wit: + # + # nvcc recognizes three types of command options: boolean options, single + # value options, and list options. + # + # Boolean options do not have an argument; they are either specified on a + # command line or not. Single value options must be specified at most once, + # and list options may be repeated. Examples of each of these option types + # are, respectively: --verbose (switch to verbose mode), --output-file + # (specify output file), and --include-path (specify include path). + # + # Single value options and list options must have arguments, which must + # follow the name of the option itself by either one of more spaces or an + # equals character. When a one-character short name such as -I, -l, and -L + # is used, the value of the option may also immediately follow the option + # itself without being separated by spaces or an equal character. The + # individual values of list options may be separated by commas in a single + # instance of the option, or the option may be repeated, or any + # combination of these two cases. + # + # One strange consequence of this choice is that directory and filenames that + # contain commas (',') cannot be passed to NVCC (at least, not as easily as + # in GCC). Another strange consequence is that it is legal to supply flags + # such as + # + # -lpthread,rt,dl,util + # -l pthread,rt,dl,util + # -l=pthread,rt,dl,util + # + # and each of the above alternatives is equivalent to GCC-speak + # + # -lpthread -lrt -ldl -lutil + # -l pthread -l rt -l dl -l util + # -l=pthread -l=rt -l=dl -l=util + # + # *With the exception of commas in the name*, GCC-speak for these list flags + # is a strict subset of NVCC-speak, so we passthrough those flags. + # + # The -D macro-define flag is documented as somehow shielding commas from + # splitting a definition. Balanced parentheses, braces and single-quotes + # around the comma are not sufficient, but balanced double-quotes are. The + # shielding appears to work with -l, -I, -L flags as well, for instance. + # + # Since our goal is to replicate GCC-speak as much as possible, we check for + # commas in all list-arguments and shield them with double-quotes. We make + # an exception for -D (where this would be value-changing) and -U (because + # it isn't possible to define a macro with a comma in the name). + + if flag in self._FLAG_PASSTHRU_NOARGS: + xflags.append(flag) + continue + + # Handle breakup of flag-values into a flag-part and value-part. + if flag[:1] not in '-/': + # This is not a flag. It's probably a file input. Pass it through. + xflags.append(flag) + continue + elif flag[:1] == '/': + # This is ambiguously either an MVSC-style /switch or an absolute path + # to a file. For some magical reason the following works acceptably in + # both cases. + wrap = '"' if ',' in flag else '' + xflags.append(f'-X{phase.value}={wrap}{flag}{wrap}') + continue + elif len(flag) >= 2 and flag[0] == '-' and flag[1] in 'IDULlmOxmte': + # This is a single-letter short option. These options (with the + # exception of -o) are allowed to receive their argument with neither + # space nor = sign before them. Detect and separate them in that event. + if flag[2:3] == '': # -I something + try: + val = next(flagit) + except StopIteration: + pass + elif flag[2:3] == '=': # -I=something + val = flag[3:] + else: # -Isomething + val = flag[2:] + flag = flag[:2] # -I + elif flag in self._FLAG_LONG2SHORT_WITHARGS or \ + flag in self._FLAG_SHORT2LONG_WITHARGS: + # This is either -o or a multi-letter flag, and it is receiving its + # value isolated. + try: + val = next(flagit) # -o something + except StopIteration: + pass + elif flag.split('=', 1)[0] in self._FLAG_LONG2SHORT_WITHARGS or \ + flag.split('=', 1)[0] in self._FLAG_SHORT2LONG_WITHARGS: + # This is either -o or a multi-letter flag, and it is receiving its + # value after an = sign. + flag, val = flag.split('=', 1) # -o=something + # Some dependencies (e.g., BoostDependency) add unspaced "-isystem/usr/include" arguments + elif flag.startswith('-isystem'): + val = flag[8:].strip() + flag = flag[:8] + else: + # This is a flag, and it's foreign to NVCC. + # + # We do not know whether this GCC-speak flag takes an isolated + # argument. Assuming it does not (the vast majority indeed don't), + # wrap this argument in an -Xcompiler flag and send it down to NVCC. + if flag == '-ffast-math': + xflags.append('-use_fast_math') + xflags.append('-Xcompiler='+flag) + elif flag == '-fno-fast-math': + xflags.append('-ftz=false') + xflags.append('-prec-div=true') + xflags.append('-prec-sqrt=true') + xflags.append('-Xcompiler='+flag) + elif flag == '-freciprocal-math': + xflags.append('-prec-div=false') + xflags.append('-Xcompiler='+flag) + elif flag == '-fno-reciprocal-math': + xflags.append('-prec-div=true') + xflags.append('-Xcompiler='+flag) + else: + xflags.append('-Xcompiler='+self._shield_nvcc_list_arg(flag)) + # The above should securely handle GCC's -Wl, -Wa, -Wp, arguments. + continue + + assert val is not None # Should only trip if there is a missing argument. + + # Take care of the various NVCC-supported flags that need special handling. + flag = self._FLAG_LONG2SHORT_WITHARGS.get(flag, flag) + + if flag in {'-include', '-isystem', '-I', '-L', '-l'}: + # These flags are known to GCC, but list-valued in NVCC. They potentially + # require double-quoting to prevent NVCC interpreting the flags as lists + # when GCC would not have done so. + # + # We avoid doing this quoting for -D to avoid redefining macros and for + # -U because it isn't possible to define a macro with a comma in the name. + # -U with comma arguments is impossible in GCC-speak (and thus unambiguous + #in NVCC-speak, albeit unportable). + if len(flag) == 2: + xflags.append(flag+self._shield_nvcc_list_arg(val)) + elif flag == '-isystem' and val in self.host_compiler.get_default_include_dirs(): + # like GnuLikeCompiler, we have to filter out include directories specified + # with -isystem that overlap with the host compiler's search path + pass + else: + xflags.append(flag) + xflags.append(self._shield_nvcc_list_arg(val)) + elif flag == '-O': + # Handle optimization levels GCC knows about that NVCC does not. + if val == 'fast': + xflags.append('-O3') + xflags.append('-use_fast_math') + xflags.append('-Xcompiler') + xflags.append(flag+val) + elif val in {'s', 'g', 'z'}: + xflags.append('-Xcompiler') + xflags.append(flag+val) + else: + xflags.append(flag+val) + elif flag in {'-D', '-U', '-m', '-t'}: + xflags.append(flag+val) # For style, keep glued. + elif flag in {'-std'}: + xflags.append(flag+'='+val) # For style, keep glued. + else: + xflags.append(flag) + xflags.append(val) - def get_always_args(self): - return [] + return self._merge_flags(xflags) - def get_no_stdinc_args(self): - return [] + def needs_static_linker(self) -> bool: + return False - def thread_link_flags(self, environment): - return self._to_host_flags(self.host_compiler.thread_link_flags(environment)) + def thread_link_flags(self, environment: 'Environment') -> T.List[str]: + return self._to_host_flags(self.host_compiler.thread_link_flags(environment), _Phase.LINKER) - def sanity_check(self, work_dir, environment): + def sanity_check(self, work_dir: str, env: 'Environment') -> None: mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist)) mlog.debug('Is cross compiler: %s.' % str(self.is_cross)) @@ -100,7 +508,7 @@ binname += '_cross' if self.is_cross else '' source_name = os.path.join(work_dir, sname) binary_name = os.path.join(work_dir, binname + '.exe') - with open(source_name, 'w') as ofile: + with open(source_name, 'w', encoding='utf-8') as ofile: ofile.write(code) # The Sanity Test for CUDA language will serve as both a sanity test @@ -111,7 +519,18 @@ # environment set up properly. Of course, this only works for native # builds; For cross builds we must still use the exe_wrapper (if any). self.detected_cc = '' - flags = ['-w', '-cudart', 'static', source_name] + flags = [] + + # Disable warnings, compile with statically-linked runtime for minimum + # reliance on the system. + flags += ['-w', '-cudart', 'static', source_name] + + # Use the -ccbin option, if available, even during sanity checking. + # Otherwise, on systems where CUDA does not support the default compiler, + # NVCC becomes unusable. + flags += self.get_ccbin_args(env.coredata.options) + + # If cross-compiling, we can't run the sanity check, only compile it. if self.is_cross and self.exe_wrapper is None: # Linking cross built apps is painful. You can't really # tell if you should use -nostdlib or not and for example @@ -131,14 +550,14 @@ mlog.debug(stde) mlog.debug('-----') if pc.returncode != 0: - raise EnvironmentException('Compiler {0} can not compile programs.'.format(self.name_string())) + raise EnvironmentException(f'Compiler {self.name_string()} can not compile programs.') # Run sanity check (if possible) if self.is_cross: if self.exe_wrapper is None: return else: - cmdlist = self.exe_wrapper + [binary_name] + cmdlist = self.exe_wrapper.get_command() + [binary_name] else: cmdlist = self.exelist + ['--run', '"' + binary_name + '"'] mlog.debug('Sanity check run command line: ', ' '.join(cmdlist)) @@ -150,7 +569,7 @@ mlog.debug('-----') pe.wait() if pe.returncode != 0: - raise EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string())) + raise EnvironmentException(f'Executables created by {self.language} compiler {self.name_string()} are not runnable.') # Interpret the result of the sanity test. # As mentioned above, it is not only a sanity test but also a GPU @@ -160,156 +579,193 @@ else: mlog.debug('cudaGetDeviceCount() returned ' + stde) - def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None): - result, cached = super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies) - if result: - return True, cached + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: if extra_args is None: extra_args = [] fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} + # Check if it's a C-like symbol + t = '''{prefix} + #include <{header}> + int main(void) {{ + /* If it's not defined as a macro, try to use as a symbol */ + #ifndef {symbol} + {symbol}; + #endif + return 0; + }}''' + found, cached = self.compiles(t.format_map(fargs), env, extra_args=extra_args, dependencies=dependencies) + if found: + return True, cached + # Check if it's a class or a template t = '''{prefix} #include <{header}> using {symbol}; - int main(void) {{ return 0; }}''' - return self.compiles(t.format(**fargs), env, extra_args, dependencies) + int main(void) {{ + return 0; + }}''' + return self.compiles(t.format_map(fargs), env, extra_args=extra_args, dependencies=dependencies) - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = super().get_options() - opts.update({'cuda_std': coredata.UserComboOption('C++ language standard to use', - ['none', 'c++03', 'c++11', 'c++14'], - 'none')}) + std_key = OptionKey('std', machine=self.for_machine, lang=self.language) + ccbindir_key = OptionKey('ccbindir', machine=self.for_machine, lang=self.language) + opts.update({ + std_key: coredata.UserComboOption('C++ language standard to use with CUDA', + ['none', 'c++03', 'c++11', 'c++14', 'c++17'], 'none'), + ccbindir_key: coredata.UserStringOption('CUDA non-default toolchain directory to use (-ccbin)', + ''), + }) return opts - def _to_host_compiler_options(self, options): - overrides = {name: opt.value for name, opt in options.copy().items()} - return OptionOverrideProxy(overrides, self.host_compiler.get_options()) + def _to_host_compiler_options(self, options: 'KeyedOptionDictType') -> 'KeyedOptionDictType': + """ + Convert an NVCC Option set to a host compiler's option set. + """ + + # We must strip the -std option from the host compiler option set, as NVCC has + # its own -std flag that may not agree with the host compiler's. + host_options = {key: options.get(key, opt) for key, opt in self.host_compiler.get_options().items()} + std_key = OptionKey('std', machine=self.for_machine, lang=self.host_compiler.language) + overrides = {std_key: 'none'} + return OptionOverrideProxy(overrides, host_options) - def get_option_compile_args(self, options): - args = [] + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = self.get_ccbin_args(options) # On Windows, the version of the C++ standard used by nvcc is dictated by # the combination of CUDA version and MSVC version; the --std= is thus ignored # and attempting to use it will result in a warning: https://stackoverflow.com/a/51272091/741027 if not is_windows(): - std = options['cuda_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': args.append('--std=' + std.value) return args + self._to_host_flags(self.host_compiler.get_option_compile_args(self._to_host_compiler_options(options))) - @classmethod - def _cook_link_args(cls, args: T.List[str]) -> T.List[str]: - # Prepare link args for nvcc - cooked = [] # type: T.List[str] - for arg in args: - if arg.startswith('-Wl,'): # strip GNU-style -Wl prefix - arg = arg.replace('-Wl,', '', 1) - arg = arg.replace(' ', '\\') # espace whitespace - cooked.append(arg) - return cls._to_host_flags(cooked, 'linker') - - def get_option_link_args(self, options): - return self._cook_link_args(self.host_compiler.get_option_link_args(self._to_host_compiler_options(options))) - - def name_string(self): - return ' '.join(self.exelist) - - def get_soname_args(self, *args): - return self._cook_link_args(self.host_compiler.get_soname_args(*args)) - - def get_dependency_gen_args(self, outtarget, outfile): - return [] + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = self.get_ccbin_args(options) + return args + self._to_host_flags(self.host_compiler.get_option_link_args(self._to_host_compiler_options(options)), _Phase.LINKER) + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, + darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_soname_args( + env, prefix, shlib_name, suffix, soversion, darwin_versions), _Phase.LINKER) - def get_compile_only_args(self): + def get_compile_only_args(self) -> T.List[str]: return ['-c'] - def get_no_optimization_args(self): + def get_no_optimization_args(self) -> T.List[str]: return ['-O0'] - def get_optimization_args(self, optimization_level): + def get_optimization_args(self, optimization_level: str) -> T.List[str]: # alternatively, consider simply redirecting this to the host compiler, which would # give us more control over options like "optimize for space" (which nvcc doesn't support): # return self._to_host_flags(self.host_compiler.get_optimization_args(optimization_level)) return cuda_optimization_args[optimization_level] - def get_debug_args(self, is_debug): + def sanitizer_compile_args(self, value: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.sanitizer_compile_args(value)) + + def sanitizer_link_args(self, value: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.sanitizer_link_args(value)) + + def get_debug_args(self, is_debug: bool) -> T.List[str]: return cuda_debug_args[is_debug] - def get_werror_args(self): + def get_werror_args(self) -> T.List[str]: return ['-Werror=cross-execution-space-call,deprecated-declarations,reorder'] - def get_warn_args(self, level): + def get_warn_args(self, level: str) -> T.List[str]: return self.warn_args[level] - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> T.List[str]: # nvcc doesn't support msvc's "Edit and Continue" PDB format; "downgrade" to # a regular PDB to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi') host_args = ['/Zi' if arg == '/ZI' else arg for arg in self.host_compiler.get_buildtype_args(buildtype)] return cuda_buildtype_args[buildtype] + self._to_host_flags(host_args) - def get_include_args(self, path, is_system): + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: if path == '': path = '.' - return ['-I' + path] - - def get_compile_debugfile_args(self, rel_obj, **kwargs): - return self._to_host_flags(self.host_compiler.get_compile_debugfile_args(rel_obj, **kwargs)) + return ['-isystem=' + path] if is_system else ['-I' + path] - def get_link_debugfile_args(self, targetfile): - return self._cook_link_args(self.host_compiler.get_link_debugfile_args(targetfile)) + def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_compile_debugfile_args(rel_obj, pch)) - def depfile_for_object(self, objfile): - return objfile + '.' + self.get_depfile_suffix() + def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_link_debugfile_args(targetfile), _Phase.LINKER) - def get_depfile_suffix(self): + def get_depfile_suffix(self) -> str: return 'd' - def get_linker_debug_crt_args(self) -> T.List[str]: - return self._cook_link_args(self.host_compiler.get_linker_debug_crt_args()) - - def get_buildtype_linker_args(self, buildtype): - return self._cook_link_args(self.host_compiler.get_buildtype_linker_args(buildtype)) + def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: + 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, - install_rpath: str) -> T.List[str]: - return self._cook_link_args(self.host_compiler.build_rpath_args( - env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)) + 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) + return (self._to_host_flags(rpath_args, _Phase.LINKER), rpath_dirs_to_remove) - def linker_to_compiler_args(self, args): + def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: return args - def get_pic_args(self): + def get_pic_args(self) -> T.List[str]: return self._to_host_flags(self.host_compiler.get_pic_args()) - def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: return [] def get_output_args(self, target: str) -> T.List[str]: return ['-o', target] def get_std_exe_link_args(self) -> T.List[str]: - return self._cook_link_args(self.host_compiler.get_std_exe_link_args()) + return self._to_host_flags(self.host_compiler.get_std_exe_link_args(), _Phase.LINKER) - def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED): + def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: return ['-l' + libname] # FIXME - def get_crt_compile_args(self, crt_val, buildtype): + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: return self._to_host_flags(self.host_compiler.get_crt_compile_args(crt_val, buildtype)) - def get_crt_link_args(self, crt_val, buildtype): + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: # nvcc defaults to static, release version of msvc runtime and provides no # native option to override it; override it with /NODEFAULTLIB host_link_arg_overrides = [] host_crt_compile_args = self.host_compiler.get_crt_compile_args(crt_val, buildtype) if any(arg in ['/MDd', '/MD', '/MTd'] for arg in host_crt_compile_args): host_link_arg_overrides += ['/NODEFAULTLIB:LIBCMT.lib'] - return self._cook_link_args(host_link_arg_overrides + self.host_compiler.get_crt_link_args(crt_val, buildtype)) + return self._to_host_flags(host_link_arg_overrides + self.host_compiler.get_crt_link_args(crt_val, buildtype), _Phase.LINKER) - def get_target_link_args(self, target): - return self._cook_link_args(super().get_target_link_args(target)) + def get_target_link_args(self, target: 'BuildTarget') -> T.List[str]: + return self._to_host_flags(super().get_target_link_args(target), _Phase.LINKER) - def get_dependency_compile_args(self, dep): + def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: return self._to_host_flags(super().get_dependency_compile_args(dep)) - def get_dependency_link_args(self, dep): - return self._cook_link_args(super().get_dependency_link_args(dep)) + def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]: + return self._to_host_flags(super().get_dependency_link_args(dep), _Phase.LINKER) + + def get_ccbin_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + key = OptionKey('ccbindir', machine=self.for_machine, lang=self.language) + ccbindir = options[key].value + if isinstance(ccbindir, str) and ccbindir != '': + return [self._shield_nvcc_list_arg('-ccbin='+ccbindir, False)] + else: + return [] + + def get_profile_generate_args(self) -> T.List[str]: + return ['-Xcompiler=' + x for x in self.host_compiler.get_profile_generate_args()] + + def get_profile_use_args(self) -> T.List[str]: + return ['-Xcompiler=' + x for x in self.host_compiler.get_profile_use_args()] + + def get_disable_assert_args(self) -> T.List[str]: + return self.host_compiler.get_disable_assert_args() diff -Nru meson-0.53.2/mesonbuild/compilers/cython.py meson-0.61.2/mesonbuild/compilers/cython.py --- meson-0.53.2/mesonbuild/compilers/cython.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/cython.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021 Intel Corporation + +"""Abstraction for Cython language compilers.""" + +import typing as T + +from .. import coredata +from ..mesonlib import EnvironmentException, OptionKey +from .compilers import Compiler + +if T.TYPE_CHECKING: + from ..coredata import KeyedOptionDictType + from ..environment import Environment + + +class CythonCompiler(Compiler): + + """Cython Compiler.""" + + language = 'cython' + id = 'cython' + + def needs_static_linker(self) -> bool: + # We transpile into C, so we don't need any linker + return False + + def get_always_args(self) -> T.List[str]: + return ['--fast-fail'] + + def get_werror_args(self) -> T.List[str]: + return ['-Werror'] + + def get_output_args(self, outputname: str) -> T.List[str]: + return ['-o', outputname] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + # Cython doesn't have optimization levels itself, the underlying + # compiler might though + return [] + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + code = 'print("hello world")' + with self.cached_compile(code, environment.coredata) as p: + if p.returncode != 0: + raise EnvironmentException(f'Cython compiler {self.id!r} cannot compile programs') + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # Cython doesn't implement this, but Meson requires an implementation + return [] + + def get_pic_args(self) -> T.List[str]: + # We can lie here, it's fine + return [] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + new: T.List[str] = [] + for i in parameter_list: + new.append(i) + + return new + + def get_options(self) -> 'KeyedOptionDictType': + opts = super().get_options() + opts.update({ + OptionKey('version', machine=self.for_machine, lang=self.language): coredata.UserComboOption( + 'Python version to target', + ['2', '3'], + '3', + ), + OptionKey('language', machine=self.for_machine, lang=self.language): coredata.UserComboOption( + 'Output C or C++ files', + ['c', 'cpp'], + 'c', + ) + }) + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args: T.List[str] = [] + key = options[OptionKey('version', machine=self.for_machine, lang=self.language)] + args.append(f'-{key.value}') + lang = options[OptionKey('language', machine=self.for_machine, lang=self.language)] + if lang.value == 'cpp': + args.append('--cplus') + return args diff -Nru meson-0.53.2/mesonbuild/compilers/detect.py meson-0.61.2/mesonbuild/compilers/detect.py --- meson-0.53.2/mesonbuild/compilers/detect.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/detect.py 2022-01-17 10:50:45.000000000 +0000 @@ -0,0 +1,1239 @@ +# Copyright 2012-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ..mesonlib import ( + MachineChoice, MesonException, EnvironmentException, + search_version, is_windows, Popen_safe, windows_proof_rm, +) +from ..envconfig import BinaryTable +from .. import mlog + +from ..linkers import ( + guess_win_linker, + guess_nix_linker, + AIXArLinker, + ArLinker, + ArmarLinker, + ArmClangDynamicLinker, + ArmDynamicLinker, + CcrxLinker, + CcrxDynamicLinker, + CompCertLinker, + CompCertDynamicLinker, + C2000Linker, + C2000DynamicLinker, + DLinker, + NAGDynamicLinker, + NvidiaHPC_DynamicLinker, + PGIDynamicLinker, + PGIStaticLinker, + StaticLinker, + Xc16Linker, + Xc16DynamicLinker, + XilinkDynamicLinker, + CudaLinker, + IntelVisualStudioLinker, + VisualStudioLinker, + VisualStudioLikeLinkerMixin, + WASMDynamicLinker, +) +from .compilers import Compiler +from .c import ( + CCompiler, + AppleClangCCompiler, + ArmCCompiler, + ArmclangCCompiler, + ClangCCompiler, + ClangClCCompiler, + GnuCCompiler, + ElbrusCCompiler, + EmscriptenCCompiler, + IntelCCompiler, + IntelClCCompiler, + NvidiaHPC_CCompiler, + PGICCompiler, + CcrxCCompiler, + Xc16CCompiler, + CompCertCCompiler, + C2000CCompiler, + VisualStudioCCompiler, +) +from .cpp import ( + CPPCompiler, + AppleClangCPPCompiler, + ArmCPPCompiler, + ArmclangCPPCompiler, + ClangCPPCompiler, + ClangClCPPCompiler, + GnuCPPCompiler, + ElbrusCPPCompiler, + EmscriptenCPPCompiler, + IntelCPPCompiler, + IntelClCPPCompiler, + NvidiaHPC_CPPCompiler, + PGICPPCompiler, + CcrxCPPCompiler, + C2000CPPCompiler, + VisualStudioCPPCompiler, +) +from .cs import MonoCompiler, VisualStudioCsCompiler +from .d import ( + DCompiler, + DmdDCompiler, + GnuDCompiler, + LLVMDCompiler, +) +from .cuda import CudaCompiler +from .fortran import ( + FortranCompiler, + G95FortranCompiler, + GnuFortranCompiler, + ElbrusFortranCompiler, + FlangFortranCompiler, + IntelFortranCompiler, + IntelClFortranCompiler, + NAGFortranCompiler, + Open64FortranCompiler, + PathScaleFortranCompiler, + NvidiaHPC_FortranCompiler, + PGIFortranCompiler, + SunFortranCompiler, +) +from .java import JavaCompiler +from .objc import ( + ObjCCompiler, + AppleClangObjCCompiler, + ClangObjCCompiler, + GnuObjCCompiler, +) +from .objcpp import ( + ObjCPPCompiler, + AppleClangObjCPPCompiler, + ClangObjCPPCompiler, + GnuObjCPPCompiler, +) +from .cython import CythonCompiler +from .rust import RustCompiler, ClippyRustCompiler +from .swift import SwiftCompiler +from .vala import ValaCompiler +from .mixins.visualstudio import VisualStudioLikeCompiler +from .mixins.gnu import GnuCompiler +from .mixins.clang import ClangCompiler + +import subprocess +import platform +import re +import shutil +import tempfile +import os +import typing as T + +if T.TYPE_CHECKING: + from ..environment import Environment + from ..programs import ExternalProgram + + +# Default compilers and linkers +# ============================= + +defaults: T.Dict[str, T.List[str]] = {} + +# List of potential compilers. +if is_windows(): + # Intel C and C++ compiler is icl on Windows, but icc and icpc elsewhere. + # Search for icl before cl, since Intel "helpfully" provides a + # cl.exe that returns *exactly the same thing* that microsofts + # cl.exe does, and if icl is present, it's almost certainly what + # you want. + defaults['c'] = ['icl', 'cl', 'cc', 'gcc', 'clang', 'clang-cl', 'pgcc'] + # There is currently no pgc++ for Windows, only for Mac and Linux. + defaults['cpp'] = ['icl', 'cl', 'c++', 'g++', 'clang++', 'clang-cl'] + defaults['fortran'] = ['ifort', 'gfortran', 'flang', 'pgfortran', 'g95'] + # Clang and clang++ are valid, but currently unsupported. + defaults['objc'] = ['cc', 'gcc'] + defaults['objcpp'] = ['c++', 'g++'] + defaults['cs'] = ['csc', 'mcs'] +else: + if platform.machine().lower() == 'e2k': + defaults['c'] = ['cc', 'gcc', 'lcc', 'clang'] + defaults['cpp'] = ['c++', 'g++', 'l++', 'clang++'] + defaults['objc'] = ['clang'] + defaults['objcpp'] = ['clang++'] + else: + defaults['c'] = ['cc', 'gcc', 'clang', 'nvc', 'pgcc', 'icc'] + defaults['cpp'] = ['c++', 'g++', 'clang++', 'nvc++', 'pgc++', 'icpc'] + defaults['objc'] = ['cc', 'gcc', 'clang'] + defaults['objcpp'] = ['c++', 'g++', 'clang++'] + defaults['fortran'] = ['gfortran', 'flang', 'nvfortran', 'pgfortran', 'ifort', 'g95'] + defaults['cs'] = ['mcs', 'csc'] +defaults['d'] = ['ldc2', 'ldc', 'gdc', 'dmd'] +defaults['java'] = ['javac'] +defaults['cuda'] = ['nvcc'] +defaults['rust'] = ['rustc'] +defaults['swift'] = ['swiftc'] +defaults['vala'] = ['valac'] +defaults['cython'] = ['cython'] +defaults['static_linker'] = ['ar', 'gar'] +defaults['strip'] = ['strip'] +defaults['vs_static_linker'] = ['lib'] +defaults['clang_cl_static_linker'] = ['llvm-lib'] +defaults['cuda_static_linker'] = ['nvlink'] +defaults['gcc_static_linker'] = ['gcc-ar'] +defaults['clang_static_linker'] = ['llvm-ar'] + + +def compiler_from_language(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Optional[Compiler]: + lang_map: T.Dict[str, T.Callable[['Environment', MachineChoice], Compiler]] = { + 'c': detect_c_compiler, + 'cpp': detect_cpp_compiler, + 'objc': detect_objc_compiler, + 'cuda': detect_cuda_compiler, + 'objcpp': detect_objcpp_compiler, + 'java': detect_java_compiler, + 'cs': detect_cs_compiler, + 'vala': detect_vala_compiler, + 'd': detect_d_compiler, + 'rust': detect_rust_compiler, + 'fortran': detect_fortran_compiler, + 'swift': detect_swift_compiler, + 'cython': detect_cython_compiler, + } + return lang_map[lang](env, for_machine) if lang in lang_map else None + +def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Optional[Compiler]: + comp = compiler_from_language(env, lang, for_machine) + if comp is not None: + assert comp.for_machine == for_machine + env.coredata.process_new_compiler(lang, comp, env) + return comp + + +# Helpers +# ======= + +def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Tuple[T.List[T.List[str]], T.List[str], T.Optional['ExternalProgram']]: + ''' + The list of compilers is detected in the exact same way for + C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here. + ''' + value = env.lookup_binary_entry(for_machine, lang) + if value is not None: + comp, ccache = BinaryTable.parse_entry(value) + # Return value has to be a list of compiler 'choices' + compilers = [comp] + else: + if not env.machines.matches_build_machine(for_machine): + raise EnvironmentException(f'{lang!r} compiler binary not defined in cross or native file') + compilers = [[x] for x in defaults[lang]] + ccache = BinaryTable.detect_compiler_cache() + + if env.machines.matches_build_machine(for_machine): + exe_wrap: T.Optional[ExternalProgram] = None + else: + exe_wrap = env.get_exe_wrapper() + + return compilers, ccache, exe_wrap + +def _handle_exceptions( + exceptions: T.Mapping[str, T.Union[Exception, str]], + binaries: T.List[T.List[str]], + bintype: str = 'compiler' + ) -> T.NoReturn: + errmsg = f'Unknown {bintype}(s): {binaries}' + if exceptions: + errmsg += '\nThe following exception(s) were encountered:' + for c, e in exceptions.items(): + errmsg += f'\nRunning "{c}" gave "{e}"' + raise EnvironmentException(errmsg) + + +# Linker specific +# =============== + +def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker: + linker = env.lookup_binary_entry(compiler.for_machine, 'ar') + if linker is not None: + linkers = [linker] + else: + default_linkers = [[l] for l in defaults['static_linker']] + if isinstance(compiler, CudaCompiler): + linkers = [defaults['cuda_static_linker']] + default_linkers + elif isinstance(compiler, VisualStudioLikeCompiler): + linkers = [defaults['vs_static_linker'], defaults['clang_cl_static_linker']] + elif isinstance(compiler, GnuCompiler): + # Use gcc-ar if available; needed for LTO + linkers = [defaults['gcc_static_linker']] + default_linkers + elif isinstance(compiler, ClangCompiler): + # Use llvm-ar if available; needed for LTO + linkers = [defaults['clang_static_linker']] + default_linkers + elif isinstance(compiler, DCompiler): + # Prefer static linkers over linkers used by D compilers + if is_windows(): + linkers = [defaults['vs_static_linker'], defaults['clang_cl_static_linker'], compiler.get_linker_exelist()] + else: + linkers = default_linkers + elif isinstance(compiler, IntelClCCompiler): + # Intel has it's own linker that acts like microsoft's lib + linkers = [['xilib']] + elif isinstance(compiler, (PGICCompiler, PGIFortranCompiler)) and is_windows(): + linkers = [['ar']] # For PGI on Windows, "ar" is just a wrapper calling link/lib. + else: + linkers = default_linkers + popen_exceptions = {} + for linker in linkers: + if not {'lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe', 'xilib', 'xilib.exe'}.isdisjoint(linker): + arg = '/?' + elif not {'ar2000', 'ar2000.exe'}.isdisjoint(linker): + arg = '?' + else: + arg = '--version' + try: + p, out, err = Popen_safe(linker + [arg]) + except OSError as e: + popen_exceptions[' '.join(linker + [arg])] = e + continue + if "xilib: executing 'lib'" in err: + return IntelVisualStudioLinker(linker, getattr(compiler, 'machine', None)) + if '/OUT:' in out.upper() or '/OUT:' in err.upper(): + return VisualStudioLinker(linker, getattr(compiler, 'machine', None)) + if 'ar-Error-Unknown switch: --version' in err: + return PGIStaticLinker(linker) + if p.returncode == 0 and ('armar' in linker or 'armar.exe' in linker): + return ArmarLinker(linker) + if 'DMD32 D Compiler' in out or 'DMD64 D Compiler' in out: + assert isinstance(compiler, DCompiler) + return DLinker(linker, compiler.arch) + if 'LDC - the LLVM D compiler' in out: + assert isinstance(compiler, DCompiler) + return DLinker(linker, compiler.arch, rsp_syntax=compiler.rsp_file_syntax()) + if 'GDC' in out and ' based on D ' in out: + assert isinstance(compiler, DCompiler) + return DLinker(linker, compiler.arch) + if err.startswith('Renesas') and ('rlink' in linker or 'rlink.exe' in linker): + return CcrxLinker(linker) + if out.startswith('GNU ar') and ('xc16-ar' in linker or 'xc16-ar.exe' in linker): + return Xc16Linker(linker) + if out.startswith('TMS320C2000') and ('ar2000' in linker or 'ar2000.exe' in linker): + return C2000Linker(linker) + if out.startswith('The CompCert'): + return CompCertLinker(linker) + if p.returncode == 0: + return ArLinker(linker) + if p.returncode == 1 and err.startswith('usage'): # OSX + return ArLinker(linker) + if p.returncode == 1 and err.startswith('Usage'): # AIX + return AIXArLinker(linker) + if p.returncode == 1 and err.startswith('ar: bad option: --'): # Solaris + return ArLinker(linker) + _handle_exceptions(popen_exceptions, linkers, 'linker') + + +# Compilers +# ========= + + +def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: MachineChoice, *, override_compiler: T.Optional[T.List[str]] = None) -> Compiler: + """Shared implementation for finding the C or C++ compiler to use. + + the override_compiler option is provided to allow compilers which use + the compiler (GCC or Clang usually) as their shared linker, to find + the linker they need. + """ + popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} + compilers, ccache, exe_wrap = _get_compilers(env, lang, for_machine) + if override_compiler is not None: + compilers = [override_compiler] + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + cls: T.Union[T.Type[CCompiler], T.Type[CPPCompiler]] + + for compiler in compilers: + if isinstance(compiler, str): + compiler = [compiler] + compiler_name = os.path.basename(compiler[0]) + + if any(os.path.basename(x) in {'cl', 'cl.exe', 'clang-cl', 'clang-cl.exe'} for x in compiler): + # Watcom C provides it's own cl.exe clone that mimics an older + # version of Microsoft's compiler. Since Watcom's cl.exe is + # just a wrapper, we skip using it if we detect its presence + # so as not to confuse Meson when configuring for MSVC. + # + # Additionally the help text of Watcom's cl.exe is paged, and + # the binary will not exit without human intervention. In + # practice, Meson will block waiting for Watcom's cl.exe to + # exit, which requires user input and thus will never exit. + if 'WATCOM' in os.environ: + def sanitize(p: str) -> str: + return os.path.normcase(os.path.abspath(p)) + + watcom_cls = [sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl')), + sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl.exe')), + sanitize(os.path.join(os.environ['WATCOM'], 'BINNT64', 'cl')), + sanitize(os.path.join(os.environ['WATCOM'], 'BINNT64', 'cl.exe')),] + found_cl = sanitize(shutil.which('cl')) + if found_cl in watcom_cls: + mlog.debug('Skipping unsupported cl.exe clone at:', found_cl) + continue + arg = '/?' + elif 'armcc' in compiler_name: + arg = '--vsn' + elif 'ccrx' in compiler_name: + arg = '-v' + elif 'xc16' in compiler_name: + arg = '--version' + elif 'ccomp' in compiler_name: + arg = '-version' + elif 'cl2000' in compiler_name: + arg = '-version' + elif compiler_name in {'icl', 'icl.exe'}: + # if you pass anything to icl you get stuck in a pager + arg = '' + else: + arg = '--version' + + try: + p, out, err = Popen_safe(compiler + [arg]) + except OSError as e: + popen_exceptions[' '.join(compiler + [arg])] = e + continue + + if 'ccrx' in compiler_name: + out = err + + full_version = out.split('\n', 1)[0] + version = search_version(out) + + guess_gcc_or_lcc: T.Optional[str] = None + if 'Free Software Foundation' in out or 'xt-' in out: + guess_gcc_or_lcc = 'gcc' + if 'e2k' in out and 'lcc' in out: + guess_gcc_or_lcc = 'lcc' + if 'Microchip Technology' in out: + # this output has "Free Software Foundation" in its version + guess_gcc_or_lcc = None + + if guess_gcc_or_lcc: + defines = _get_gnu_compiler_defines(compiler) + if not defines: + popen_exceptions[' '.join(compiler)] = 'no pre-processor defines' + continue + + if guess_gcc_or_lcc == 'lcc': + version = _get_lcc_version_from_defines(defines) + cls = ElbrusCCompiler if lang == 'c' else ElbrusCPPCompiler + else: + version = _get_gnu_version_from_defines(defines) + cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler + + linker = guess_nix_linker(env, compiler, cls, for_machine) + + return cls( + ccache + compiler, version, for_machine, is_cross, + info, exe_wrap, defines=defines, full_version=full_version, + linker=linker) + + if 'Emscripten' in out: + cls = EmscriptenCCompiler if lang == 'c' else EmscriptenCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + + # emcc requires a file input in order to pass arguments to the + # linker. It'll exit with an error code, but still print the + # linker version. Old emcc versions ignore -Wl,--version completely, + # however. We'll report "unknown version" in that case. + with tempfile.NamedTemporaryFile(suffix='.c') as f: + cmd = compiler + [cls.LINKER_PREFIX + "--version", f.name] + _, o, _ = Popen_safe(cmd) + + linker = WASMDynamicLinker( + compiler, for_machine, cls.LINKER_PREFIX, + [], version=search_version(o)) + return cls( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, linker=linker, full_version=full_version) + + 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:'. + # So, searching for the 'Component' in out although we know it is + # present in second line, as we are not sure about the + # output format in future versions + arm_ver_match = re.search('.*Component.*', out) + if arm_ver_match is None: + popen_exceptions[' '.join(compiler)] = 'version string not found' + continue + arm_ver_str = arm_ver_match.group(0) + # Override previous values + version = search_version(arm_ver_str) + full_version = arm_ver_str + cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler + linker = ArmClangDynamicLinker(for_machine, version=version) + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + return cls( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + if 'CL.EXE COMPATIBILITY' in out: + # if this is clang-cl masquerading as cl, detect it as cl, not + # clang + arg = '--version' + try: + p, out, err = Popen_safe(compiler + [arg]) + except OSError as e: + popen_exceptions[' '.join(compiler + [arg])] = e + version = search_version(out) + match = re.search('^Target: (.*?)-', out, re.MULTILINE) + if match: + target = match.group(1) + else: + target = 'unknown target' + cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler + linker = guess_win_linker(env, ['lld-link'], cls, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, target, + exe_wrap, linker=linker) + if 'clang' in out or 'Clang' in out: + linker = None + + defines = _get_clang_compiler_defines(compiler) + + # Even if the for_machine is darwin, we could be using vanilla + # clang. + if 'Apple' in out: + cls = AppleClangCCompiler if lang == 'c' else AppleClangCPPCompiler + else: + cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler + + if 'windows' in out or env.machines[for_machine].is_windows(): + # If we're in a MINGW context this actually will use a gnu + # style ld, but for clang on "real" windows we'll use + # either link.exe or lld-link.exe + try: + linker = guess_win_linker(env, compiler, cls, for_machine, invoked_directly=False) + except MesonException: + pass + if linker is None: + linker = guess_nix_linker(env, compiler, cls, for_machine) + + return cls( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, defines=defines, full_version=full_version, linker=linker) + + if 'Intel(R) C++ Intel(R)' in err: + version = search_version(err) + target = 'x86' if 'IA-32' in err else 'x86_64' + cls = IntelClCCompiler if lang == 'c' else IntelClCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = XilinkDynamicLinker(for_machine, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, target, + exe_wrap, linker=linker) + if 'Microsoft' in out or 'Microsoft' in err: + # Latest versions of Visual Studio print version + # number to stderr but earlier ones print version + # on stdout. Why? Lord only knows. + # Check both outputs to figure out version. + for lookat in [err, out]: + version = search_version(lookat) + if version != 'unknown version': + break + else: + raise EnvironmentException(f'Failed to detect MSVC compiler version: stderr was\n{err!r}') + cl_signature = lookat.split('\n')[0] + match = re.search(r'.*(x86|x64|ARM|ARM64)([^_A-Za-z0-9]|$)', cl_signature) + if match: + target = match.group(1) + else: + m = f'Failed to detect MSVC compiler target architecture: \'cl /?\' output is\n{cl_signature}' + raise EnvironmentException(m) + cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler + linker = guess_win_linker(env, ['link'], cls, for_machine) + # As of this writing, CCache does not support MSVC but sccache does. + if 'sccache' in ccache: + final_compiler = ccache + compiler + else: + final_compiler = compiler + return cls( + final_compiler, version, for_machine, is_cross, info, target, + exe_wrap, full_version=cl_signature, linker=linker) + if 'PGI Compilers' in out: + cls = PGICCompiler if lang == 'c' else PGICPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) + return cls( + ccache + compiler, version, for_machine, is_cross, + info, exe_wrap, linker=linker) + if 'NVIDIA Compilers and Tools' in out: + cls = NvidiaHPC_CCompiler if lang == 'c' else NvidiaHPC_CPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = NvidiaHPC_DynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) + return cls( + ccache + compiler, version, for_machine, is_cross, + info, exe_wrap, linker=linker) + if '(ICC)' in out: + cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler + l = guess_nix_linker(env, compiler, cls, for_machine) + return cls( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=l) + if 'ARM' in out: + cls = ArmCCompiler if lang == 'c' else ArmCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = ArmDynamicLinker(for_machine, version=version) + return cls( + ccache + compiler, version, for_machine, is_cross, + info, exe_wrap, full_version=full_version, linker=linker) + if 'RX Family' in out: + cls = CcrxCCompiler if lang == 'c' else CcrxCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = CcrxDynamicLinker(for_machine, version=version) + return cls( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Microchip Technology' in out: + cls = Xc16CCompiler if lang == 'c' else Xc16CCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = Xc16DynamicLinker(for_machine, version=version) + return cls( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'CompCert' in out: + cls = CompCertCCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = CompCertDynamicLinker(for_machine, version=version) + return cls( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'TMS320C2000 C/C++' in out: + cls = C2000CCompiler if lang == 'c' else C2000CPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = C2000DynamicLinker(compiler, for_machine, version=version) + return cls( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException(f'Unknown compiler {compilers}') + +def detect_c_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + return _detect_c_or_cpp_compiler(env, 'c', for_machine) + +def detect_cpp_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + return _detect_c_or_cpp_compiler(env, 'cpp', for_machine) + +def detect_cuda_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + popen_exceptions = {} + is_cross = env.is_cross_build(for_machine) + compilers, ccache, exe_wrap = _get_compilers(env, 'cuda', for_machine) + info = env.machines[for_machine] + for compiler in compilers: + arg = '--version' + try: + p, out, err = Popen_safe(compiler + [arg]) + except OSError as e: + popen_exceptions[' '.join(compiler + [arg])] = e + continue + # Example nvcc printout: + # + # nvcc: NVIDIA (R) Cuda compiler driver + # Copyright (c) 2005-2018 NVIDIA Corporation + # Built on Sat_Aug_25_21:08:01_CDT_2018 + # Cuda compilation tools, release 10.0, V10.0.130 + # + # search_version() first finds the "10.0" after "release", + # rather than the more precise "10.0.130" after "V". + # The patch version number is occasionally important; For + # instance, on Linux, + # - CUDA Toolkit 8.0.44 requires NVIDIA Driver 367.48 + # - CUDA Toolkit 8.0.61 requires NVIDIA Driver 375.26 + # Luckily, the "V" also makes it very simple to extract + # the full version: + version = out.strip().split('V')[-1] + cpp_compiler = detect_cpp_compiler(env, for_machine) + cls = CudaCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = CudaLinker(compiler, for_machine, CudaCompiler.LINKER_PREFIX, [], version=CudaLinker.parse_version()) + return cls(ccache + compiler, version, for_machine, is_cross, exe_wrap, host_compiler=cpp_compiler, info=info, linker=linker) + raise EnvironmentException(f'Could not find suitable CUDA compiler: "{"; ".join([" ".join(c) for c in compilers])}"') + +def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} + compilers, ccache, exe_wrap = _get_compilers(env, 'fortran', for_machine) + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + cls: T.Type[FortranCompiler] + for compiler in compilers: + for arg in ['--version', '-V']: + try: + p, out, err = Popen_safe(compiler + [arg]) + except OSError as e: + popen_exceptions[' '.join(compiler + [arg])] = e + continue + + version = search_version(out) + full_version = out.split('\n', 1)[0] + + guess_gcc_or_lcc: T.Optional[str] = None + if 'GNU Fortran' in out: + guess_gcc_or_lcc = 'gcc' + if 'e2k' in out and 'lcc' in out: + guess_gcc_or_lcc = 'lcc' + + if guess_gcc_or_lcc: + defines = _get_gnu_compiler_defines(compiler) + if not defines: + popen_exceptions[' '.join(compiler)] = 'no pre-processor defines' + continue + if guess_gcc_or_lcc == 'lcc': + version = _get_lcc_version_from_defines(defines) + cls = ElbrusFortranCompiler + linker = guess_nix_linker(env, compiler, cls, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, defines, full_version=full_version, linker=linker) + else: + version = _get_gnu_version_from_defines(defines) + cls = GnuFortranCompiler + linker = guess_nix_linker(env, compiler, cls, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, defines, full_version=full_version, linker=linker) + + if 'G95' in out: + cls = G95FortranCompiler + linker = guess_nix_linker(env, compiler, cls, for_machine) + return G95FortranCompiler( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Sun Fortran' in err: + version = search_version(err) + cls = SunFortranCompiler + linker = guess_nix_linker(env, compiler, cls, for_machine) + return SunFortranCompiler( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Intel(R) Visual Fortran' in err or 'Intel(R) Fortran' in err: + version = search_version(err) + target = 'x86' if 'IA-32' in err else 'x86_64' + cls = IntelClFortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = XilinkDynamicLinker(for_machine, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, + target, exe_wrap, linker=linker) + + if 'ifort (IFORT)' in out: + linker = guess_nix_linker(env, compiler, IntelFortranCompiler, for_machine) + return IntelFortranCompiler( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'PathScale EKOPath(tm)' in err: + return PathScaleFortranCompiler( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version) + + if 'PGI Compilers' in out: + cls = PGIFortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = PGIDynamicLinker(compiler, for_machine, + cls.LINKER_PREFIX, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, exe_wrap, + full_version=full_version, linker=linker) + + if 'NVIDIA Compilers and Tools' in out: + cls = NvidiaHPC_FortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = PGIDynamicLinker(compiler, for_machine, + cls.LINKER_PREFIX, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, exe_wrap, + full_version=full_version, linker=linker) + + if 'flang' in out or 'clang' in out: + linker = guess_nix_linker(env, + compiler, FlangFortranCompiler, for_machine) + return FlangFortranCompiler( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Open64 Compiler Suite' in err: + linker = guess_nix_linker(env, + compiler, Open64FortranCompiler, for_machine) + return Open64FortranCompiler( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'NAG Fortran' in err: + full_version = err.split('\n', 1)[0] + version = full_version.split()[-1] + cls = NAGFortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = NAGDynamicLinker( + compiler, for_machine, cls.LINKER_PREFIX, [], + version=version) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_objc_compiler(env: 'Environment', for_machine: MachineChoice) -> 'Compiler': + return _detect_objc_or_objcpp_compiler(env, for_machine, True) + +def detect_objcpp_compiler(env: 'Environment', for_machine: MachineChoice) -> 'Compiler': + return _detect_objc_or_objcpp_compiler(env, for_machine, False) + +def _detect_objc_or_objcpp_compiler(env: 'Environment', for_machine: MachineChoice, objc: bool) -> 'Compiler': + popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} + compilers, ccache, exe_wrap = _get_compilers(env, 'objc' if objc else 'objcpp', for_machine) + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + comp: T.Union[T.Type[ObjCCompiler], T.Type[ObjCPPCompiler]] + + for compiler in compilers: + arg = ['--version'] + try: + p, out, err = Popen_safe(compiler + arg) + except OSError as e: + popen_exceptions[' '.join(compiler + arg)] = e + continue + version = search_version(out) + if 'Free Software Foundation' in out: + defines = _get_gnu_compiler_defines(compiler) + if not defines: + popen_exceptions[' '.join(compiler)] = 'no pre-processor defines' + continue + version = _get_gnu_version_from_defines(defines) + comp = GnuObjCCompiler if objc else GnuObjCPPCompiler + linker = guess_nix_linker(env, compiler, comp, for_machine) + return comp( + ccache + compiler, version, for_machine, is_cross, info, + exe_wrap, defines, linker=linker) + if 'clang' in out: + linker = None + defines = _get_clang_compiler_defines(compiler) + if not defines: + popen_exceptions[' '.join(compiler)] = 'no pre-processor defines' + continue + if 'Apple' in out: + comp = AppleClangObjCCompiler if objc else AppleClangObjCPPCompiler + else: + comp = ClangObjCCompiler if objc else ClangObjCPPCompiler + if 'windows' in out or env.machines[for_machine].is_windows(): + # If we're in a MINGW context this actually will use a gnu style ld + try: + linker = guess_win_linker(env, compiler, comp, for_machine) + except MesonException: + pass + + if not linker: + linker = guess_nix_linker(env, compiler, comp, for_machine) + return comp( + ccache + compiler, version, for_machine, + is_cross, info, exe_wrap, linker=linker, defines=defines) + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_java_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + exelist = env.lookup_binary_entry(for_machine, 'java') + info = env.machines[for_machine] + if exelist is None: + # TODO support fallback + exelist = [defaults['java'][0]] + + try: + p, out, err = Popen_safe(exelist + ['-version']) + except OSError: + raise EnvironmentException('Could not execute Java compiler "{}"'.format(' '.join(exelist))) + if 'javac' in out or 'javac' in err: + version = search_version(err if 'javac' in err else out) + if not version or version == 'unknown version': + parts = (err if 'javac' in err else out).split() + if len(parts) > 1: + version = parts[1] + comp_class = JavaCompiler + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class(exelist, version, for_machine, info) + raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') + +def detect_cs_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + compilers, ccache, exe_wrap = _get_compilers(env, 'cs', for_machine) + popen_exceptions = {} + info = env.machines[for_machine] + for comp in compilers: + try: + p, out, err = Popen_safe(comp + ['--version']) + except OSError as e: + popen_exceptions[' '.join(comp + ['--version'])] = e + continue + + version = search_version(out) + cls: T.Union[T.Type[MonoCompiler], T.Type[VisualStudioCsCompiler]] + if 'Mono' in out: + cls = MonoCompiler + elif "Visual C#" in out: + cls = VisualStudioCsCompiler + else: + continue + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + return cls(comp, version, for_machine, info) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_cython_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + """Search for a cython compiler.""" + compilers, _, _ = _get_compilers(env, 'cython', for_machine) + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + + popen_exceptions: T.Dict[str, Exception] = {} + for comp in compilers: + try: + err = Popen_safe(comp + ['-V'])[2] + except OSError as e: + popen_exceptions[' '.join(comp + ['-V'])] = e + continue + + version = search_version(err) + if 'Cython' in err: + comp_class = CythonCompiler + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class(comp, version, for_machine, info, is_cross=is_cross) + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_vala_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + exelist = env.lookup_binary_entry(for_machine, 'vala') + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + if exelist is None: + # TODO support fallback + exelist = [defaults['vala'][0]] + + try: + p, out = Popen_safe(exelist + ['--version'])[0:2] + except OSError: + raise EnvironmentException('Could not execute Vala compiler "{}"'.format(' '.join(exelist))) + version = search_version(out) + if 'Vala' in out: + comp_class = ValaCompiler + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class(exelist, version, for_machine, is_cross, info) + raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') + +def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> RustCompiler: + popen_exceptions = {} # type: T.Dict[str, Exception] + compilers, _, exe_wrap = _get_compilers(env, 'rust', for_machine) + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + + cc = detect_c_compiler(env, for_machine) + is_link_exe = isinstance(cc.linker, VisualStudioLikeLinkerMixin) + override = env.lookup_binary_entry(for_machine, 'rust_ld') + + for compiler in compilers: + arg = ['--version'] + try: + out = Popen_safe(compiler + arg)[1] + except OSError as e: + popen_exceptions[' '.join(compiler + arg)] = e + continue + + version = search_version(out) + cls: T.Type[RustCompiler] = RustCompiler + + # Clippy is a wrapper around rustc, but it doesn't have rustc in it's + # output. We can otherwise treat it as rustc. + if 'clippy' in out: + out = 'rustc' + cls = ClippyRustCompiler + + if 'rustc' in out: + # On Linux and mac rustc will invoke gcc (clang for mac + # presumably) and it can do this windows, for dynamic linking. + # this means the easiest way to C compiler for dynamic linking. + # figure out what linker to use is to just get the value of the + # C compiler and use that as the basis of the rust linker. + # However, there are two things we need to change, if CC is not + # the default use that, and second add the necessary arguments + # to rust to use -fuse-ld + + if any(a.startswith('linker=') for a in compiler): + mlog.warning( + 'Please do not put -C linker= in your compiler ' + 'command, set rust_ld=command in your cross file ' + 'or use the RUST_LD environment variable, otherwise meson ' + 'will override your selection.') + + compiler = compiler.copy() # avoid mutating the original list + + if override is None: + extra_args: T.Dict[str, T.Union[str, bool]] = {} + always_args: T.List[str] = [] + if is_link_exe: + compiler.extend(cls.use_linker_args(cc.linker.exelist[0])) + extra_args['direct'] = True + extra_args['machine'] = cc.linker.machine + else: + exelist = cc.linker.exelist + cc.linker.get_always_args() + if 'ccache' in exelist[0]: + del exelist[0] + c = exelist.pop(0) + compiler.extend(cls.use_linker_args(c)) + + # Also ensure that we pass any extra arguments to the linker + for l in exelist: + compiler.extend(['-C', f'link-arg={l}']) + + # This trickery with type() gets us the class of the linker + # so we can initialize a new copy for the Rust Compiler + # TODO rewrite this without type: ignore + if is_link_exe: + linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist, # type: ignore + version=cc.linker.version, **extra_args) # type: ignore + else: + linker = type(cc.linker)(compiler, for_machine, cc.LINKER_PREFIX, + always_args=always_args, version=cc.linker.version, + **extra_args) # type: ignore + elif 'link' in override[0]: + linker = guess_win_linker(env, + override, cls, for_machine, use_linker_prefix=False) + # rustc takes linker arguments without a prefix, and + # inserts the correct prefix itself. + assert isinstance(linker, VisualStudioLikeLinkerMixin) + linker.direct = True + compiler.extend(cls.use_linker_args(linker.exelist[0])) + else: + # On linux and macos rust will invoke the c compiler for + # linking, on windows it will use lld-link or link.exe. + # we will simply ask for the C compiler that corresponds to + # it, and use that. + cc = _detect_c_or_cpp_compiler(env, 'c', for_machine, override_compiler=override) + linker = cc.linker + + # Of course, we're not going to use any of that, we just + # need it to get the proper arguments to pass to rustc + c = linker.exelist[1] if linker.exelist[0].endswith('ccache') else linker.exelist[0] + compiler.extend(cls.use_linker_args(c)) + + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + return cls( + compiler, version, for_machine, is_cross, info, exe_wrap, + linker=linker) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + info = env.machines[for_machine] + + # Detect the target architecture, required for proper architecture handling on Windows. + # MSVC compiler is required for correct platform detection. + c_compiler = {'c': detect_c_compiler(env, for_machine)} + is_msvc = isinstance(c_compiler['c'], VisualStudioCCompiler) + if not is_msvc: + c_compiler = {} + + # Import here to avoid circular imports + from ..environment import detect_cpu_family + arch = detect_cpu_family(c_compiler) + if is_msvc and arch == 'x86': + arch = 'x86_mscoff' + + popen_exceptions = {} + is_cross = env.is_cross_build(for_machine) + compilers, ccache, exe_wrap = _get_compilers(env, 'd', for_machine) + for exelist in compilers: + # Search for a D compiler. + # We prefer LDC over GDC unless overridden with the DC + # environment variable because LDC has a much more + # up to date language version at time (2016). + if os.path.basename(exelist[-1]).startswith(('ldmd', 'gdmd')): + raise EnvironmentException( + f'Meson does not support {exelist[-1]} as it is only a DMD frontend for another compiler.' + 'Please provide a valid value for DC or unset it so that Meson can resolve the compiler by itself.') + try: + p, out = Popen_safe(exelist + ['--version'])[0:2] + except OSError as e: + popen_exceptions[' '.join(exelist + ['--version'])] = e + continue + version = search_version(out) + full_version = out.split('\n', 1)[0] + + if 'LLVM D compiler' in out: + # LDC seems to require a file + # We cannot use NamedTemproraryFile on windows, its documented + # to not work for our uses. So, just use mkstemp and only have + # one path for simplicity. + o, f = tempfile.mkstemp('.d') + os.close(o) + + try: + if info.is_windows() or info.is_cygwin(): + objfile = os.path.basename(f)[:-1] + 'obj' + linker = guess_win_linker(env, + exelist, + LLVMDCompiler, for_machine, + use_linker_prefix=True, invoked_directly=False, + extra_args=[f]) + else: + # LDC writes an object file to the current working directory. + # Clean it up. + objfile = os.path.basename(f)[:-1] + 'o' + linker = guess_nix_linker(env, + exelist, LLVMDCompiler, for_machine, + extra_args=[f]) + finally: + windows_proof_rm(f) + windows_proof_rm(objfile) + + return LLVMDCompiler( + exelist, version, for_machine, info, arch, + full_version=full_version, linker=linker, version_output=out) + elif 'gdc' in out: + linker = guess_nix_linker(env, exelist, GnuDCompiler, for_machine) + return GnuDCompiler( + exelist, version, for_machine, info, arch, + exe_wrapper=exe_wrap, is_cross=is_cross, + full_version=full_version, linker=linker) + elif 'The D Language Foundation' in out or 'Digital Mars' in out: + # DMD seems to require a file + # We cannot use NamedTemproraryFile on windows, its documented + # to not work for our uses. So, just use mkstemp and only have + # one path for simplicity. + o, f = tempfile.mkstemp('.d') + os.close(o) + + # DMD as different detection logic for x86 and x86_64 + arch_arg = '-m64' if arch == 'x86_64' else '-m32' + + try: + if info.is_windows() or info.is_cygwin(): + objfile = os.path.basename(f)[:-1] + 'obj' + linker = guess_win_linker(env, + exelist, DmdDCompiler, for_machine, + invoked_directly=False, extra_args=[f, arch_arg]) + else: + objfile = os.path.basename(f)[:-1] + 'o' + linker = guess_nix_linker(env, + exelist, DmdDCompiler, for_machine, + extra_args=[f, arch_arg]) + finally: + windows_proof_rm(f) + windows_proof_rm(objfile) + + return DmdDCompiler( + exelist, version, for_machine, info, arch, + full_version=full_version, linker=linker) + raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_swift_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + exelist = env.lookup_binary_entry(for_machine, 'swift') + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + if exelist is None: + # TODO support fallback + exelist = [defaults['swift'][0]] + + try: + p, _, err = Popen_safe(exelist + ['-v']) + except OSError: + raise EnvironmentException('Could not execute Swift compiler "{}"'.format(' '.join(exelist))) + version = search_version(err) + if 'Swift' in err: + # As for 5.0.1 swiftc *requires* a file to check the linker: + with tempfile.NamedTemporaryFile(suffix='.swift') as f: + linker = guess_nix_linker(env, + exelist, SwiftCompiler, for_machine, + extra_args=[f.name]) + return SwiftCompiler( + exelist, version, for_machine, is_cross, info, linker=linker) + + raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') + + +# GNU/Clang defines and version +# ============================= + +def _get_gnu_compiler_defines(compiler: T.List[str]) -> T.Dict[str, str]: + """ + Detect GNU compiler platform type (Apple, MinGW, Unix) + """ + # Arguments to output compiler pre-processor defines to stdout + # gcc, g++, and gfortran all support these arguments + args = compiler + ['-E', '-dM', '-'] + p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE) + if p.returncode != 0: + raise EnvironmentException('Unable to detect GNU compiler type:\n' + output + error) + # Parse several lines of the type: + # `#define ___SOME_DEF some_value` + # and extract `___SOME_DEF` + defines: T.Dict[str, str] = {} + for line in output.split('\n'): + if not line: + continue + d, *rest = line.split(' ', 2) + if d != '#define': + continue + if len(rest) == 1: + defines[rest[0]] = '' + if len(rest) == 2: + defines[rest[0]] = rest[1] + return defines + +def _get_clang_compiler_defines(compiler: T.List[str]) -> T.Dict[str, str]: + """ + Get the list of Clang pre-processor defines + """ + args = compiler + ['-E', '-dM', '-'] + p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE) + if p.returncode != 0: + raise EnvironmentException('Unable to get clang pre-processor defines:\n' + output + error) + defines: T.Dict[str, str] = {} + for line in output.split('\n'): + if not line: + continue + d, *rest = line.split(' ', 2) + if d != '#define': + continue + if len(rest) == 1: + defines[rest[0]] = '' + if len(rest) == 2: + defines[rest[0]] = rest[1] + return defines + +def _get_gnu_version_from_defines(defines: T.Dict[str, str]) -> str: + dot = '.' + major = defines.get('__GNUC__', '0') + minor = defines.get('__GNUC_MINOR__', '0') + patch = defines.get('__GNUC_PATCHLEVEL__', '0') + return dot.join((major, minor, patch)) + +def _get_lcc_version_from_defines(defines: T.Dict[str, str]) -> str: + dot = '.' + generation_and_major = defines.get('__LCC__', '100') + generation = generation_and_major[:1] + major = generation_and_major[1:] + minor = defines.get('__LCC_MINOR__', '0') + return dot.join((generation, major, minor)) diff -Nru meson-0.53.2/mesonbuild/compilers/d.py meson-0.61.2/mesonbuild/compilers/d.py --- meson-0.53.2/mesonbuild/compilers/d.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/d.py 2022-02-14 19:03:13.000000000 +0000 @@ -12,26 +12,35 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os.path, subprocess +import os.path +import re +import subprocess import typing as T from ..mesonlib import ( - EnvironmentException, MachineChoice, version_compare, + EnvironmentException, MachineChoice, version_compare, OptionKey, is_windows ) +from ..arglist import CompilerArgs +from ..linkers import RSPFileSyntax from .compilers import ( d_dmd_buildtype_args, d_gdc_buildtype_args, d_ldc_buildtype_args, clike_debug_args, Compiler, - CompilerArgs, ) from .mixins.gnu import GnuCompiler -from .mixins.islinker import LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin if T.TYPE_CHECKING: + from ..programs import ExternalProgram from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers import DynamicLinker + + CompilerMixinBase = Compiler +else: + CompilerMixinBase = object d_feature_args = {'gcc': {'unittest': '-funittest', 'debug': '-fdebug', @@ -48,15 +57,15 @@ 'version': '-version', 'import_dir': '-J' } - } + } # type: T.Dict[str, T.Dict[str, str]] ldc_optimization_args = {'0': [], 'g': [], '1': ['-O1'], '2': ['-O2'], '3': ['-O3'], - 's': ['-Os'], - } + 's': ['-Oz'], + } # type: T.Dict[str, T.List[str]] dmd_optimization_args = {'0': [], 'g': [], @@ -64,23 +73,44 @@ '2': ['-O'], '3': ['-O'], 's': ['-O'], - } + } # type: T.Dict[str, T.List[str]] + + +class DmdLikeCompilerMixin(CompilerMixinBase): + + """Mixin class for DMD and LDC. + LDC has a number of DMD like arguments, and this class allows for code + sharing between them as makes sense. + """ -class DmdLikeCompilerMixin: + def __init__(self, dmd_frontend_version: T.Optional[str]): + if dmd_frontend_version is None: + self._dmd_has_depfile = False + else: + # -makedeps switch introduced in 2.095 frontend + self._dmd_has_depfile = version_compare(dmd_frontend_version, ">=2.095.0") + + if T.TYPE_CHECKING: + mscrt_args = {} # type: T.Dict[str, T.List[str]] - LINKER_PREFIX = '-L' + def _get_target_arch_args(self) -> T.List[str]: ... - def get_output_args(self, target): - return ['-of=' + target] + LINKER_PREFIX = '-L=' - def get_linker_output_args(self, target): - return ['-of=' + target] + def get_output_args(self, outputname: str) -> T.List[str]: + return ['-of=' + outputname] - def get_include_args(self, path, is_system): + def get_linker_output_args(self, outputname: str) -> T.List[str]: + return ['-of=' + outputname] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == "": + path = "." return ['-I=' + path] - def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): if i[:3] == '-I=': parameter_list[idx] = i[:3] + os.path.normpath(os.path.join(build_dir, i[3:])) @@ -93,38 +123,43 @@ return parameter_list - def get_warn_args(self, level): + def get_warn_args(self, level: str) -> T.List[str]: return ['-wi'] - def get_werror_args(self): + def get_werror_args(self) -> T.List[str]: return ['-w'] - def get_dependency_gen_args(self, outtarget, outfile): - # DMD and LDC does not currently return Makefile-compatible dependency info. - return [] - - def get_coverage_args(self): + def get_coverage_args(self) -> T.List[str]: return ['-cov'] - def get_preprocess_only_args(self): + def get_coverage_link_args(self) -> T.List[str]: + return [] + + def get_preprocess_only_args(self) -> T.List[str]: return ['-E'] - def get_compile_only_args(self): + def get_compile_only_args(self) -> T.List[str]: return ['-c'] - def depfile_for_object(self, objfile): - return objfile + '.' + self.get_depfile_suffix() - - def get_depfile_suffix(self): + def get_depfile_suffix(self) -> str: return 'deps' - def get_pic_args(self): + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + if self._dmd_has_depfile: + return [f'-makedeps={outfile}'] + return [] + + def get_pic_args(self) -> T.List[str]: if self.info.is_windows(): return [] return ['-fPIC'] - def get_feature_args(self, kwargs, build_to_src): + def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: + # TODO: using a TypeDict here would improve this res = [] + # get_feature_args can be called multiple times for the same target when there is generated source + # so we have to copy the kwargs (target.d_features) dict before popping from it + kwargs = kwargs.copy() if 'unittest' in kwargs: unittest = kwargs.pop('unittest') unittest_arg = d_feature_args[self.id]['unittest'] @@ -152,10 +187,10 @@ if int(d) > debug_level: debug_level = int(d) else: - res.append('{0}={1}'.format(debug_arg, d)) + res.append(f'{debug_arg}={d}') if debug_level >= 0: - res.append('{0}={1}'.format(debug_arg, debug_level)) + res.append(f'{debug_arg}={debug_level}') if 'versions' in kwargs: version_level = -1 @@ -176,10 +211,10 @@ if int(v) > version_level: version_level = int(v) else: - res.append('{0}={1}'.format(version_arg, v)) + res.append(f'{version_arg}={v}') if version_level >= 0: - res.append('{0}={1}'.format(version_arg, version_level)) + res.append(f'{version_arg}={version_level}') if 'import_dirs' in kwargs: import_dirs = kwargs.pop('import_dirs') @@ -192,62 +227,74 @@ for idir_obj in import_dirs: basedir = idir_obj.get_curdir() for idir in idir_obj.get_incdirs(): + bldtreedir = os.path.join(basedir, idir) # Avoid superfluous '/.' at the end of paths when d is '.' if idir not in ('', '.'): - expdir = os.path.join(basedir, idir) + expdir = bldtreedir else: expdir = basedir srctreedir = os.path.join(build_to_src, expdir) - res.append('{0}{1}'.format(import_dir_arg, srctreedir)) + res.append(f'{import_dir_arg}{srctreedir}') + res.append(f'{import_dir_arg}{bldtreedir}') if kwargs: raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys())) return res - def get_buildtype_linker_args(self, buildtype): + def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: if buildtype != 'plain': - return self.get_target_arch_args() + return self._get_target_arch_args() return [] - def get_std_exe_link_args(self): - return [] + def gen_import_library_args(self, implibname: str) -> T.List[str]: + return self.linker.import_library_args(implibname) - def gen_import_library_args(self, implibname): - return ['-Wl,--out-implib=' + implibname] - - def build_rpath_args(self, env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: 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 [] + return ([], set()) - # This method is to be used by LDC and DMD. - # GDC can deal with the verbatim flags. - if not rpath_paths and not install_rpath: - return [] - paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) - if build_rpath != '': - paths += ':' + build_rpath - if len(paths) < len(install_rpath): - padding = 'X' * (len(install_rpath) - len(paths)) - if not paths: - paths = padding - else: - paths = paths + ':' + padding - return ['-Wl,-rpath,{}'.format(paths)] + # GNU ld, solaris ld, and lld acting like GNU ld + if self.linker.id.startswith('ld'): + # The way that dmd and ldc pass rpath to gcc is different than we would + # do directly, each argument -rpath and the value to rpath, need to be + # split into two separate arguments both prefaced with the -L=. + args = [] + (rpath_args, rpath_dirs_to_remove) = super().build_rpath_args( + env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) + for r in rpath_args: + if ',' in r: + a, b = r.split(',', maxsplit=1) + args.append(a) + args.append(self.LINKER_PREFIX + b) + else: + args.append(r) + return (args, rpath_dirs_to_remove) - def translate_args_to_nongnu(self, args): - dcargs = [] + return super().build_rpath_args( + env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) + + def _translate_args_to_nongnu(self, args: T.List[str]) -> T.List[str]: # Translate common arguments to flags the LDC/DMD compilers # can understand. # The flags might have been added by pkg-config files, # and are therefore out of the user's control. + dcargs = [] + # whether we hit a linker argument that expect another arg + # see the comment in the "-L" section + link_expect_arg = False + link_flags_with_arg = [ + '-rpath', '-soname', '-compatibility_version', '-current_version', + ] for arg in args: # Translate OS specific arguments first. - osargs = [] + osargs = [] # type: T.List[str] if self.info.is_windows(): osargs = self.translate_arg_to_windows(arg) elif self.info.is_darwin(): - osargs = self.translate_arg_to_osx(arg) + osargs = self._translate_arg_to_osx(arg) if osargs: dcargs.extend(osargs) continue @@ -295,23 +342,51 @@ else: dcargs.append('-I' + arg[10:]) continue - elif arg.startswith('-L/') or arg.startswith('-L./'): - # we need to handle cases where -L is set by e.g. a pkg-config - # setting to select a linker search path. We can however not - # unconditionally prefix '-L' with '-L' because the user might - # have set this flag too to do what it is intended to for this - # compiler (pass flag through to the linker) - # Hence, we guess here whether the flag was intended to pass - # a linker search path. + elif arg.startswith('-L'): + # The D linker expect library search paths in the form of -L=-L/path (the '=' is optional). + # + # This function receives a mix of arguments already prepended + # with -L for the D linker driver and other linker arguments. + # The arguments starting with -L can be: + # - library search path (with or without a second -L) + # - it can come from pkg-config (a single -L) + # - or from the user passing linker flags (-L-L would be expected) + # - arguments like "-L=-rpath" that expect a second argument (also prepended with -L) + # - arguments like "-L=@rpath/xxx" without a second argument (on Apple platform) + # - arguments like "-L=/SUBSYSTEM:CONSOLE (for Windows linker) + # + # The logic that follows tries to detect all these cases (some may be missing) + # in order to prepend a -L only for the library search paths with a single -L + + if arg.startswith('-L='): + suffix = arg[3:] + else: + suffix = arg[2:] + + if link_expect_arg: + # flags like rpath and soname expect a path or filename respectively, + # we must not alter it (i.e. prefixing with -L for a lib search path) + dcargs.append(arg) + link_expect_arg = False + continue + + if suffix in link_flags_with_arg: + link_expect_arg = True + + if suffix.startswith('-') or suffix.startswith('@'): + # this is not search path + dcargs.append(arg) + continue + + # linker flag such as -L=/DEBUG must pass through + if self.linker.id == 'link' and self.info.is_windows() and suffix.startswith('/'): + dcargs.append(arg) + continue # Make sure static library files are passed properly to the linker. if arg.endswith('.a') or arg.endswith('.lib'): - if arg.startswith('-L='): - farg = arg[3:] - else: - farg = arg[2:] - if len(farg) > 0 and not farg.startswith('-'): - dcargs.append('-L=' + farg) + if len(suffix) > 0 and not suffix.startswith('-'): + dcargs.append('-L=' + suffix) continue dcargs.append('-L=' + arg) @@ -326,7 +401,7 @@ return dcargs @classmethod - def translate_arg_to_windows(cls, arg): + def translate_arg_to_windows(cls, arg: str) -> T.List[str]: args = [] if arg.startswith('-Wl,'): # Translate linker arguments here. @@ -352,57 +427,91 @@ return args @classmethod - def translate_arg_to_osx(cls, arg): + def _translate_arg_to_osx(cls, arg: str) -> T.List[str]: args = [] if arg.startswith('-install_name'): args.append('-L=' + arg) return args - def get_debug_args(self, is_debug): + def get_debug_args(self, is_debug: bool) -> T.List[str]: ddebug_args = [] if is_debug: ddebug_args = [d_feature_args[self.id]['debug']] return clike_debug_args[is_debug] + ddebug_args - def get_crt_args(self, crt_val, buildtype): + def _get_crt_args(self, crt_val: str, buildtype: str) -> T.List[str]: if not self.info.is_windows(): return [] if crt_val in self.mscrt_args: return self.mscrt_args[crt_val] - assert(crt_val == 'from_buildtype') + assert crt_val in ['from_buildtype', 'static_from_buildtype'] + + dbg = 'mdd' + rel = 'md' + if crt_val == 'static_from_buildtype': + dbg = 'mtd' + rel = 'mt' # Match what build type flags used to do. if buildtype == 'plain': return [] elif buildtype == 'debug': - return self.mscrt_args['mdd'] + return self.mscrt_args[dbg] elif buildtype == 'debugoptimized': - return self.mscrt_args['md'] + return self.mscrt_args[rel] elif buildtype == 'release': - return self.mscrt_args['md'] + return self.mscrt_args[rel] elif buildtype == 'minsize': - return self.mscrt_args['md'] + return self.mscrt_args[rel] else: - assert(buildtype == 'custom') + assert buildtype == 'custom' raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') - def get_soname_args(self, *args, **kwargs) -> T.List[str]: + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, + darwin_versions: T.Tuple[str, str]) -> T.List[str]: + sargs = super().get_soname_args(env, prefix, shlib_name, suffix, + soversion, darwin_versions) + # LDC and DMD actually do use a linker, but they proxy all of that with # their own arguments - soargs = [] - for arg in Compiler.get_soname_args(self, *args, **kwargs): - soargs.append('-L=' + arg) - return soargs + if self.linker.id.startswith('ld.'): + soargs = [] + for arg in sargs: + a, b = arg.split(',', maxsplit=1) + soargs.append(a) + soargs.append(self.LINKER_PREFIX + b) + return soargs + elif self.linker.id.startswith('ld64'): + soargs = [] + for arg in sargs: + if not arg.startswith(self.LINKER_PREFIX): + soargs.append(self.LINKER_PREFIX + arg) + else: + soargs.append(arg) + return soargs + else: + return sargs def get_allow_undefined_link_args(self) -> T.List[str]: - args = [] - for arg in self.linker.get_allow_undefined_args(): - args.append('-L=' + arg) + args = self.linker.get_allow_undefined_args() + if self.info.is_darwin(): + # On macOS we're passing these options to the C compiler, but + # they're linker options and need -Wl, so clang/gcc knows what to + # do with them. I'm assuming, but don't know for certain, that + # ldc/dmd do some kind of mapping internally for arguments they + # understand, but pass arguments they don't understand directly. + args = [a.replace('-L=', '-Xcc=-Wl,') for a in args] return args +class DCompilerArgs(CompilerArgs): + prepend_prefixes = ('-I', '-L') + dedup2_prefixes = ('-I', ) + + class DCompiler(Compiler): mscrt_args = { 'none': ['-mscrtlib='], @@ -414,20 +523,23 @@ language = 'd' - def __init__(self, exelist, version, for_machine: MachineChoice, - info: 'MachineInfo', arch, is_cross, exe_wrapper, **kwargs): - super().__init__(exelist, version, for_machine, info, **kwargs) - self.id = 'unknown' + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', arch: str, *, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, + is_cross: bool = False): + super().__init__(exelist, version, for_machine, info, linker=linker, + full_version=full_version, is_cross=is_cross) self.arch = arch self.exe_wrapper = exe_wrapper - self.is_cross = is_cross - def sanity_check(self, work_dir, environment): + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: source_name = os.path.join(work_dir, 'sanity.d') output_name = os.path.join(work_dir, 'dtest') - with open(source_name, 'w') as ofile: + with open(source_name, 'w', encoding='utf-8') as ofile: ofile.write('''void main() { }''') - pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + self.get_target_arch_args() + [source_name], cwd=work_dir) + pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + self._get_target_arch_args() + [source_name], cwd=work_dir) pc.wait() if pc.returncode != 0: raise EnvironmentException('D compiler %s can not compile programs.' % self.name_string()) @@ -441,22 +553,23 @@ if subprocess.call(cmdlist) != 0: raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string()) - def needs_static_linker(self): + def needs_static_linker(self) -> bool: return True - def depfile_for_object(self, objfile): - return objfile + '.' + self.get_depfile_suffix() - - def get_depfile_suffix(self): + def get_depfile_suffix(self) -> str: return 'deps' - def get_pic_args(self): + def get_pic_args(self) -> T.List[str]: if self.info.is_windows(): return [] return ['-fPIC'] - def get_feature_args(self, kwargs, build_to_src): + def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: + # TODO: using a TypeDict here would improve this res = [] + # get_feature_args can be called multiple times for the same target when there is generated source + # so we have to copy the kwargs (target.d_features) dict before popping from it + kwargs = kwargs.copy() if 'unittest' in kwargs: unittest = kwargs.pop('unittest') unittest_arg = d_feature_args[self.id]['unittest'] @@ -484,10 +597,10 @@ if int(d) > debug_level: debug_level = int(d) else: - res.append('{0}={1}'.format(debug_arg, d)) + res.append(f'{debug_arg}={d}') if debug_level >= 0: - res.append('{0}={1}'.format(debug_arg, debug_level)) + res.append(f'{debug_arg}={debug_level}') if 'versions' in kwargs: version_level = -1 @@ -508,10 +621,10 @@ if int(v) > version_level: version_level = int(v) else: - res.append('{0}={1}'.format(version_arg, v)) + res.append(f'{version_arg}={v}') if version_level >= 0: - res.append('{0}={1}'.format(version_arg, version_level)) + res.append(f'{version_arg}={version_level}') if 'import_dirs' in kwargs: import_dirs = kwargs.pop('import_dirs') @@ -524,67 +637,33 @@ for idir_obj in import_dirs: basedir = idir_obj.get_curdir() for idir in idir_obj.get_incdirs(): + bldtreedir = os.path.join(basedir, idir) # Avoid superfluous '/.' at the end of paths when d is '.' if idir not in ('', '.'): - expdir = os.path.join(basedir, idir) + expdir = bldtreedir else: expdir = basedir srctreedir = os.path.join(build_to_src, expdir) - res.append('{0}{1}'.format(import_dir_arg, srctreedir)) + res.append(f'{import_dir_arg}{srctreedir}') + res.append(f'{import_dir_arg}{bldtreedir}') if kwargs: raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys())) return res - def get_buildtype_linker_args(self, buildtype): + def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: if buildtype != 'plain': - return self.get_target_arch_args() + return self._get_target_arch_args() return [] - def get_std_exe_link_args(self): - return [] + def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> DCompilerArgs: + return DCompilerArgs(self, args) - def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): - if callable(extra_args): - extra_args = extra_args(mode) - if extra_args is None: - extra_args = [] - elif isinstance(extra_args, str): - extra_args = [extra_args] - if dependencies is None: - dependencies = [] - elif not isinstance(dependencies, list): - dependencies = [dependencies] - # Collect compiler arguments - args = CompilerArgs(self) - for d in dependencies: - # Add compile flags needed by dependencies - args += d.get_compile_args() - if mode == 'link': - # Add link flags needed to find dependencies - args += d.get_link_args() - - if mode == 'compile': - # Add DFLAGS from the env - args += env.coredata.get_external_args(self.for_machine, self.language) - elif mode == 'link': - # Add LDFLAGS from the env - args += env.coredata.get_external_link_args(self.for_machine, self.language) - # extra_args must override all other arguments, so we add them last - args += extra_args - return args - - def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'): - args = self._get_compiler_check_args(env, extra_args, dependencies, mode) - - with self.cached_compile(code, env.coredata, extra_args=args, mode=mode) as p: - return p.returncode == 0, p.cached - - def has_multi_arguments(self, args, env): + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: return self.compiles('int i;\n', env, extra_args=args) - def get_target_arch_args(self): + def _get_target_arch_args(self) -> T.List[str]: # LDC2 on Windows targets to current OS architecture, but # it should follow the target specified by the MSVC toolchain. if self.info.is_windows(): @@ -593,27 +672,27 @@ return ['-m32'] return [] - def get_crt_compile_args(self, crt_val, buildtype): + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: return [] - def get_crt_link_args(self, crt_val, buildtype): + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: return [] - def thread_link_flags(self, env): - return ['-pthread'] - def name_string(self): - return ' '.join(self.exelist) - - -class GnuDCompiler(DCompiler, GnuCompiler): +class GnuDCompiler(GnuCompiler, DCompiler): # we mostly want DCompiler, but that gives us the Compiler.LINKER_PREFIX instead LINKER_PREFIX = GnuCompiler.LINKER_PREFIX - def __init__(self, exelist, version, for_machine: MachineChoice, - info: 'MachineInfo', is_cross, exe_wrapper, arch, **kwargs): - DCompiler.__init__(self, exelist, version, for_machine, info, is_cross, exe_wrapper, arch, **kwargs) + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', arch: str, *, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, + is_cross: bool = False): + DCompiler.__init__(self, exelist, version, for_machine, info, arch, + 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'] @@ -621,33 +700,34 @@ '1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} - self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic', 'b_vscrt'] + self.base_options = { + OptionKey(o) for o in [ + 'b_colorout', 'b_sanitize', 'b_staticpic', 'b_vscrt', + 'b_coverage', 'b_pgo', 'b_ndebug']} self._has_color_support = version_compare(self.version, '>=4.9') # dependencies were implemented before, but broken - support was fixed in GCC 7.1+ # (and some backported versions) self._has_deps_support = version_compare(self.version, '>=7.1') - def get_colorout_args(self, colortype): + def get_colorout_args(self, colortype: str) -> T.List[str]: if self._has_color_support: super().get_colorout_args(colortype) return [] - def get_dependency_gen_args(self, outtarget, outfile): + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: if self._has_deps_support: return super().get_dependency_gen_args(outtarget, outfile) return [] - def get_warn_args(self, level): + def get_warn_args(self, level: str) -> T.List[str]: return self.warn_args[level] - def get_coverage_args(self): - return [] - - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> T.List[str]: return d_gdc_buildtype_args[buildtype] - def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): if i[:2] == '-I' or i[:2] == '-L': parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) @@ -657,68 +737,119 @@ def get_allow_undefined_link_args(self) -> T.List[str]: return self.linker.get_allow_undefined_args() + def get_linker_always_args(self) -> T.List[str]: + args = super().get_linker_always_args() + if self.info.is_windows(): + return args + return args + ['-shared-libphobos'] -class LLVMDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin, DCompiler): + def get_disable_assert_args(self) -> T.List[str]: + return ['-frelease'] - def __init__(self, exelist, version, for_machine: MachineChoice, - info: 'MachineInfo', arch, **kwargs): - DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs) +# LDC uses the DMD frontend code to parse and analyse the code. +# It then uses LLVM for the binary code generation and optimizations. +# This function retrieves the dmd frontend version, which determines +# the common features between LDC and DMD. +# We need the complete version text because the match is not on first line +# of version_output +def find_ldc_dmd_frontend_version(version_output: T.Optional[str]) -> T.Optional[str]: + if version_output is None: + return None + version_regex = re.search(r'DMD v(\d+\.\d+\.\d+)', version_output) + if version_regex: + return version_regex.group(1) + return None + +class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler): + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', arch: str, *, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, + is_cross: bool = False, version_output: T.Optional[str] = None): + DCompiler.__init__(self, exelist, version, for_machine, info, arch, + 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 = ['b_coverage', 'b_colorout', 'b_vscrt'] + self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} - def get_colorout_args(self, colortype): + def get_colorout_args(self, colortype: str) -> T.List[str]: if colortype == 'always': return ['-enable-color'] return [] - def get_warn_args(self, level): - if level == '2' or level == '3': + def get_warn_args(self, level: str) -> T.List[str]: + if level in {'2', '3'}: return ['-wi', '-dw'] elif level == '1': return ['-wi'] - else: - return [] + return [] - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> T.List[str]: if buildtype != 'plain': - return self.get_target_arch_args() + d_ldc_buildtype_args[buildtype] + return self._get_target_arch_args() + d_ldc_buildtype_args[buildtype] return d_ldc_buildtype_args[buildtype] - def get_pic_args(self): + def get_pic_args(self) -> T.List[str]: return ['-relocation-model=pic'] - def get_std_shared_lib_link_args(self): - return ['-shared'] - - def get_crt_link_args(self, crt_val, buildtype): - return self.get_crt_args(crt_val, buildtype) + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return self._get_crt_args(crt_val, buildtype) - def unix_args_to_native(self, args): - return self.translate_args_to_nongnu(args) + def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: + return self._translate_args_to_nongnu(args) - def get_optimization_args(self, optimization_level): + def get_optimization_args(self, optimization_level: str) -> T.List[str]: return ldc_optimization_args[optimization_level] + @classmethod + def use_linker_args(cls, linker: str) -> T.List[str]: + return [f'-linker={linker}'] + + def get_linker_always_args(self) -> T.List[str]: + args = super().get_linker_always_args() + if self.info.is_windows(): + return args + return args + ['-link-defaultlib-shared'] -class DmdDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin, DCompiler): + def get_disable_assert_args(self) -> T.List[str]: + return ['--release'] - def __init__(self, exelist, version, for_machine: MachineChoice, - info: 'MachineInfo', arch, **kwargs): - DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs) + def rsp_file_syntax(self) -> RSPFileSyntax: + # We use `mesonlib.is_windows` here because we want to know what the + # build machine is, not the host machine. This really means we would + # have the Environment not the MachineInfo in the compiler. + return RSPFileSyntax.MSVC if is_windows() else RSPFileSyntax.GCC + + +class DmdDCompiler(DmdLikeCompilerMixin, DCompiler): + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', arch: str, *, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, + is_cross: bool = False): + DCompiler.__init__(self, exelist, version, for_machine, info, arch, + exe_wrapper=exe_wrapper, linker=linker, + full_version=full_version, is_cross=is_cross) + DmdLikeCompilerMixin.__init__(self, version) self.id = 'dmd' - self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt'] + self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} - def get_colorout_args(self, colortype): + def get_colorout_args(self, colortype: str) -> T.List[str]: if colortype == 'always': return ['-color=on'] return [] - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> T.List[str]: if buildtype != 'plain': - return self.get_target_arch_args() + d_dmd_buildtype_args[buildtype] + return self._get_target_arch_args() + d_dmd_buildtype_args[buildtype] return d_dmd_buildtype_args[buildtype] - def get_std_exe_link_args(self): + def get_std_exe_link_args(self) -> T.List[str]: if self.info.is_windows(): # DMD links against D runtime only when main symbol is found, # so these needs to be inserted when linking static D libraries. @@ -729,7 +860,7 @@ return ['phobos.lib'] return [] - def get_std_shared_lib_link_args(self): + def get_std_shared_lib_link_args(self) -> T.List[str]: libname = 'libphobos2.so' if self.info.is_windows(): if self.arch == 'x86_64': @@ -740,7 +871,7 @@ libname = 'phobos.lib' return ['-shared', '-defaultlib=' + libname] - def get_target_arch_args(self): + def _get_target_arch_args(self) -> T.List[str]: # DMD32 and DMD64 on 64-bit Windows defaults to 32-bit (OMF). # Force the target to 64-bit in order to stay consistent # across the different platforms. @@ -752,11 +883,26 @@ return ['-m32'] return [] - def get_crt_compile_args(self, crt_val, buildtype): - return self.get_crt_args(crt_val, buildtype) + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return self._get_crt_args(crt_val, buildtype) - def unix_args_to_native(self, args): - return self.translate_args_to_nongnu(args) + def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: + return self._translate_args_to_nongnu(args) - def get_optimization_args(self, optimization_level): + def get_optimization_args(self, optimization_level: str) -> T.List[str]: return dmd_optimization_args[optimization_level] + + def can_linker_accept_rsp(self) -> bool: + return False + + def get_linker_always_args(self) -> T.List[str]: + args = super().get_linker_always_args() + if self.info.is_windows(): + return args + return args + ['-defaultlib=phobos2', '-debuglib=phobos2'] + + def get_disable_assert_args(self) -> T.List[str]: + return ['-release'] + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.MSVC diff -Nru meson-0.53.2/mesonbuild/compilers/fortran.py meson-0.61.2/mesonbuild/compilers/fortran.py --- meson-0.53.2/mesonbuild/compilers/fortran.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/fortran.py 2022-01-17 10:50:45.000000000 +0000 @@ -29,62 +29,68 @@ from .mixins.clang import ClangCompiler from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler -from .. import mlog from mesonbuild.mesonlib import ( - version_compare, EnvironmentException, MesonException, MachineChoice, LibType + version_compare, EnvironmentException, MesonException, MachineChoice, + LibType, OptionKey, ) if T.TYPE_CHECKING: + from ..coredata import KeyedOptionDictType + from ..dependencies import Dependency from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers import DynamicLinker + from ..programs import ExternalProgram + from .compilers import CompileCheckMode class FortranCompiler(CLikeCompiler, Compiler): language = 'fortran' - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): - Compiler.__init__(self, exelist, version, for_machine, info, **kwargs) - CLikeCompiler.__init__(self, is_cross, exe_wrapper) - self.id = 'unknown' - - def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None): + 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): + Compiler.__init__(self, exelist, version, for_machine, info, + is_cross=is_cross, full_version=full_version, linker=linker) + CLikeCompiler.__init__(self, exe_wrapper) + + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: raise MesonException('Fortran does not have "has_function" capability.\n' 'It is better to test if a Fortran capability is working like:\n\n' "meson.get_compiler('fortran').links('block; end block; end program')\n\n" 'that example is to see if the compiler has Fortran 2008 Block element.') - def sanity_check(self, work_dir: Path, environment): - """ - Check to be sure a minimal program can compile and execute - with this compiler & platform. - """ - work_dir = Path(work_dir) + def sanity_check(self, work_dir_: str, environment: 'Environment') -> None: + work_dir = Path(work_dir_) source_name = work_dir / 'sanitycheckf.f90' binary_name = work_dir / 'sanitycheckf' if binary_name.is_file(): binary_name.unlink() - source_name.write_text('print *, "Fortran compilation is working."; end') + source_name.write_text('program main; print *, "Fortran compilation is working."; end program', encoding='utf-8') - extra_flags = environment.coredata.get_external_args(self.for_machine, self.language) + extra_flags: T.List[str] = [] + extra_flags += environment.coredata.get_external_args(self.for_machine, self.language) extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language) extra_flags += self.get_always_args() # %% build the test executable "sanitycheckf" # cwd=work_dir is necessary on Windows especially for Intel compilers to avoid error: cannot write on sanitycheckf.obj # this is a defect with how Windows handles files and ifort's object file-writing behavior vis concurrent ProcessPoolExecutor. # This simple workaround solves the issue. - # FIXME: cwd=str(work_dir) is for Python 3.5 on Windows, when 3.5 is deprcated, this can become cwd=work_dir returncode = subprocess.run(self.exelist + extra_flags + [str(source_name), '-o', str(binary_name)], - cwd=str(work_dir)).returncode + cwd=work_dir).returncode if returncode != 0: raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string()) if self.is_cross: if self.exe_wrapper is None: # Can't check if the binaries run so we have to assume they do return - cmdlist = self.exe_wrapper + [str(binary_name)] + cmdlist = self.exe_wrapper.get_command() + [str(binary_name)] else: cmdlist = [str(binary_name)] # %% Run the test executable @@ -95,31 +101,26 @@ except OSError: raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string()) - def get_std_warn_args(self, level): - return FortranCompiler.std_warn_args - - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> T.List[str]: return gnulike_buildtype_args[buildtype] - def get_optimization_args(self, optimization_level): + def get_optimization_args(self, optimization_level: str) -> T.List[str]: return gnu_optimization_args[optimization_level] - def get_debug_args(self, is_debug): + def get_debug_args(self, is_debug: bool) -> T.List[str]: return clike_debug_args[is_debug] - def get_dependency_gen_args(self, outtarget, outfile): - return [] - - def get_preprocess_only_args(self): + def get_preprocess_only_args(self) -> T.List[str]: return ['-cpp'] + super().get_preprocess_only_args() - def get_module_incdir_args(self): + def get_module_incdir_args(self) -> T.Tuple[str, ...]: return ('-I', ) - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-module', path] - def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): if i[:2] == '-I' or i[:2] == '-L': parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) @@ -140,36 +141,40 @@ return filename - def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED): - code = '''stop; end program''' - return self.find_library_impl(libname, env, extra_dirs, code, libtype) - - def has_multi_arguments(self, args, env): - for arg in args[:]: - # some compilers, e.g. GCC, don't warn for unsupported warning-disable - # flags, so when we are testing a flag like "-Wno-forgotten-towel", also - # check the equivalent enable flag too "-Wforgotten-towel" - if arg.startswith('-Wno-'): - args.append('-W' + arg[5:]) - if arg.startswith('-Wl,'): - mlog.warning('{} looks like a linker argument, ' - 'but has_argument and other similar methods only ' - 'support checking compiler arguments. Using them ' - 'to check linker arguments are never supported, ' - 'and results are likely to be wrong regardless of ' - 'the compiler you are using. has_link_argument or ' - 'other similar method can be used instead.' - .format(arg)) + def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: code = 'stop; end program' - return self.has_arguments(args, env, code, mode='compile') + return self._find_library_impl(libname, env, extra_dirs, code, libtype) + + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self._has_multi_arguments(args, env, 'stop; end program') + + def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self._has_multi_link_arguments(args, env, 'stop; end program') + + def get_options(self) -> 'KeyedOptionDictType': + opts = super().get_options() + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key: coredata.UserComboOption( + 'Fortran language standard to use', + ['none'], + 'none', + ), + }) + return opts class GnuFortranCompiler(GnuCompiler, FortranCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - defines=None, **kwargs): + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, **kwargs) + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) GnuCompiler.__init__(self, defines) default_warn_args = ['-Wall'] self.warn_args = {'0': [], @@ -177,54 +182,92 @@ '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic', '-fimplicit-none']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = FortranCompiler.get_options(self) fortran_stds = ['legacy', 'f95', 'f2003'] if version_compare(self.version, '>=4.4.0'): fortran_stds += ['f2008'] if version_compare(self.version, '>=8.0.0'): fortran_stds += ['f2018'] - opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use', - ['none'] + fortran_stds, - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + fortran_stds return opts - def get_option_compile_args(self, options) -> T.List[str]: + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['fortran_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] if std.value != 'none': args.append('-std=' + std.value) return args - def get_dependency_gen_args(self, outtarget, outfile): + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: # Disabled until this is fixed: # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162 # return ['-cpp', '-MD', '-MQ', outtarget] return [] - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-J' + path] - def language_stdlib_only_link_flags(self): - return ['-lgfortran', '-lm'] - -class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - defines=None, **kwargs): - GnuFortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, defines, - **kwargs) + 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 + # be passed to a different compiler with a different set of default + # search paths, such as when using Clang for C/C++ and gfortran for + # fortran, + search_dir = self._get_search_dirs(env) + search_dirs: T.List[str] = [] + if search_dir is not None: + for d in search_dir.split()[-1][len('libraries: ='):].split(':'): + search_dirs.append(f'-L{d}') + return search_dirs + ['-lgfortran', '-lm'] + + def has_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + disable_cache: bool = False) -> T.Tuple[bool, bool]: + ''' + Derived from mixins/clike.py:has_header, but without C-style usage of + __has_include which breaks with GCC-Fortran 10: + https://github.com/mesonbuild/meson/issues/7017 + ''' + code = f'{prefix}\n#include <{hname}>' + return self.compiles(code, env, extra_args=extra_args, + dependencies=dependencies, mode='preprocess', disable_cache=disable_cache) + + +class ElbrusFortranCompiler(ElbrusCompiler, FortranCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + defines: T.Optional[T.Dict[str, str]] = 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) ElbrusCompiler.__init__(self) + def get_options(self) -> 'KeyedOptionDictType': + opts = FortranCompiler.get_options(self) + fortran_stds = ['f95', 'f2003', 'f2008', 'gnu', 'legacy', 'f2008ts'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + fortran_stds + return opts + + def get_module_outdir_args(self, path: str) -> T.List[str]: + return ['-J' + path] + + class G95FortranCompiler(FortranCompiler): LINKER_PREFIX = '-Wl,' - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + 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, **kwargs) + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) self.id = 'g95' default_warn_args = ['-Wall'] self.warn_args = {'0': [], @@ -232,10 +275,10 @@ '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-pedantic']} - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-fmod=' + path] - def get_no_warn_args(self): + def get_no_warn_args(self) -> T.List[str]: # FIXME: Confirm that there's no compiler option to disable all warnings return [] @@ -244,39 +287,45 @@ LINKER_PREFIX = '-Wl,' - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - **kwargs): - FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs) + 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' - def get_dependency_gen_args(self, outtarget, outfile): + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: return ['-fpp'] - def get_always_args(self): + def get_always_args(self) -> T.List[str]: return [] - def get_warn_args(self, level): + def get_warn_args(self, level: str) -> T.List[str]: return [] - def get_module_incdir_args(self): + def get_module_incdir_args(self) -> T.Tuple[str, ...]: return ('-M', ) - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-moddir=' + path] - def openmp_flags(self): + def openmp_flags(self) -> T.List[str]: return ['-xopenmp'] class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - **kwargs): - self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp') + file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp', ) + + 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, **kwargs) + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) # FIXME: Add support for OS X and Windows in detect_fortran_compiler so # we are sent the type of compiler IntelGnuLikeCompiler.__init__(self) @@ -287,32 +336,26 @@ '2': default_warn_args + ['-warn', 'unused'], '3': ['-warn', 'all']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = FortranCompiler.get_options(self) - fortran_stds = ['legacy', 'f95', 'f2003', 'f2008', 'f2018'] - opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use', - ['none'] + fortran_stds, - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018'] return opts - def get_option_compile_args(self, options) -> T.List[str]: + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['fortran_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'} if std.value != 'none': args.append('-stand=' + stds[std.value]) return args - def get_preprocess_only_args(self): + def get_preprocess_only_args(self) -> T.List[str]: return ['-cpp', '-EP'] - def get_always_args(self): - """Ifort doesn't have -pipe.""" - val = super().get_always_args() - val.remove('-pipe') - return val - - def language_stdlib_only_link_flags(self): + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: + # TODO: needs default search path added return ['-lifcore', '-limf'] def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: @@ -321,14 +364,17 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler): - file_suffixes = ['f90', 'f', 'for', 'ftn', 'fpp'] + file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp', ) always_args = ['/nologo'] - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, target: str, info: 'MachineInfo', exe_wrapper=None, - **kwargs): + 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, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, **kwargs) + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) IntelVisualStudioLikeCompiler.__init__(self, target) default_warn_args = ['/warn:general', '/warn:truncated_source'] @@ -337,32 +383,34 @@ '2': default_warn_args + ['/warn:unused'], '3': ['/warn:all']} - def get_options(self): + def get_options(self) -> 'KeyedOptionDictType': opts = FortranCompiler.get_options(self) - fortran_stds = ['legacy', 'f95', 'f2003', 'f2008', 'f2018'] - opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use', - ['none'] + fortran_stds, - 'none')}) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018'] return opts - def get_option_compile_args(self, options) -> T.List[str]: + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] - std = options['fortran_std'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'} if std.value != 'none': args.append('/stand:' + stds[std.value]) return args - def get_module_outdir_args(self, path) -> T.List[str]: + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['/module:' + path] class PathScaleFortranCompiler(FortranCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - **kwargs): + + 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, **kwargs) + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) self.id = 'pathscale' default_warn_args = ['-fullwarn'] self.warn_args = {'0': [], @@ -370,16 +418,19 @@ '2': default_warn_args, '3': default_warn_args} - def openmp_flags(self): + def openmp_flags(self) -> T.List[str]: return ['-mp'] class PGIFortranCompiler(PGICompiler, FortranCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - **kwargs): + + 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, **kwargs) + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) PGICompiler.__init__(self) default_warn_args = ['-Minform=inform'] @@ -388,17 +439,41 @@ '2': default_warn_args, '3': default_warn_args + ['-Mdclchk']} - def language_stdlib_only_link_flags(self) -> T.List[str]: + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: + # TODO: needs default search path added return ['-lpgf90rtl', '-lpgf90', '-lpgf90_rpm1', '-lpgf902', '-lpgf90rtl', '-lpgftnrtl', '-lrt'] + +class NvidiaHPC_FortranCompiler(PGICompiler, FortranCompiler): + + 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) + PGICompiler.__init__(self) + + self.id = 'nvidia_hpc' + default_warn_args = ['-Minform=inform'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args, + '3': default_warn_args + ['-Mdclchk']} + + class FlangFortranCompiler(ClangCompiler, FortranCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - **kwargs): + + 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, **kwargs) - ClangCompiler.__init__(self) + 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': [], @@ -406,15 +481,28 @@ '2': default_warn_args, '3': default_warn_args} - def language_stdlib_only_link_flags(self) -> T.List[str]: - return ['-lflang', '-lpgmath'] + 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 + # be passed to a different compiler with a different set of default + # search paths, such as when using Clang for C/C++ and gfortran for + # fortran, + # XXX: Untested.... + search_dir = self._get_search_dirs(env) + search_dirs: T.List[str] = [] + if search_dir is not None: + for d in search_dir.split()[-1][len('libraries: ='):].split(':'): + search_dirs.append(f'-L{d}') + return search_dirs + ['-lflang', '-lpgmath'] class Open64FortranCompiler(FortranCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - **kwargs): + + 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, **kwargs) + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) self.id = 'open64' default_warn_args = ['-fullwarn'] self.warn_args = {'0': [], @@ -422,23 +510,46 @@ '2': default_warn_args, '3': default_warn_args} - def openmp_flags(self): + def openmp_flags(self) -> T.List[str]: return ['-mp'] class NAGFortranCompiler(FortranCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, - is_cross, info: 'MachineInfo', exe_wrapper=None, - **kwargs): + + 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, **kwargs) + 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'], + '1': [], + '2': [], + '3': [], + } - def get_warn_args(self, level): - return [] + def get_always_args(self) -> T.List[str]: + return self.get_nagfor_quiet(self.version) - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-mdir', path] - def openmp_flags(self): + @staticmethod + def get_nagfor_quiet(version: str) -> T.List[str]: + return ['-quiet'] if version_compare(version, '>=7100') else [] + + def get_pic_args(self) -> T.List[str]: + return ['-PIC'] + + def get_preprocess_only_args(self) -> T.List[str]: + return ['-fpp'] + + def get_std_exe_link_args(self) -> T.List[str]: + return self.get_always_args() + + def openmp_flags(self) -> T.List[str]: return ['-openmp'] diff -Nru meson-0.53.2/mesonbuild/compilers/__init__.py meson-0.61.2/mesonbuild/compilers/__init__.py --- meson-0.53.2/mesonbuild/compilers/__init__.py 2019-12-04 18:45:50.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/__init__.py 2021-11-02 19:58:07.000000000 +0000 @@ -15,6 +15,7 @@ # Public symbols for compilers sub-package when using 'from . import compilers' __all__ = [ 'Compiler', + 'RunResult', 'all_languages', 'base_options', @@ -30,11 +31,32 @@ 'is_llvm_ir', 'is_object', 'is_source', + 'is_known_suffix', 'lang_suffixes', + 'LANGUAGES_USING_LDFLAGS', 'sort_clink', + 'SUFFIX_TO_LANG', + + 'compiler_from_language', + 'detect_compiler_for', + 'detect_static_linker', + 'detect_c_compiler', + 'detect_cpp_compiler', + 'detect_cuda_compiler', + 'detect_fortran_compiler', + 'detect_objc_compiler', + 'detect_objcpp_compiler', + 'detect_java_compiler', + 'detect_cs_compiler', + 'detect_vala_compiler', + 'detect_rust_compiler', + 'detect_d_compiler', + 'detect_swift_compiler', 'AppleClangCCompiler', 'AppleClangCPPCompiler', + 'AppleClangObjCCompiler', + 'AppleClangObjCPPCompiler', 'ArmCCompiler', 'ArmCPPCompiler', 'ArmclangCCompiler', @@ -47,7 +69,6 @@ 'ClangObjCPPCompiler', 'ClangClCCompiler', 'ClangClCPPCompiler', - 'CompilerArgs', 'CPPCompiler', 'DCompiler', 'DmdDCompiler', @@ -57,6 +78,7 @@ 'ElbrusCCompiler', 'EmscriptenCCompiler', 'GnuCompiler', + 'GnuLikeCompiler', 'GnuCPPCompiler', 'ElbrusCPPCompiler', 'EmscriptenCPPCompiler', @@ -84,23 +106,33 @@ 'ObjCPPCompiler', 'Open64FortranCompiler', 'PathScaleFortranCompiler', + 'NvidiaHPC_CCompiler', + 'NvidiaHPC_CPPCompiler', + 'NvidiaHPC_FortranCompiler', 'PGICCompiler', 'PGICPPCompiler', 'PGIFortranCompiler', 'RustCompiler', + 'ClippyRustCompiler', 'CcrxCCompiler', 'CcrxCPPCompiler', + 'Xc16CCompiler', + 'CompCertCCompiler', + 'C2000CCompiler', + 'C2000CPPCompiler', 'SunFortranCompiler', 'SwiftCompiler', 'ValaCompiler', 'VisualStudioLikeCompiler', 'VisualStudioCCompiler', 'VisualStudioCPPCompiler', + 'CythonCompiler', ] # Bring symbols from each module into compilers sub-package namespace from .compilers import ( Compiler, + RunResult, all_languages, base_options, clib_langs, @@ -115,9 +147,28 @@ is_llvm_ir, is_object, is_library, + is_known_suffix, lang_suffixes, + LANGUAGES_USING_LDFLAGS, sort_clink, - CompilerArgs, + SUFFIX_TO_LANG, +) +from .detect import ( + compiler_from_language, + detect_compiler_for, + detect_static_linker, + detect_c_compiler, + detect_cpp_compiler, + detect_cuda_compiler, + detect_objc_compiler, + detect_objcpp_compiler, + detect_fortran_compiler, + detect_java_compiler, + detect_cs_compiler, + detect_vala_compiler, + detect_rust_compiler, + detect_d_compiler, + detect_swift_compiler, ) from .c import ( CCompiler, @@ -131,8 +182,12 @@ EmscriptenCCompiler, IntelCCompiler, IntelClCCompiler, + NvidiaHPC_CCompiler, PGICCompiler, CcrxCCompiler, + Xc16CCompiler, + CompCertCCompiler, + C2000CCompiler, VisualStudioCCompiler, ) from .cpp import ( @@ -147,8 +202,10 @@ EmscriptenCPPCompiler, IntelCPPCompiler, IntelClCPPCompiler, + NvidiaHPC_CPPCompiler, PGICPPCompiler, CcrxCPPCompiler, + C2000CPPCompiler, VisualStudioCPPCompiler, ) from .cs import MonoCompiler, VisualStudioCsCompiler @@ -170,24 +227,28 @@ NAGFortranCompiler, Open64FortranCompiler, PathScaleFortranCompiler, + NvidiaHPC_FortranCompiler, PGIFortranCompiler, SunFortranCompiler, ) from .java import JavaCompiler from .objc import ( ObjCCompiler, + AppleClangObjCCompiler, ClangObjCCompiler, GnuObjCCompiler, ) from .objcpp import ( ObjCPPCompiler, + AppleClangObjCPPCompiler, ClangObjCPPCompiler, GnuObjCPPCompiler, ) -from .rust import RustCompiler +from .rust import RustCompiler, ClippyRustCompiler from .swift import SwiftCompiler from .vala import ValaCompiler from .mixins.visualstudio import VisualStudioLikeCompiler -from .mixins.gnu import GnuCompiler +from .mixins.gnu import GnuCompiler, GnuLikeCompiler from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler from .mixins.clang import ClangCompiler +from .cython import CythonCompiler diff -Nru meson-0.53.2/mesonbuild/compilers/java.py meson-0.61.2/mesonbuild/compilers/java.py --- meson-0.53.2/mesonbuild/compilers/java.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/java.py 2022-01-17 10:50:45.000000000 +0000 @@ -12,9 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os import os.path import shutil import subprocess +import textwrap import typing as T from ..mesonlib import EnvironmentException, MachineChoice @@ -23,60 +25,43 @@ if T.TYPE_CHECKING: from ..envconfig import MachineInfo + from ..environment import Environment class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler): language = 'java' - def __init__(self, exelist, version, for_machine: MachineChoice, - info: 'MachineInfo'): - super().__init__(exelist, version, for_machine, info) + 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.is_cross = False self.javarunner = 'java' - def get_werror_args(self): + def get_werror_args(self) -> T.List[str]: return ['-Werror'] - def split_shlib_to_parts(self, fname): - return None, fname + def get_no_warn_args(self) -> T.List[str]: + return ['-nowarn'] - def get_dependency_gen_args(self, outtarget, outfile): - return [] - - def get_compile_only_args(self): - return [] - - def get_output_args(self, subdir): - if subdir == '': - subdir = './' - return ['-d', subdir, '-s', subdir] - - def get_coverage_args(self): - return [] - - def get_std_exe_link_args(self): - return [] - - def get_include_args(self, path): - return [] + def get_output_args(self, outputname: str) -> T.List[str]: + if outputname == '': + outputname = './' + return ['-d', outputname, '-s', outputname] - def get_pic_args(self): + def get_pic_args(self) -> T.List[str]: return [] - def name_string(self): - return ' '.join(self.exelist) - - def get_pch_use_args(self, pch_dir, header): + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: return [] - def get_pch_name(self, header_name): + def get_pch_name(self, name: str) -> str: return '' - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> T.List[str]: return java_buildtype_args[buildtype] - def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): if i in ['-cp', '-classpath', '-sourcepath'] and idx + 1 < len(parameter_list): path_list = parameter_list[idx + 1].split(os.pathsep) @@ -85,17 +70,18 @@ return parameter_list - def sanity_check(self, work_dir, environment): + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: src = 'SanityCheck.java' obj = 'SanityCheck' source_name = os.path.join(work_dir, src) - with open(source_name, 'w') as ofile: - ofile.write('''class SanityCheck { - public static void main(String[] args) { - int i; - } -} -''') + with open(source_name, 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent( + '''class SanityCheck { + public static void main(String[] args) { + int i; + } + } + ''')) pc = subprocess.Popen(self.exelist + [src], cwd=work_dir) pc.wait() if pc.returncode != 0: @@ -115,5 +101,13 @@ "all about it." raise EnvironmentException(m) - def needs_static_linker(self): + def needs_static_linker(self) -> bool: return False + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return [] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + if is_debug: + return ['-g'] + return ['-g:none'] diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/arm.py meson-0.61.2/mesonbuild/compilers/mixins/arm.py --- meson-0.53.2/mesonbuild/compilers/mixins/arm.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/mixins/arm.py 2022-01-17 10:50:45.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright 2012-2019 The Meson development team +# Copyright 2012-2020 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. @@ -15,22 +15,30 @@ """Representations specific to the arm family of compilers.""" import os -import re import typing as T from ... import mesonlib +from ...linkers import ArmClangDynamicLinker +from ...mesonlib import OptionKey from ..compilers import clike_debug_args from .clang import clang_color_args if T.TYPE_CHECKING: from ...environment import Environment + from ...compilers.compilers import Compiler +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object arm_buildtype_args = { 'plain': [], - 'debug': ['-O0', '--debug'], - 'debugoptimized': ['-O1', '--debug'], - 'release': ['-O3', '-Otime'], - 'minsize': ['-O3', '-Ospace'], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], 'custom': [], } # type: T.Dict[str, T.List[str]] @@ -38,33 +46,35 @@ '0': ['-O0'], 'g': ['-g'], '1': ['-O1'], - '2': ['-O2'], - '3': ['-O3'], - 's': [], + '2': [], # Compiler defaults to -O2 + '3': ['-O3', '-Otime'], + 's': ['-O3'], # Compiler defaults to -Ospace } # type: T.Dict[str, T.List[str]] armclang_buildtype_args = { 'plain': [], - 'debug': ['-O0', '-g'], - 'debugoptimized': ['-O1', '-g'], - 'release': ['-Os'], - 'minsize': ['-Oz'], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], 'custom': [], } # type: T.Dict[str, T.List[str]] armclang_optimization_args = { - '0': ['-O0'], + '0': [], # Compiler defaults to -O0 'g': ['-g'], '1': ['-O1'], '2': ['-O2'], '3': ['-O3'], - 's': ['-Os'] + 's': ['-Oz'] } # type: T.Dict[str, T.List[str]] -class ArmCompiler: - # Functionality that is common to all ARM family compilers. - def __init__(self): +class ArmCompiler(Compiler): + + """Functionality that is common to all ARM family compilers.""" + + def __init__(self) -> None: if not self.is_cross: raise mesonlib.EnvironmentException('armcc supports only cross-compilation.') self.id = 'arm' @@ -72,7 +82,7 @@ self.warn_args = {'0': [], '1': default_warn_args, '2': default_warn_args + [], - '3': default_warn_args + []} + '3': default_warn_args + []} # type: T.Dict[str, T.List[str]] # Assembly self.can_compile_suffixes.add('s') @@ -87,9 +97,8 @@ def get_always_args(self) -> T.List[str]: return [] - # Override CCompiler.get_dependency_gen_args def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: - return [] + return ['--depend_target', outtarget, '--depend', outfile, '--depend_single_line'] def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: # FIXME: Add required arguments @@ -126,36 +135,21 @@ return parameter_list -class ArmclangCompiler: - def __init__(self): +class ArmclangCompiler(Compiler): + + def __init__(self) -> None: if not self.is_cross: raise mesonlib.EnvironmentException('armclang supports only cross-compilation.') # Check whether 'armlink' is available in path - self.linker_exe = 'armlink' - args = '--vsn' - try: - p, stdo, stderr = mesonlib.Popen_safe(self.linker_exe, args) - except OSError as e: - err_msg = 'Unknown linker\nRunning "{0}" gave \n"{1}"'.format(' '.join([self.linker_exe] + [args]), e) - raise mesonlib.EnvironmentException(err_msg) - # Verify the armlink version - ver_str = re.search('.*Component.*', stdo) - if ver_str: - ver_str = ver_str.group(0) - else: - raise mesonlib.EnvironmentException('armlink version string not found') - assert ver_str # makes mypy happy - # Using the regular expression from environment.search_version, - # which is used for searching compiler version - version_regex = r'(? T.List[str]: - return [] + return ['-MD', '-MT', outtarget, '-MF', outfile] def get_optimization_args(self, optimization_level: str) -> T.List[str]: return armclang_optimization_args[optimization_level] diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/c2000.py meson-0.61.2/mesonbuild/compilers/mixins/c2000.py --- meson-0.53.2/mesonbuild/compilers/mixins/c2000.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/mixins/c2000.py 2022-01-17 10:50:45.000000000 +0000 @@ -0,0 +1,131 @@ +# Copyright 2012-2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Representations specific to the Texas Instruments C2000 compiler family.""" + +import os +import typing as T + +from ...mesonlib import EnvironmentException + +if T.TYPE_CHECKING: + from ...environment import Environment + from ...compilers.compilers import Compiler +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object + +c2000_buildtype_args = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], + 'custom': [], +} # type: T.Dict[str, T.List[str]] + +c2000_optimization_args = { + '0': ['-O0'], + 'g': ['-Ooff'], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-04'] +} # type: T.Dict[str, T.List[str]] + +c2000_debug_args = { + False: [], + True: ['-g'] +} # type: T.Dict[bool, T.List[str]] + + +class C2000Compiler(Compiler): + + 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) + + default_warn_args = [] # type: T.List[str] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + [], + '3': default_warn_args + []} # type: T.Dict[str, T.List[str]] + + def get_pic_args(self) -> T.List[str]: + # PIC support is not enabled by default for c2000, + # if users want to use it, they need to add the required arguments explicitly + return [] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return c2000_buildtype_args[buildtype] + + def get_pch_suffix(self) -> str: + return 'pch' + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return [] + + def thread_flags(self, env: 'Environment') -> T.List[str]: + return [] + + def get_coverage_args(self) -> T.List[str]: + return [] + + def get_no_stdinc_args(self) -> T.List[str]: + return [] + + def get_no_stdlib_link_args(self) -> T.List[str]: + return [] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return c2000_optimization_args[optimization_level] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return c2000_debug_args[is_debug] + + @classmethod + def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]: + result = [] + for i in args: + if i.startswith('-D'): + i = '--define=' + i[2:] + if i.startswith('-I'): + i = '--include_path=' + i[2:] + if i.startswith('-Wl,-rpath='): + continue + elif i == '--print-search-dirs': + continue + elif i.startswith('-L'): + continue + result.append(i) + return result + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:14] == '--include_path': + parameter_list[idx] = i[:14] + os.path.normpath(os.path.join(build_dir, i[14:])) + if i[:2] == '-I': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + + return parameter_list + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return ['--preproc_with_compile', f'--preproc_dependency={outfile}'] diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/ccrx.py meson-0.61.2/mesonbuild/compilers/mixins/ccrx.py --- meson-0.53.2/mesonbuild/compilers/mixins/ccrx.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/mixins/ccrx.py 2022-01-17 10:50:45.000000000 +0000 @@ -21,6 +21,13 @@ if T.TYPE_CHECKING: from ...environment import Environment + from ...compilers.compilers import Compiler +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object ccrx_buildtype_args = { 'plain': [], @@ -46,8 +53,13 @@ } # type: T.Dict[bool, T.List[str]] -class CcrxCompiler: - def __init__(self): +class CcrxCompiler(Compiler): + + if T.TYPE_CHECKING: + is_cross = True + can_compile_suffixes = set() # type: T.Set[str] + + def __init__(self) -> None: if not self.is_cross: raise EnvironmentException('ccrx supports only cross-compilation.') self.id = 'ccrx' @@ -57,7 +69,7 @@ self.warn_args = {'0': [], '1': default_warn_args, '2': default_warn_args + [], - '3': default_warn_args + []} + '3': default_warn_args + []} # type: T.Dict[str, T.List[str]] def get_pic_args(self) -> T.List[str]: # PIC support is not enabled by default for CCRX, @@ -73,10 +85,6 @@ def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: return [] - # Override CCompiler.get_dependency_gen_args - def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: - return [] - def thread_flags(self, env: 'Environment') -> T.List[str]: return [] diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/clang.py meson-0.61.2/mesonbuild/compilers/mixins/clang.py --- meson-0.53.2/mesonbuild/compilers/mixins/clang.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/mixins/clang.py 2022-01-17 10:50:45.000000000 +0000 @@ -15,11 +15,13 @@ """Abstractions for the LLVM/Clang compiler family.""" import os +import shutil import typing as T from ... import mesonlib -from ...linkers import AppleDynamicLinker -from ..compilers import clike_optimization_args +from ...linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker +from ...mesonlib import OptionKey +from ..compilers import CompileCheckMode from .gnu import GnuLikeCompiler if T.TYPE_CHECKING: @@ -27,29 +29,47 @@ from ...dependencies import Dependency # noqa: F401 clang_color_args = { - 'auto': ['-Xclang', '-fcolor-diagnostics'], - 'always': ['-Xclang', '-fcolor-diagnostics'], - 'never': ['-Xclang', '-fno-color-diagnostics'], + 'auto': ['-fcolor-diagnostics'], + 'always': ['-fcolor-diagnostics'], + 'never': ['-fno-color-diagnostics'], } # type: T.Dict[str, T.List[str]] +clang_optimization_args = { + '0': ['-O0'], + 'g': ['-Og'], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-Oz'], +} # type: T.Dict[str, T.List[str]] class ClangCompiler(GnuLikeCompiler): - def __init__(self): + + def __init__(self, defines: T.Optional[T.Dict[str, str]]): super().__init__() self.id = 'clang' - self.base_options.append('b_colorout') + self.defines = defines or {} + self.base_options.update( + {OptionKey('b_colorout'), OptionKey('b_lto_threads'), OptionKey('b_lto_mode')}) + # TODO: this really should be part of the linker base_options, but # linkers don't have base_options. if isinstance(self.linker, AppleDynamicLinker): - self.base_options.append('b_bitcode') + self.base_options.add(OptionKey('b_bitcode')) # All Clang backends can also do LLVM IR self.can_compile_suffixes.add('ll') def get_colorout_args(self, colortype: str) -> T.List[str]: return clang_color_args[colortype][:] + def has_builtin_define(self, define: str) -> bool: + return define in self.defines + + def get_builtin_define(self, define: str) -> T.Optional[str]: + return self.defines.get(define) + def get_optimization_args(self, optimization_level: str) -> T.List[str]: - return clike_optimization_args[optimization_level] + return clang_optimization_args[optimization_level] def get_pch_suffix(self) -> str: return 'pch' @@ -60,17 +80,21 @@ # so it might change semantics at any time. return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] - def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.List[str]: - myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument'] - if mesonlib.version_compare(self.version, '>=3.6.0'): - myargs.append('-Werror=ignored-optimization-argument') - return super().has_multi_arguments( - myargs + args, - env) + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + # Clang is different than GCC, it will return True when a symbol isn't + # defined in a header. Specifically this seems to have something to do + # with functions that may be in a header on some systems, but not all of + # them. `strlcat` specifically with can trigger this. + myargs: T.List[str] = ['-Werror=implicit-function-declaration'] + if mode is CompileCheckMode.COMPILE: + myargs.extend(['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument']) + if mesonlib.version_compare(self.version, '>=3.6.0'): + myargs.append('-Werror=ignored-optimization-argument') + return super().get_compiler_check_args(mode) + myargs def has_function(self, funcname: str, prefix: str, env: 'Environment', *, extra_args: T.Optional[T.List[str]] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> bool: + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: if extra_args is None: extra_args = [] # Starting with XCode 8, we need to pass this to force linker @@ -81,7 +105,7 @@ if isinstance(self.linker, AppleDynamicLinker) and mesonlib.version_compare(self.version, '>=8.0'): extra_args.append('-Wl,-no_weak_imports') return super().has_function(funcname, prefix, env, extra_args=extra_args, - dependencies=dependencies) + dependencies=dependencies) def openmp_flags(self) -> T.List[str]: if mesonlib.version_compare(self.version, '>=3.8.0'): @@ -91,3 +115,50 @@ else: # Shouldn't work, but it'll be checked explicitly in the OpenMP dependency. return [] + + @classmethod + def use_linker_args(cls, linker: str) -> T.List[str]: + # Clang additionally can use a linker specified as a path, which GCC + # (and other gcc-like compilers) cannot. This is because clang (being + # llvm based) is retargetable, while GCC is not. + # + + # qcld: Qualcomm Snapdragon linker, based on LLVM + if linker == 'qcld': + return ['-fuse-ld=qcld'] + + if shutil.which(linker): + if not shutil.which(linker): + raise mesonlib.MesonException( + f'Cannot find linker {linker}.') + return [f'-fuse-ld={linker}'] + return super().use_linker_args(linker) + + def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: + # Clang only warns about unknown or ignored attributes, so force an + # error. + return ['-Werror=attributes'] + + def get_coverage_link_args(self) -> T.List[str]: + return ['--coverage'] + + def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: + args: T.List[str] = [] + if mode == 'thin': + # Thin LTO requires the use of gold, lld, ld64, or lld-link + if not isinstance(self.linker, (AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker)): + raise mesonlib.MesonException(f"LLVM's thinLTO only works with gnu gold, lld, lld-link, and ld64, not {self.linker.id}") + args.append(f'-flto={mode}') + else: + assert mode == 'default', 'someone forgot to wire something up' + args.extend(super().get_lto_compile_args(threads=threads)) + return args + + def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: + args = self.get_lto_compile_args(threads=threads, mode=mode) + # In clang -flto-jobs=0 means auto, and is the default if unspecified, just like in meson + if threads > 0: + if not mesonlib.version_compare(self.version, '>=4.0.0'): + raise mesonlib.MesonException('clang support for LTO threads requires clang >=4.0') + args.append(f'-flto-jobs={threads}') + return args diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/clike.py meson-0.61.2/mesonbuild/compilers/mixins/clike.py --- meson-0.53.2/mesonbuild/compilers/mixins/clike.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/mesonbuild/compilers/mixins/clike.py 2022-01-02 20:12:32.000000000 +0000 @@ -20,6 +20,7 @@ standalone, they only work through inheritance. """ +import collections import functools import glob import itertools @@ -29,105 +30,170 @@ import typing as T from pathlib import Path +from ... import arglist from ... import mesonlib -from ...mesonlib import LibType from ... import mlog +from ...linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker +from ...mesonlib import LibType +from ...coredata import OptionKey from .. import compilers +from ..compilers import CompileCheckMode from .visualstudio import VisualStudioLikeCompiler if T.TYPE_CHECKING: + from ...dependencies import Dependency + from ..._typing import ImmutableListProtocol from ...environment import Environment + from ...compilers.compilers import Compiler + from ...programs import ExternalProgram +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object + +GROUP_FLAGS = re.compile(r'''\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ | + ^(?:-Wl,)?-l | + \.a$''', re.X) + +class CLikeCompilerArgs(arglist.CompilerArgs): + prepend_prefixes = ('-I', '-L') + dedup2_prefixes = ('-I', '-isystem', '-L', '-D', '-U') + + # NOTE: not thorough. A list of potential corner cases can be found in + # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 + dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic') + dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') + dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread') + + def to_native(self, copy: bool = False) -> T.List[str]: + # This seems to be allowed, but could never work? + assert isinstance(self.compiler, compilers.Compiler), 'How did you get here' + + # Check if we need to add --start/end-group for circular dependencies + # between static libraries, and for recursively searching for symbols + # needed by static libraries that are provided by object files or + # shared libraries. + self.flush_pre_post() + if copy: + new = self.copy() + else: + new = self + # This covers all ld.bfd, ld.gold, ld.gold, and xild on Linux, which + # all act like (or are) gnu ld + # TODO: this could probably be added to the DynamicLinker instead + if isinstance(self.compiler.linker, (GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker)): + group_start = -1 + group_end = -1 + for i, each in enumerate(new): + if not GROUP_FLAGS.search(each): + continue + group_end = i + if group_start < 0: + # First occurrence of a library + group_start = i + if group_start >= 0: + # Last occurrence of a library + new.insert(group_end + 1, '-Wl,--end-group') + new.insert(group_start, '-Wl,--start-group') + # Remove system/default include paths added with -isystem + default_dirs = self.compiler.get_default_include_dirs() + if default_dirs: + bad_idx_list = [] # type: T.List[int] + for i, each in enumerate(new): + if not each.startswith('-isystem'): + continue + + # Remove the -isystem and the path if the path is a default path + if (each == '-isystem' and + i < (len(new) - 1) and + new[i + 1] in default_dirs): + bad_idx_list += [i, i + 1] + elif each.startswith('-isystem=') and each[9:] in default_dirs: + bad_idx_list += [i] + elif each[8:] in default_dirs: + bad_idx_list += [i] + for i in reversed(bad_idx_list): + new.pop(i) + return self.compiler.unix_args_to_native(new._container) + + def __repr__(self) -> str: + self.flush_pre_post() + return f'CLikeCompilerArgs({self.compiler!r}, {self._container!r})' -class CLikeCompiler: +class CLikeCompiler(Compiler): """Shared bits for the C and CPP Compilers.""" + if T.TYPE_CHECKING: + warn_args = {} # type: T.Dict[str, T.List[str]] + # TODO: Replace this manual cache with functools.lru_cache - library_dirs_cache = {} - program_dirs_cache = {} - find_library_cache = {} - find_framework_cache = {} - internal_libs = compilers.unixy_compiler_internal_libs + find_library_cache = {} # type: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], str, LibType], T.Optional[T.List[str]]] + find_framework_cache = {} # type: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], bool], T.Optional[T.List[str]]] + internal_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS - def __init__(self, is_cross: bool, exe_wrapper: T.Optional[str] = None): + def __init__(self, exe_wrapper: T.Optional['ExternalProgram'] = None): # If a child ObjC or CPP class has already set it, don't set it ourselves - self.is_cross = is_cross self.can_compile_suffixes.add('h') # If the exe wrapper was not found, pretend it wasn't set so that the # sanity check is skipped and compiler checks use fallbacks. - if not exe_wrapper or not exe_wrapper.found(): + if not exe_wrapper or not exe_wrapper.found() or not exe_wrapper.get_command(): self.exe_wrapper = None else: - self.exe_wrapper = exe_wrapper.get_command() + self.exe_wrapper = exe_wrapper + + def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CLikeCompilerArgs: + # This is correct, mypy just doesn't understand co-operative inheritance + return CLikeCompilerArgs(self, args) - def needs_static_linker(self): + def needs_static_linker(self) -> bool: return True # When compiling static libraries, so yes. - def get_always_args(self): + def get_always_args(self) -> T.List[str]: ''' Args that are always-on for all C compilers other than MSVC ''' - return ['-pipe'] + compilers.get_largefile_args(self) + return self.get_largefile_args() - def get_no_stdinc_args(self): + def get_no_stdinc_args(self) -> T.List[str]: return ['-nostdinc'] - def get_no_stdlib_link_args(self): + def get_no_stdlib_link_args(self) -> T.List[str]: return ['-nostdlib'] - def get_warn_args(self, level): + def get_warn_args(self, level: str) -> T.List[str]: + # TODO: this should be an enum return self.warn_args[level] - def get_no_warn_args(self): + def get_no_warn_args(self) -> T.List[str]: # Almost every compiler uses this for disabling warnings return ['-w'] - def split_shlib_to_parts(self, fname): - return None, fname - - def depfile_for_object(self, objfile): - return objfile + '.' + self.get_depfile_suffix() - - def get_depfile_suffix(self): + def get_depfile_suffix(self) -> str: return 'd' - def get_exelist(self): - return self.exelist[:] + def get_exelist(self) -> T.List[str]: + return self.exelist.copy() - def get_preprocess_only_args(self): + def get_preprocess_only_args(self) -> T.List[str]: return ['-E', '-P'] - def get_compile_only_args(self): + def get_compile_only_args(self) -> T.List[str]: return ['-c'] - def get_no_optimization_args(self): + def get_no_optimization_args(self) -> T.List[str]: return ['-O0'] - def get_compiler_check_args(self): - ''' - Get arguments useful for compiler checks such as being permissive in - the code quality and not doing any optimization. - ''' - return self.get_no_optimization_args() - - def get_output_args(self, target): + def get_output_args(self, target: str) -> T.List[str]: return ['-o', target] - def get_coverage_args(self): - return ['--coverage'] - - def get_coverage_link_args(self) -> T.List[str]: - return self.linker.get_coverage_args() - - def get_werror_args(self): + def get_werror_args(self) -> T.List[str]: return ['-Werror'] - def get_std_exe_link_args(self): - # TODO: is this a linker property? - return [] - - def get_include_args(self, path, is_system): + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: if path == '': path = '.' if is_system: @@ -141,7 +207,9 @@ return [] @functools.lru_cache() - def get_library_dirs(self, env, elf_class = None): + def _get_library_dirs(self, env: 'Environment', + elf_class: T.Optional[int] = None) -> 'ImmutableListProtocol[str]': + # TODO: replace elf_class with enum dirs = self.get_compiler_dirs(env, 'libraries') if elf_class is None or elf_class == 0: return dirs @@ -158,41 +226,54 @@ if not files: retval.append(d) continue - file_to_check = os.path.join(d, files[0]) - with open(file_to_check, 'rb') as fd: - header = fd.read(5) - # if file is not an ELF file, it's weird, but accept dir - # if it is elf, and the class matches, accept dir - if header[1:4] != b'ELF' or int(header[4]) == elf_class: - retval.append(d) - # at this point, it's an ELF file which doesn't match the - # appropriate elf_class, so skip this one - return tuple(retval) + + for f in files: + file_to_check = os.path.join(d, f) + try: + with open(file_to_check, 'rb') as fd: + header = fd.read(5) + # if file is not an ELF file, it's weird, but accept dir + # if it is elf, and the class matches, accept dir + if header[1:4] != b'ELF' or int(header[4]) == elf_class: + retval.append(d) + # at this point, it's an ELF file which doesn't match the + # appropriate elf_class, so skip this one + # stop scanning after the first successful read + break + except OSError: + # Skip the file if we can't read it + pass + + return retval + + def get_library_dirs(self, env: 'Environment', + elf_class: T.Optional[int] = None) -> T.List[str]: + """Wrap the lru_cache so that we return a new copy and don't allow + mutation of the cached value. + """ + return self._get_library_dirs(env, elf_class).copy() @functools.lru_cache() - def get_program_dirs(self, env): + def _get_program_dirs(self, env: 'Environment') -> 'ImmutableListProtocol[str]': ''' Programs used by the compiler. Also where toolchain DLLs such as libstdc++-6.dll are found with MinGW. ''' return self.get_compiler_dirs(env, 'programs') + def get_program_dirs(self, env: 'Environment') -> T.List[str]: + return self._get_program_dirs(env).copy() + def get_pic_args(self) -> T.List[str]: return ['-fPIC'] - def name_string(self) -> str: - return ' '.join(self.exelist) - def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: return ['-include', os.path.basename(header)] def get_pch_name(self, header_name: str) -> str: return os.path.basename(header_name) + '.' + self.get_pch_suffix() - def get_linker_search_args(self, dirname: str) -> T.List[str]: - return self.linker.get_search_args(dirname) - - def get_default_include_dirs(self): + def get_default_include_dirs(self) -> T.List[str]: return [] def gen_export_dynamic_link_args(self, env: 'Environment') -> T.List[str]: @@ -201,13 +282,14 @@ def gen_import_library_args(self, implibname: str) -> T.List[str]: return self.linker.import_library_args(implibname) - def sanity_check_impl(self, work_dir, environment, sname, code): + def _sanity_check_impl(self, work_dir: str, environment: 'Environment', + sname: str, code: str) -> None: mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist)) - mlog.debug('Is cross compiler: %s.' % str(self.is_cross)) + mlog.debug(f'Is cross compiler: {self.is_cross!s}.') source_name = os.path.join(work_dir, sname) binname = sname.rsplit('.', 1)[0] - mode = 'link' + mode = CompileCheckMode.LINK if self.is_cross: binname += '_cross' if self.exe_wrapper is None: @@ -216,7 +298,7 @@ # on OSX the compiler binary is the same but you need # a ton of compiler flags to differentiate between # arm and x86_64. So just compile. - mode = 'compile' + mode = CompileCheckMode.COMPILE cargs, largs = self._get_basic_compiler_args(environment, mode) extra_flags = cargs + self.linker_to_compiler_args(largs) @@ -224,12 +306,12 @@ binname += '.exe' # Write binary check source binary_name = os.path.join(work_dir, binname) - with open(source_name, 'w') as ofile: + with open(source_name, 'w', encoding='utf-8') as ofile: ofile.write(code) # Compile sanity check # NOTE: extra_flags must be added at the end. On MSVC, it might contain a '/link' argument # after which all further arguments will be passed directly to the linker - cmdlist = self.exelist + [source_name] + self.get_output_args(binary_name) + extra_flags + cmdlist = self.exelist + [sname] + self.get_output_args(binname) + extra_flags pc, stdo, stde = mesonlib.Popen_safe(cmdlist, cwd=work_dir) mlog.debug('Sanity check compiler command line:', ' '.join(cmdlist)) mlog.debug('Sanity check compile stdout:') @@ -238,52 +320,57 @@ mlog.debug(stde) mlog.debug('-----') if pc.returncode != 0: - raise mesonlib.EnvironmentException('Compiler {0} can not compile programs.'.format(self.name_string())) + raise mesonlib.EnvironmentException(f'Compiler {self.name_string()} can not compile programs.') # Run sanity check if self.is_cross: if self.exe_wrapper is None: # Can't check if the binaries run so we have to assume they do return - cmdlist = self.exe_wrapper + [binary_name] + cmdlist = self.exe_wrapper.get_command() + [binary_name] else: cmdlist = [binary_name] mlog.debug('Running test binary command: ' + ' '.join(cmdlist)) try: pe = subprocess.Popen(cmdlist) except Exception as e: - raise mesonlib.EnvironmentException('Could not invoke sanity test executable: %s.' % str(e)) + raise mesonlib.EnvironmentException(f'Could not invoke sanity test executable: {e!s}.') pe.wait() if pe.returncode != 0: - raise mesonlib.EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string())) + raise mesonlib.EnvironmentException(f'Executables created by {self.language} compiler {self.name_string()} are not runnable.') - def sanity_check(self, work_dir, environment): + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: code = 'int main(void) { int class=0; return class; }\n' - return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) + return self._sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) - def check_header(self, hname, prefix, env, *, extra_args=None, dependencies=None): - fargs = {'prefix': prefix, 'header': hname} - code = '''{prefix} - #include <{header}>''' - return self.compiles(code.format(**fargs), env, extra_args=extra_args, + def check_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + code = f'''{prefix} + #include <{hname}>''' + return self.compiles(code, env, extra_args=extra_args, dependencies=dependencies) - def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None, disable_cache=False): - fargs = {'prefix': prefix, 'header': hname} - code = '''{prefix} + def has_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + disable_cache: bool = False) -> T.Tuple[bool, bool]: + code = f'''{prefix} #ifdef __has_include - #if !__has_include("{header}") - #error "Header '{header}' could not be found" + #if !__has_include("{hname}") + #error "Header '{hname}' could not be found" #endif #else - #include <{header}> + #include <{hname}> #endif''' - return self.compiles(code.format(**fargs), env, extra_args=extra_args, + return self.compiles(code, env, extra_args=extra_args, dependencies=dependencies, mode='preprocess', disable_cache=disable_cache) - def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None): - fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} - t = '''{prefix} - #include <{header}> + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + t = f'''{prefix} + #include <{hname}> int main(void) {{ /* If it's not defined as a macro, try to use as a symbol */ #ifndef {symbol} @@ -291,17 +378,28 @@ #endif return 0; }}''' - return self.compiles(t.format(**fargs), env, extra_args=extra_args, + return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies) - def _get_basic_compiler_args(self, env, mode): - cargs, largs = [], [] - # Select a CRT if needed since we're linking - if mode == 'link': - cargs += self.get_linker_debug_crt_args() + def _get_basic_compiler_args(self, env: 'Environment', mode: CompileCheckMode) -> T.Tuple[T.List[str], T.List[str]]: + cargs = [] # type: T.List[str] + largs = [] # type: T.List[str] + if mode is CompileCheckMode.LINK: + # Sometimes we need to manually select the CRT to use with MSVC. + # One example is when trying to do a compiler check that involves + # linking with static libraries since MSVC won't select a CRT for + # us in that case and will error out asking us to pick one. + try: + crt_val = env.coredata.options[OptionKey('b_vscrt')].value + buildtype = env.coredata.options[OptionKey('buildtype')].value + cargs += self.get_crt_compile_args(crt_val, buildtype) + except (KeyError, AttributeError): + pass # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env sys_args = env.coredata.get_external_args(self.for_machine, self.language) + if isinstance(sys_args, str): + sys_args = [sys_args] # Apparently it is a thing to inject linker flags both # via CFLAGS _and_ LDFLAGS, even though the former are # also used during linking. These flags can break @@ -309,7 +407,11 @@ cleaned_sys_args = self.remove_linkerlike_args(sys_args) cargs += cleaned_sys_args - if mode == 'link': + if mode is CompileCheckMode.LINK: + ld_value = env.lookup_binary_entry(self.for_machine, self.language + '_ld') + if ld_value is not None: + largs += self.use_linker_args(ld_value[0]) + # Add LDFLAGS from the env sys_ld_args = env.coredata.get_external_link_args(self.for_machine, self.language) # CFLAGS and CXXFLAGS go to both linking and compiling, but we want them @@ -319,24 +421,30 @@ cargs += self.get_compiler_args_for_mode(mode) return cargs, largs - def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): + def build_wrapper_args(self, env: 'Environment', + extra_args: T.Union[None, arglist.CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']], + mode: CompileCheckMode = CompileCheckMode.COMPILE) -> arglist.CompilerArgs: + # TODO: the caller should handle the listfing of these arguments if extra_args is None: extra_args = [] else: + # TODO: we want to do this in the caller extra_args = mesonlib.listify(extra_args) - extra_args = mesonlib.listify([e(mode) if callable(e) else e for e in extra_args]) + extra_args = mesonlib.listify([e(mode.value) if callable(e) else e for e in extra_args]) if dependencies is None: dependencies = [] - elif not isinstance(dependencies, list): + elif not isinstance(dependencies, collections.abc.Iterable): + # TODO: we want to ensure the front end does the listifing here dependencies = [dependencies] # Collect compiler arguments - cargs = compilers.CompilerArgs(self) - largs = [] + cargs = self.compiler_args() # type: arglist.CompilerArgs + largs = [] # type: T.List[str] for d in dependencies: # Add compile flags needed by dependencies cargs += d.get_compile_args() - if mode == 'link': + if mode is CompileCheckMode.LINK: # Add link flags needed to find dependencies largs += d.get_link_args() @@ -344,47 +452,34 @@ cargs += ca largs += la - cargs += self.get_compiler_check_args() + cargs += self.get_compiler_check_args(mode) # on MSVC compiler and linker flags must be separated by the "/link" argument # at this point, the '/link' argument may already be part of extra_args, otherwise, it is added here - if self.linker_to_compiler_args([]) == ['/link'] and largs != [] and not ('/link' in extra_args): + if self.linker_to_compiler_args([]) == ['/link'] and largs != [] and '/link' not in extra_args: extra_args += ['/link'] args = cargs + extra_args + largs return args - def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile', disable_cache=False): - with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: - return p.returncode == 0, p.cached - - def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False, disable_cache=False, temp_dir=None): - args = self._get_compiler_check_args(env, extra_args, dependencies, mode) - if disable_cache or want_output: - return self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) - return self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir) - - def links(self, code, env, *, extra_args=None, dependencies=None, disable_cache=False): - return self.compiles(code, env, extra_args=extra_args, - dependencies=dependencies, mode='link', disable_cache=disable_cache) - - def run(self, code: str, env, *, extra_args=None, dependencies=None): - if self.is_cross and self.exe_wrapper is None: + def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult: + need_exe_wrapper = env.need_exe_wrapper(self.for_machine) + if need_exe_wrapper and self.exe_wrapper is None: raise compilers.CrossNoRunException('Can not run test applications in this cross environment.') with self._build_wrapper(code, env, extra_args, dependencies, mode='link', want_output=True) as p: if p.returncode != 0: - mlog.debug('Could not compile test file %s: %d\n' % ( - p.input_name, - p.returncode)) + mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n') return compilers.RunResult(False) - if self.is_cross: - cmdlist = self.exe_wrapper + [p.output_name] + if need_exe_wrapper: + cmdlist = self.exe_wrapper.get_command() + [p.output_name] else: - cmdlist = p.output_name + cmdlist = [p.output_name] try: pe, so, se = mesonlib.Popen_safe(cmdlist) except Exception as e: - mlog.debug('Could not run: %s (error: %s)\n' % (cmdlist, e)) + mlog.debug(f'Could not run: {cmdlist} (error: {e})\n') return compilers.RunResult(False) mlog.debug('Program stdout:\n') @@ -393,27 +488,31 @@ mlog.debug(se) return compilers.RunResult(True, pe.returncode, so, se) - def _compile_int(self, expression, prefix, env, extra_args, dependencies): - fargs = {'prefix': prefix, 'expression': expression} - t = '''#include + def _compile_int(self, expression: str, prefix: str, env: 'Environment', + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']]) -> bool: + t = f'''#include {prefix} int main(void) {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}''' - return self.compiles(t.format(**fargs), env, extra_args=extra_args, + return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies)[0] - def cross_compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies): + def cross_compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], + guess: T.Optional[int], prefix: str, env: 'Environment', + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: # Try user's guess first if isinstance(guess, int): - if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies): + if self._compile_int(f'{expression} == {guess}', prefix, env, extra_args, dependencies): return guess # If no bounds are given, compute them in the limit of int32 maxint = 0x7fffffff minint = -0x80000000 if not isinstance(low, int) or not isinstance(high, int): - if self._compile_int('%s >= 0' % (expression), prefix, env, extra_args, dependencies): + if self._compile_int(f'{expression} >= 0', prefix, env, extra_args, dependencies): low = cur = 0 - while self._compile_int('%s > %d' % (expression, cur), prefix, env, extra_args, dependencies): + while self._compile_int(f'{expression} > {cur}', prefix, env, extra_args, dependencies): low = cur + 1 if low > maxint: raise mesonlib.EnvironmentException('Cross-compile check overflowed') @@ -423,7 +522,7 @@ high = cur else: high = cur = -1 - while self._compile_int('%s < %d' % (expression, cur), prefix, env, extra_args, dependencies): + while self._compile_int(f'{expression} < {cur}', prefix, env, extra_args, dependencies): high = cur - 1 if high < minint: raise mesonlib.EnvironmentException('Cross-compile check overflowed') @@ -435,33 +534,35 @@ # Sanity check limits given by user if high < low: raise mesonlib.EnvironmentException('high limit smaller than low limit') - condition = '%s <= %d && %s >= %d' % (expression, high, expression, low) + condition = f'{expression} <= {high} && {expression} >= {low}' if not self._compile_int(condition, prefix, env, extra_args, dependencies): raise mesonlib.EnvironmentException('Value out of given range') # Binary search while low != high: cur = low + int((high - low) / 2) - if self._compile_int('%s <= %d' % (expression, cur), prefix, env, extra_args, dependencies): + if self._compile_int(f'{expression} <= {cur}', prefix, env, extra_args, dependencies): high = cur else: low = cur + 1 return low - def compute_int(self, expression, low, high, guess, prefix, env, *, extra_args=None, dependencies=None): + def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], + guess: T.Optional[int], prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']] = None) -> int: if extra_args is None: extra_args = [] if self.is_cross: return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies) - fargs = {'prefix': prefix, 'expression': expression} - t = '''#include + t = f'''#include {prefix} int main(void) {{ printf("%ld\\n", (long)({expression})); return 0; - }};''' - res = self.run(t.format(**fargs), env, extra_args=extra_args, + }}''' + res = self.run(t, env, extra_args=extra_args, dependencies=dependencies) if not res.compiled: return -1 @@ -469,35 +570,37 @@ raise mesonlib.EnvironmentException('Could not run compute_int test binary.') return int(res.stdout) - def cross_sizeof(self, typename, prefix, env, *, extra_args=None, dependencies=None): + def cross_sizeof(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: if extra_args is None: extra_args = [] - fargs = {'prefix': prefix, 'type': typename} - t = '''#include + t = f'''#include {prefix} int main(void) {{ - {type} something; + {typename} something; return 0; }}''' - if not self.compiles(t.format(**fargs), env, extra_args=extra_args, + if not self.compiles(t, env, extra_args=extra_args, dependencies=dependencies)[0]: return -1 - return self.cross_compute_int('sizeof(%s)' % typename, None, None, None, prefix, env, extra_args, dependencies) + return self.cross_compute_int(f'sizeof({typename})', None, None, None, prefix, env, extra_args, dependencies) - def sizeof(self, typename, prefix, env, *, extra_args=None, dependencies=None): + def sizeof(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: if extra_args is None: extra_args = [] - fargs = {'prefix': prefix, 'type': typename} if self.is_cross: return self.cross_sizeof(typename, prefix, env, extra_args=extra_args, dependencies=dependencies) - t = '''#include + t = f'''#include {prefix} int main(void) {{ - printf("%ld\\n", (long)(sizeof({type}))); + printf("%ld\\n", (long)(sizeof({typename}))); return 0; - }};''' - res = self.run(t.format(**fargs), env, extra_args=extra_args, + }}''' + res = self.run(t, env, extra_args=extra_args, dependencies=dependencies) if not res.compiled: return -1 @@ -505,46 +608,48 @@ raise mesonlib.EnvironmentException('Could not run sizeof test binary.') return int(res.stdout) - def cross_alignment(self, typename, prefix, env, *, extra_args=None, dependencies=None): + def cross_alignment(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: if extra_args is None: extra_args = [] - fargs = {'prefix': prefix, 'type': typename} - t = '''#include + t = f'''#include {prefix} int main(void) {{ - {type} something; + {typename} something; return 0; }}''' - if not self.compiles(t.format(**fargs), env, extra_args=extra_args, + if not self.compiles(t, env, extra_args=extra_args, dependencies=dependencies)[0]: return -1 - t = '''#include + t = f'''#include {prefix} struct tmp {{ char c; - {type} target; + {typename} target; }};''' - return self.cross_compute_int('offsetof(struct tmp, target)', None, None, None, t.format(**fargs), env, extra_args, dependencies) + return self.cross_compute_int('offsetof(struct tmp, target)', None, None, None, t, env, extra_args, dependencies) - def alignment(self, typename, prefix, env, *, extra_args=None, dependencies=None): + def alignment(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: if extra_args is None: extra_args = [] if self.is_cross: return self.cross_alignment(typename, prefix, env, extra_args=extra_args, dependencies=dependencies) - fargs = {'prefix': prefix, 'type': typename} - t = '''#include + t = f'''#include #include {prefix} struct tmp {{ char c; - {type} target; + {typename} target; }}; int main(void) {{ printf("%d", (int)offsetof(struct tmp, target)); return 0; }}''' - res = self.run(t.format(**fargs), env, extra_args=extra_args, + res = self.run(t, env, extra_args=extra_args, dependencies=dependencies) if not res.compiled: raise mesonlib.EnvironmentException('Could not compile alignment test.') @@ -552,33 +657,39 @@ raise mesonlib.EnvironmentException('Could not run alignment test binary.') align = int(res.stdout) if align == 0: - raise mesonlib.EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename) + raise mesonlib.EnvironmentException(f'Could not determine alignment of {typename}. Sorry. You might want to file a bug.') return align - def get_define(self, dname, prefix, env, extra_args, dependencies, disable_cache=False): + def get_define(self, dname: str, prefix: str, env: 'Environment', + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']], + disable_cache: bool = False) -> T.Tuple[str, bool]: delim = '"MESON_GET_DEFINE_DELIMITER"' - fargs = {'prefix': prefix, 'define': dname, 'delim': delim} - code = ''' + code = f''' {prefix} - #ifndef {define} - # define {define} + #ifndef {dname} + # define {dname} #endif - {delim}\n{define}''' - args = self._get_compiler_check_args(env, extra_args, dependencies, - mode='preprocess').to_native() - func = lambda: self.cached_compile(code.format(**fargs), env.coredata, extra_args=args, mode='preprocess') + {delim}\n{dname}''' + args = self.build_wrapper_args(env, extra_args, dependencies, + mode=CompileCheckMode.PREPROCESS).to_native() + func = functools.partial(self.cached_compile, code, env.coredata, extra_args=args, mode='preprocess') if disable_cache: - func = lambda: self.compile(code.format(**fargs), extra_args=args, mode='preprocess', temp_dir=env.scratch_dir) + func = functools.partial(self.compile, code, extra_args=args, mode='preprocess', temp_dir=env.scratch_dir) with func() as p: cached = p.cached if p.returncode != 0: - raise mesonlib.EnvironmentException('Could not get define {!r}'.format(dname)) + raise mesonlib.EnvironmentException(f'Could not get define {dname!r}') # Get the preprocessed value after the delimiter, # minus the extra newline at the end and # merge string literals. - return self.concatenate_string_literals(p.stdo.split(delim + '\n')[-1][:-1]), cached + return self._concatenate_string_literals(p.stdout.split(delim + '\n')[-1][:-1]), cached - def get_return_value(self, fname, rtype, prefix, env, extra_args, dependencies): + def get_return_value(self, fname: str, rtype: str, prefix: str, + env: 'Environment', extra_args: T.Optional[T.List[str]], + dependencies: T.Optional[T.List['Dependency']]) -> T.Union[str, int]: + # TODO: rtype should be an enum. + # TODO: maybe we can use overload to tell mypy when this will return int vs str? if rtype == 'string': fmt = '%s' cast = '(char*)' @@ -586,29 +697,27 @@ fmt = '%lli' cast = '(long long int)' else: - raise AssertionError('BUG: Unknown return type {!r}'.format(rtype)) - fargs = {'prefix': prefix, 'f': fname, 'cast': cast, 'fmt': fmt} - code = '''{prefix} + raise AssertionError(f'BUG: Unknown return type {rtype!r}') + code = f'''{prefix} #include int main(void) {{ - printf ("{fmt}", {cast} {f}()); + printf ("{fmt}", {cast} {fname}()); return 0; - }}'''.format(**fargs) + }}''' res = self.run(code, env, extra_args=extra_args, dependencies=dependencies) if not res.compiled: - m = 'Could not get return value of {}()' - raise mesonlib.EnvironmentException(m.format(fname)) + raise mesonlib.EnvironmentException(f'Could not get return value of {fname}()') if rtype == 'string': return res.stdout elif rtype == 'int': try: return int(res.stdout.strip()) except ValueError: - m = 'Return value of {}() is not an int' - raise mesonlib.EnvironmentException(m.format(fname)) + raise mesonlib.EnvironmentException(f'Return value of {fname}() is not an int') + assert False, 'Unreachable' @staticmethod - def _no_prototype_templ(): + def _no_prototype_templ() -> T.Tuple[str, str]: """ Try to find the function without a prototype from a header by defining our own dummy prototype and trying to link with the C library (and @@ -643,7 +752,7 @@ return head, main @staticmethod - def _have_prototype_templ(): + def _have_prototype_templ() -> T.Tuple[str, str]: """ Returns a head-er and main() call that uses the headers listed by the user for the function prototype while checking if a function exists. @@ -658,13 +767,16 @@ # is not run so we don't care what the return value is. main = '''\nint main(void) {{ void *a = (void*) &{func}; - long b = (long) a; + long long b = (long long) a; return (int) b; }}''' return head, main - def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None): - """ + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + """Determine if a function exists. + First, this function looks for the symbol in the default libraries provided by the compiler (stdlib + a few others usually). If that fails, it checks if any of the headers specified in the prefix provide @@ -682,9 +794,13 @@ if val is not None: if isinstance(val, bool): return val, False - raise mesonlib.EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) + raise mesonlib.EnvironmentException(f'Cross variable {varname} is not a boolean.') - fargs = {'prefix': prefix, 'func': funcname} + # TODO: we really need a protocol for this, + # + # class StrProto(typing.Protocol): + # def __str__(self) -> str: ... + fargs = {'prefix': prefix, 'func': funcname} # type: T.Dict[str, T.Union[str, bool, int]] # glibc defines functions that are not available on Linux as stubs that # fail with ENOSYS (such as e.g. lchmod). In this case we want to fail @@ -727,56 +843,64 @@ # need to look for them differently. On nice compilers like clang, we # can just directly use the __has_builtin() macro. fargs['no_includes'] = '#include' not in prefix + is_builtin = funcname.startswith('__builtin_') + fargs['is_builtin'] = is_builtin + fargs['__builtin_'] = '' if is_builtin else '__builtin_' t = '''{prefix} int main(void) {{ + + /* With some toolchains (MSYS2/mingw for example) the compiler + * provides various builtins which are not really implemented and + * fall back to the stdlib where they aren't provided and fail at + * build/link time. In case the user provides a header, including + * the header didn't lead to the function being defined, and the + * function we are checking isn't a builtin itself we assume the + * builtin is not functional and we just error out. */ + #if !{no_includes:d} && !defined({func}) && !{is_builtin:d} + #error "No definition for {__builtin_}{func} found in the prefix" + #endif + #ifdef __has_builtin - #if !__has_builtin(__builtin_{func}) - #error "__builtin_{func} not found" + #if !__has_builtin({__builtin_}{func}) + #error "{__builtin_}{func} not found" #endif #elif ! defined({func}) - /* Check for __builtin_{func} only if no includes were added to the - * prefix above, which means no definition of {func} can be found. - * We would always check for this, but we get false positives on - * MSYS2 if we do. Their toolchain is broken, but we can at least - * give them a workaround. */ - #if {no_includes:d} - __builtin_{func}; - #else - #error "No definition for __builtin_{func} found in the prefix" - #endif + {__builtin_}{func}; #endif return 0; }}''' return self.links(t.format(**fargs), env, extra_args=extra_args, dependencies=dependencies) - def has_members(self, typename, membernames, prefix, env, *, extra_args=None, dependencies=None): + def has_members(self, typename: str, membernames: T.List[str], + prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: if extra_args is None: extra_args = [] - fargs = {'prefix': prefix, 'type': typename, 'name': 'foo'} # Create code that accesses all members members = '' for member in membernames: - members += '{}.{};\n'.format(fargs['name'], member) - fargs['members'] = members - t = '''{prefix} + members += f'foo.{member};\n' + t = f'''{prefix} void bar(void) {{ - {type} {name}; + {typename} foo; {members} - }};''' - return self.compiles(t.format(**fargs), env, extra_args=extra_args, + }}''' + return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies) - def has_type(self, typename, prefix, env, extra_args, dependencies=None): - fargs = {'prefix': prefix, 'type': typename} - t = '''{prefix} + def has_type(self, typename: str, prefix: str, env: 'Environment', + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], *, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + t = f'''{prefix} void bar(void) {{ - sizeof({type}); - }};''' - return self.compiles(t.format(**fargs), env, extra_args=extra_args, + sizeof({typename}); + }}''' + return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies) - def symbols_have_underscore_prefix(self, env): + def symbols_have_underscore_prefix(self, env: 'Environment') -> bool: ''' Check if the compiler prefixes an underscore to global C symbols ''' @@ -789,15 +913,13 @@ } #endif ''' - args = self.get_compiler_check_args() + args = self.get_compiler_check_args(CompileCheckMode.COMPILE) n = 'symbols_have_underscore_prefix' with self._build_wrapper(code, env, extra_args=args, mode='compile', want_output=True, temp_dir=env.scratch_dir) as p: if p.returncode != 0: - m = 'BUG: Unable to compile {!r} check: {}' - raise RuntimeError(m.format(n, p.stdo)) + raise RuntimeError(f'BUG: Unable to compile {n!r} check: {p.stdout}') if not os.path.isfile(p.output_name): - m = 'BUG: Can\'t find compiled test code for {!r} check' - raise RuntimeError(m.format(n)) + raise RuntimeError(f'BUG: Can\'t find compiled test code for {n!r} check') with open(p.output_name, 'rb') as o: for line in o: # Check if the underscore form of the symbol is somewhere @@ -809,10 +931,10 @@ elif symbol_name in line: mlog.debug("Symbols have underscore prefix: NO") return False - raise RuntimeError('BUG: {!r} check failed unexpectedly'.format(n)) + raise RuntimeError(f'BUG: {n!r} check failed unexpectedly') - def _get_patterns(self, env, prefixes, suffixes, shared=False): - patterns = [] + def _get_patterns(self, env: 'Environment', prefixes: T.List[str], suffixes: T.List[str], shared: bool = False) -> T.List[str]: + patterns = [] # type: T.List[str] for p in prefixes: for s in suffixes: patterns.append(p + '{}.' + s) @@ -828,7 +950,7 @@ patterns.append(p + '{}.so.[0-9]*.[0-9]*') return patterns - def get_library_naming(self, env, libtype: LibType, strict=False): + def get_library_naming(self, env: 'Environment', libtype: LibType, strict: bool = False) -> T.Tuple[str, ...]: ''' Get library prefixes and suffixes for the target platform ordered by priority @@ -875,8 +997,8 @@ return tuple(patterns) @staticmethod - def _sort_shlibs_openbsd(libs): - filtered = [] + def _sort_shlibs_openbsd(libs: T.List[str]) -> T.List[str]: + filtered = [] # type: T.List[str] for lib in libs: # Validate file as a shared library of type libfoo.so.X.Y ret = lib.rsplit('.so.', maxsplit=1) @@ -891,7 +1013,7 @@ return sorted(filtered, key=float_cmp, reverse=True) @classmethod - def _get_trials_from_pattern(cls, pattern, directory, libname): + def _get_trials_from_pattern(cls, pattern: str, directory: str, libname: str) -> T.List[Path]: f = Path(directory) / pattern.format(libname) # Globbing for OpenBSD if '*' in pattern: @@ -901,7 +1023,7 @@ return [f] @staticmethod - def _get_file_from_list(env, files: T.List[str]) -> Path: + def _get_file_from_list(env: 'Environment', paths: T.List[Path]) -> Path: ''' We just check whether the library exists. We can't do a link check because the library might have unresolved symbols that require other @@ -909,31 +1031,29 @@ architecture. ''' # If not building on macOS for Darwin, do a simple file check - files = [Path(f) for f in files] if not env.machines.host.is_darwin() or not env.machines.build.is_darwin(): - for f in files: - if f.is_file(): - return f + for p in paths: + if p.is_file(): + return p # Run `lipo` and check if the library supports the arch we want - for f in files: - if not f.is_file(): + for p in paths: + if not p.is_file(): continue - archs = mesonlib.darwin_get_object_archs(f) + archs = mesonlib.darwin_get_object_archs(str(p)) if archs and env.machines.host.cpu_family in archs: - return f + return p else: - mlog.debug('Rejected {}, supports {} but need {}' - .format(f, archs, env.machines.host.cpu_family)) + mlog.debug(f'Rejected {p}, supports {archs} but need {env.machines.host.cpu_family}') return None @functools.lru_cache() - def output_is_64bit(self, env): + def output_is_64bit(self, env: 'Environment') -> bool: ''' returns true if the output produced is 64-bit, false if 32-bit ''' return self.sizeof('void *', '', env) == 8 - def find_library_real(self, libname, env, extra_dirs, code, libtype: LibType): + def _find_library_real(self, libname: str, env: 'Environment', extra_dirs: T.List[str], code: str, libtype: LibType) -> T.Optional[T.List[str]]: # First try if we can just add the library as -l. # Gcc + co seem to prefer builtin lib dirs to -L dirs. # Only try to find std libs if no extra dirs specified. @@ -942,7 +1062,7 @@ if ((not extra_dirs and libtype is LibType.PREFER_SHARED) or libname in self.internal_libs): cargs = ['-l' + libname] - largs = self.get_allow_undefined_link_args() + largs = self.get_linker_always_args() + self.get_allow_undefined_link_args() extra_args = cargs + self.linker_to_compiler_args(largs) if self.links(code, env, extra_args=extra_args, disable_cache=True)[0]: @@ -966,16 +1086,17 @@ # Search in the specified dirs, and then in the system libraries for d in itertools.chain(extra_dirs, self.get_library_dirs(env, elf_class)): for p in patterns: - trial = self._get_trials_from_pattern(p, d, libname) - if not trial: + trials = self._get_trials_from_pattern(p, d, libname) + if not trials: continue - trial = self._get_file_from_list(env, trial) + trial = self._get_file_from_list(env, trials) if not trial: continue return [trial.as_posix()] return None - def find_library_impl(self, libname, env, extra_dirs, code, libtype: LibType): + def _find_library_impl(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + code: str, libtype: LibType) -> T.Optional[T.List[str]]: # These libraries are either built-in or invalid if libname in self.ignore_libs: return [] @@ -983,24 +1104,26 @@ extra_dirs = [extra_dirs] key = (tuple(self.exelist), libname, tuple(extra_dirs), code, libtype) if key not in self.find_library_cache: - value = self.find_library_real(libname, env, extra_dirs, code, libtype) + value = self._find_library_real(libname, env, extra_dirs, code, libtype) self.find_library_cache[key] = value else: value = self.find_library_cache[key] if value is None: return None - return value[:] + return value.copy() - def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED): - code = 'int main(void) { return 0; }' - return self.find_library_impl(libname, env, extra_dirs, code, libtype) + def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: + code = 'int main(void) { return 0; }\n' + return self._find_library_impl(libname, env, extra_dirs, code, libtype) - def find_framework_paths(self, env): + def find_framework_paths(self, env: 'Environment') -> T.List[str]: ''' These are usually /Library/Frameworks and /System/Library/Frameworks, unless you select a particular macOS SDK with the -isysroot flag. You can also add to this by setting -F in CFLAGS. ''' + # TODO: this really needs to be *AppleClang*, not just any clang. if self.id != 'clang': raise mesonlib.MesonException('Cannot find framework path with non-clang compiler') # Construct the compiler command-line @@ -1012,7 +1135,7 @@ os_env = os.environ.copy() os_env['LC_ALL'] = 'C' _, _, stde = mesonlib.Popen_safe(commands, env=os_env, stdin=subprocess.PIPE) - paths = [] + paths = [] # T.List[str] for line in stde.split('\n'): if '(framework directory)' not in line: continue @@ -1021,7 +1144,7 @@ paths.append(line[:-21].strip()) return paths - def find_framework_real(self, name, env, extra_dirs, allow_system): + def _find_framework_real(self, name: str, env: 'Environment', extra_dirs: T.List[str], allow_system: bool) -> T.Optional[T.List[str]]: code = 'int main(void) { return 0; }' link_args = [] for d in extra_dirs: @@ -1032,80 +1155,88 @@ link_args += ['-framework', name] if self.links(code, env, extra_args=(extra_args + link_args), disable_cache=True)[0]: return link_args + return None - def find_framework_impl(self, name, env, extra_dirs, allow_system): + def _find_framework_impl(self, name: str, env: 'Environment', extra_dirs: T.List[str], + allow_system: bool) -> T.Optional[T.List[str]]: if isinstance(extra_dirs, str): extra_dirs = [extra_dirs] key = (tuple(self.exelist), name, tuple(extra_dirs), allow_system) if key in self.find_framework_cache: value = self.find_framework_cache[key] else: - value = self.find_framework_real(name, env, extra_dirs, allow_system) + value = self._find_framework_real(name, env, extra_dirs, allow_system) self.find_framework_cache[key] = value if value is None: return None - return value[:] + return value.copy() - def find_framework(self, name, env, extra_dirs, allow_system=True): + def find_framework(self, name: str, env: 'Environment', extra_dirs: T.List[str], + allow_system: bool = True) -> T.Optional[T.List[str]]: ''' Finds the framework with the specified name, and returns link args for the same or returns None when the framework is not found. ''' - if self.id != 'clang': - raise mesonlib.MesonException('Cannot find frameworks with non-clang compiler') - return self.find_framework_impl(name, env, extra_dirs, allow_system) + # TODO: should probably check for macOS? + return self._find_framework_impl(name, env, extra_dirs, allow_system) def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + # TODO: does this belong here or in GnuLike or maybe PosixLike? return [] def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + # TODO: does this belong here or in GnuLike or maybe PosixLike? return [] - def thread_flags(self, env): + def thread_flags(self, env: 'Environment') -> T.List[str]: + # TODO: does this belong here or in GnuLike or maybe PosixLike? host_m = env.machines[self.for_machine] if host_m.is_haiku() or host_m.is_darwin(): return [] return ['-pthread'] - def thread_link_flags(self, env: 'Environment') -> T.List[str]: - return self.linker.thread_flags(env) + def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: + return args.copy() - def linker_to_compiler_args(self, args): - return args - - def has_arguments(self, args, env, code, mode): + def has_arguments(self, args: T.List[str], env: 'Environment', code: str, + mode: str) -> T.Tuple[bool, bool]: return self.compiles(code, env, extra_args=args, mode=mode) - def has_multi_arguments(self, args, env): - for arg in args[:]: + def _has_multi_arguments(self, args: T.List[str], env: 'Environment', code: str) -> T.Tuple[bool, bool]: + new_args = [] # type: T.List[str] + for arg in args: # some compilers, e.g. GCC, don't warn for unsupported warning-disable # flags, so when we are testing a flag like "-Wno-forgotten-towel", also # check the equivalent enable flag too "-Wforgotten-towel" if arg.startswith('-Wno-'): - args.append('-W' + arg[5:]) + new_args.append('-W' + arg[5:]) if arg.startswith('-Wl,'): - mlog.warning('{} looks like a linker argument, ' + mlog.warning(f'{arg} looks like a linker argument, ' 'but has_argument and other similar methods only ' 'support checking compiler arguments. Using them ' 'to check linker arguments are never supported, ' 'and results are likely to be wrong regardless of ' 'the compiler you are using. has_link_argument or ' - 'other similar method can be used instead.' - .format(arg)) - code = 'int i;\n' - return self.has_arguments(args, env, code, mode='compile') + 'other similar method can be used instead.') + new_args.append(arg) + return self.has_arguments(new_args, env, code, mode='compile') + + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self._has_multi_arguments(args, env, 'extern int i;\nint i;\n') - def has_multi_link_arguments(self, args, env): + def _has_multi_link_arguments(self, args: T.List[str], env: 'Environment', code: str) -> T.Tuple[bool, bool]: # First time we check for link flags we need to first check if we have # --fatal-warnings, otherwise some linker checks could give some # false positive. args = self.linker.fatal_warnings() + args args = self.linker_to_compiler_args(args) - code = 'int main(void) { return 0; }' return self.has_arguments(args, env, code, mode='link') + def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self._has_multi_link_arguments(args, env, 'int main(void) { return 0; }\n') + @staticmethod - def concatenate_string_literals(s): + def _concatenate_string_literals(s: str) -> str: pattern = re.compile(r'(?P
.*([^\\]")|^")(?P([^\\"]|\\.)*)"\s+"(?P([^\\"]|\\.)*)(?P".*)')
         ret = s
         m = pattern.match(ret)
@@ -1114,7 +1245,13 @@
             m = pattern.match(ret)
         return ret
 
-    def has_func_attribute(self, name, env):
+    def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
+        # Most compilers (such as GCC and Clang) only warn about unknown or
+        # ignored attributes, so force an error. Overridden in GCC and Clang
+        # mixins.
+        return ['-Werror']
+
+    def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
         # Just assume that if we're not on windows that dllimport and dllexport
         # don't work
         m = env.machines[self.for_machine]
@@ -1122,6 +1259,8 @@
             if name in ['dllimport', 'dllexport']:
                 return False, False
 
-        # Clang and GCC both return warnings if the __attribute__ is undefined,
-        # so set -Werror
-        return self.compiles(self.attribute_check_func(name), env, extra_args='-Werror')
+        return self.compiles(self.attribute_check_func(name), env,
+                             extra_args=self.get_has_func_attribute_extra_args(name))
+
+    def get_disable_assert_args(self) -> T.List[str]:
+        return ['-DNDEBUG']
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/compcert.py meson-0.61.2/mesonbuild/compilers/mixins/compcert.py
--- meson-0.53.2/mesonbuild/compilers/mixins/compcert.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/compcert.py	2022-01-17 10:50:45.000000000 +0000
@@ -0,0 +1,131 @@
+# Copyright 2012-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Representations specific to the CompCert C compiler family."""
+
+import os
+import re
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+ccomp_buildtype_args = {
+    'plain': [''],
+    'debug': ['-O0', '-g'],
+    'debugoptimized': ['-O0', '-g'],
+    'release': ['-03'],
+    'minsize': ['-Os'],
+    'custom': ['-Obranchless'],
+}  # type: T.Dict[str, T.List[str]]
+
+ccomp_optimization_args = {
+    '0': ['-O0'],
+    'g': ['-O0'],
+    '1': ['-O1'],
+    '2': ['-O2'],
+    '3': ['-O3'],
+    's': ['-Os']
+}  # type: T.Dict[str, T.List[str]]
+
+ccomp_debug_args = {
+    False: [],
+    True: ['-g']
+}  # type: T.Dict[bool, T.List[str]]
+
+# As of CompCert 20.04, these arguments should be passed to the underlying gcc linker (via -WUl,)
+# There are probably (many) more, but these are those used by picolibc
+ccomp_args_to_wul = [
+        r"^-ffreestanding$",
+        r"^-r$"
+] # type: T.List[str]
+
+class CompCertCompiler(Compiler):
+
+    def __init__(self) -> None:
+        self.id = 'ccomp'
+        # Assembly
+        self.can_compile_suffixes.add('s')
+        default_warn_args = []  # type: T.List[str]
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + [],
+                          '3': default_warn_args + []}  # type: T.Dict[str, T.List[str]]
+
+    def get_always_args(self) -> T.List[str]:
+        return []
+
+    def get_pic_args(self) -> T.List[str]:
+        # As of now, CompCert does not support PIC
+        return []
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return ccomp_buildtype_args[buildtype]
+
+    def get_pch_suffix(self) -> str:
+        return 'pch'
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        return []
+
+    def unix_args_to_native(self, args: T.List[str]) -> T.List[str]:
+        "Always returns a copy that can be independently mutated"
+        patched_args = []  # type: T.List[str]
+        for arg in args:
+            added = 0
+            for ptrn in ccomp_args_to_wul:
+                if re.match(ptrn, arg):
+                    patched_args.append('-WUl,' + arg)
+                    added = 1
+            if not added:
+                patched_args.append(arg)
+        return patched_args
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def get_preprocess_only_args(self) -> T.List[str]:
+        return ['-E']
+
+    def get_compile_only_args(self) -> T.List[str]:
+        return ['-c']
+
+    def get_coverage_args(self) -> T.List[str]:
+        return []
+
+    def get_no_stdinc_args(self) -> T.List[str]:
+        return ['-nostdinc']
+
+    def get_no_stdlib_link_args(self) -> T.List[str]:
+        return ['-nostdlib']
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return ccomp_optimization_args[optimization_level]
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return ccomp_debug_args[is_debug]
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:9] == '-I':
+                parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
+
+        return parameter_list
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/elbrus.py meson-0.61.2/mesonbuild/compilers/mixins/elbrus.py
--- meson-0.53.2/mesonbuild/compilers/mixins/elbrus.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/elbrus.py	2022-01-17 10:50:45.000000000 +0000
@@ -21,21 +21,26 @@
 
 from .gnu import GnuLikeCompiler
 from .gnu import gnu_optimization_args
-from ...mesonlib import Popen_safe
+from ...mesonlib import Popen_safe, OptionKey
 
 if T.TYPE_CHECKING:
     from ...environment import Environment
+    from ...coredata import KeyedOptionDictType
 
 
 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.
-    def __init__(self):
+
+    def __init__(self) -> None:
         super().__init__()
         self.id = 'lcc'
-        self.base_options = ['b_pgo', 'b_coverage',
-                             'b_ndebug', 'b_staticpic',
-                             'b_lundef', 'b_asneeded']
+        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': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + ['-Wextra'],
+                          '3': default_warn_args + ['-Wextra', '-Wpedantic']}
 
     # FIXME: use _build_wrapper to call this so that linker flags from the env
     # get applied
@@ -75,9 +80,19 @@
     def get_optimization_args(self, optimization_level: str) -> T.List[str]:
         return gnu_optimization_args[optimization_level]
 
+    def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]:
+        return ['-r', '-nodefaultlibs', '-nostartfiles', '-o', prelink_name] + obj_list
+
     def get_pch_suffix(self) -> str:
         # Actually it's not supported for now, but probably will be supported in future
         return 'pch'
 
+    def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        args = []
+        std = options[OptionKey('std', lang=self.language, machine=self.for_machine)]
+        if std.value != 'none':
+            args.append('-std=' + std.value)
+        return args
+
     def openmp_flags(self) -> T.List[str]:
         return ['-fopenmp']
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/emscripten.py meson-0.61.2/mesonbuild/compilers/mixins/emscripten.py
--- meson-0.53.2/mesonbuild/compilers/mixins/emscripten.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/emscripten.py	2021-11-02 19:58:07.000000000 +0000
@@ -17,22 +17,35 @@
 import os.path
 import typing as T
 
-from ...mesonlib import MesonException
-
-class EmscriptenMixin:
-    def get_option_link_args(self, options):
-        return []
-
-    def get_soname_args(self, *args, **kwargs):
-        raise MesonException('Emscripten does not support shared libraries.')
-
-    def get_allow_undefined_link_args(self) -> T.List[str]:
-        return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0']
+from ... import coredata
+from ... import mesonlib
+from ...mesonlib import OptionKey
+from ...mesonlib import LibType
+
+if T.TYPE_CHECKING:
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+    from ...dependencies import Dependency
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+
+def wrap_js_includes(args: T.List[str]) -> T.List[str]:
+    final_args = []
+    for i in args:
+        if i.endswith('.js') and not i.startswith('-'):
+            final_args += ['--js-library', i]
+        else:
+            final_args += [i]
+    return final_args
 
-    def get_linker_output_args(self, output: str) -> T.List[str]:
-        return ['-o', output]
+class EmscriptenMixin(Compiler):
 
-    def _get_compile_output(self, dirname, mode):
+    def _get_compile_output(self, dirname: str, mode: str) -> str:
         # In pre-processor mode, the output is sent to stdout and discarded
         if mode == 'preprocess':
             return None
@@ -42,5 +55,49 @@
         if mode == 'link':
             suffix = 'js'
         else:
-            suffix = 'wasm'
+            suffix = 'o'
         return os.path.join(dirname, 'output.' + suffix)
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return ['-s', 'USE_PTHREADS=1']
+
+    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
+        args = ['-s', 'USE_PTHREADS=1']
+        count: int = env.coredata.options[OptionKey('thread_count', lang=self.language, machine=self.for_machine)].value
+        if count:
+            args.extend(['-s', f'PTHREAD_POOL_SIZE={count}'])
+        return args
+
+    def get_options(self) -> 'coredata.KeyedOptionDictType':
+        opts = super().get_options()
+        key = OptionKey('thread_count', machine=self.for_machine, lang=self.language)
+        opts.update({
+            key: coredata.UserIntegerOption(
+                'Number of threads to use in web assembly, set to 0 to disable',
+                (0, None, 4),  # Default was picked at random
+            ),
+        })
+
+        return opts
+
+    @classmethod
+    def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
+        return wrap_js_includes(super().native_args_to_unix(args))
+
+    def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]:
+        return wrap_js_includes(super().get_dependency_link_args(dep))
+
+    def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
+                     libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]:
+        if not libname.endswith('.js'):
+            return super().find_library(libname, env, extra_dirs, libtype)
+        if os.path.isabs(libname):
+            if os.path.exists(libname):
+                return [libname]
+        if len(extra_dirs) == 0:
+            raise mesonlib.EnvironmentException('Looking up Emscripten JS libraries requires either an absolute path or specifying extra_dirs.')
+        for d in extra_dirs:
+            abs_path = os.path.join(d, libname)
+            if os.path.exists(abs_path):
+                return [abs_path]
+        return None
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/gnu.py meson-0.61.2/mesonbuild/compilers/mixins/gnu.py
--- meson-0.53.2/mesonbuild/compilers/mixins/gnu.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/gnu.py	2022-01-17 10:50:45.000000000 +0000
@@ -17,6 +17,7 @@
 import abc
 import functools
 import os
+import multiprocessing
 import pathlib
 import re
 import subprocess
@@ -24,10 +25,18 @@
 
 from ... import mesonlib
 from ... import mlog
+from ...mesonlib import OptionKey
 
 if T.TYPE_CHECKING:
-    from ...coredata import UserOption  # noqa: F401
+    from ..._typing import ImmutableListProtocol
     from ...environment import Environment
+    from ..compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
 
 # XXX: prevent circular references.
 # FIXME: this really is a posix interface not a c-like interface
@@ -84,7 +93,7 @@
 
 
 @functools.lru_cache(maxsize=None)
-def gnulike_default_include_dirs(compiler: T.Tuple[str], lang: str) -> T.List[str]:
+def gnulike_default_include_dirs(compiler: T.Tuple[str, ...], lang: str) -> 'ImmutableListProtocol[str]':
     lang_map = {
         'c': 'c',
         'cpp': 'c++',
@@ -96,7 +105,7 @@
     lang = lang_map[lang]
     env = os.environ.copy()
     env["LC_ALL"] = 'C'
-    cmd = list(compiler) + ['-x{}'.format(lang), '-E', '-v', '-']
+    cmd = list(compiler) + [f'-x{lang}', '-E', '-v', '-']
     p = subprocess.Popen(
         cmd,
         stdin=subprocess.DEVNULL,
@@ -106,7 +115,7 @@
     )
     stdout = p.stdout.read().decode('utf-8', errors='replace')
     parse_state = 0
-    paths = []
+    paths = []  # type: T.List[str]
     for line in stdout.split('\n'):
         line = line.strip(' \n\r\t')
         if parse_state == 0:
@@ -129,7 +138,7 @@
     return paths
 
 
-class GnuLikeCompiler(metaclass=abc.ABCMeta):
+class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta):
     """
     GnuLikeCompiler is a common interface to all compilers implementing
     the GNU-style commandline interface. This includes GCC, Clang
@@ -139,13 +148,16 @@
 
     LINKER_PREFIX = '-Wl,'
 
-    def __init__(self):
-        self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
-                             'b_ndebug', 'b_staticpic', 'b_pie']
+    def __init__(self) -> None:
+        self.base_options = {
+            OptionKey(o) for o in ['b_pch', 'b_lto', 'b_pgo', 'b_coverage',
+                                   'b_ndebug', 'b_staticpic', 'b_pie']}
         if not (self.info.is_windows() or self.info.is_cygwin() or self.info.is_openbsd()):
-            self.base_options.append('b_lundef')
+            self.base_options.add(OptionKey('b_lundef'))
         if not self.info.is_windows() or self.info.is_cygwin():
-            self.base_options.append('b_asneeded')
+            self.base_options.add(OptionKey('b_asneeded'))
+        if not self.info.is_hurd():
+            self.base_options.add(OptionKey('b_sanitize'))
         # All GCC-like backends can do assembly
         self.can_compile_suffixes.add('s')
 
@@ -162,14 +174,14 @@
 
     @abc.abstractmethod
     def get_optimization_args(self, optimization_level: str) -> T.List[str]:
-        raise NotImplementedError("get_optimization_args not implemented")
+        pass
 
     def get_debug_args(self, is_debug: bool) -> T.List[str]:
         return clike_debug_args[is_debug]
 
     @abc.abstractmethod
     def get_pch_suffix(self) -> str:
-        raise NotImplementedError("get_pch_suffix not implemented")
+        pass
 
     def split_shlib_to_parts(self, fname: str) -> T.Tuple[str, str]:
         return os.path.dirname(fname), fname
@@ -178,11 +190,11 @@
         return gnulike_instruction_set_args.get(instruction_set, None)
 
     def get_default_include_dirs(self) -> T.List[str]:
-        return gnulike_default_include_dirs(tuple(self.exelist), self.language)
+        return gnulike_default_include_dirs(tuple(self.exelist), self.language).copy()
 
     @abc.abstractmethod
     def openmp_flags(self) -> T.List[str]:
-        raise NotImplementedError("openmp_flags not implemented")
+        pass
 
     def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]:
         return gnu_symbol_visibility_args[vistype]
@@ -207,9 +219,7 @@
         return ['-fprofile-use', '-fprofile-correction']
 
     def get_gui_app_args(self, value: bool) -> T.List[str]:
-        if self.info.is_windows() or self.info.is_cygwin():
-            return ['-mwindows' if value else '-mconsole']
-        return []
+        return ['-mwindows' if value else '-mconsole']
 
     def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
         for idx, i in enumerate(parameter_list):
@@ -221,12 +231,10 @@
     @functools.lru_cache()
     def _get_search_dirs(self, env: 'Environment') -> str:
         extra_args = ['--print-search-dirs']
-        stdo = None
         with self._build_wrapper('', env, extra_args=extra_args,
                                  dependencies=None, mode='compile',
                                  want_output=True) as p:
-            stdo = p.stdo
-        return stdo
+            return p.stdout
 
     def _split_fetch_real_dirs(self, pathstr: str) -> T.List[str]:
         # We need to use the path separator used by the compiler for printing
@@ -275,7 +283,9 @@
                 return self._split_fetch_real_dirs(line.split('=', 1)[1])
         return []
 
-    def get_lto_compile_args(self) -> T.List[str]:
+    def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]:
+        # This provides a base for many compilers, GCC and Clang override this
+        # for their specific arguments
         return ['-flto']
 
     def sanitizer_compile_args(self, value: str) -> T.List[str]:
@@ -289,7 +299,7 @@
     def get_output_args(self, target: str) -> T.List[str]:
         return ['-o', target]
 
-    def get_dependency_gen_args(self, outtarget, outfile):
+    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
         return ['-MD', '-MQ', outtarget, '-MF', outfile]
 
     def get_compile_only_args(self) -> T.List[str]:
@@ -304,7 +314,13 @@
 
     @classmethod
     def use_linker_args(cls, linker: str) -> T.List[str]:
-        return ['-fuse-ld={}'.format(linker)]
+        if linker not in {'gold', 'bfd', 'lld'}:
+            raise mesonlib.MesonException(
+                f'Unsupported linker, only bfd, gold, and lld are supported, not {linker}.')
+        return [f'-fuse-ld={linker}']
+
+    def get_coverage_args(self) -> T.List[str]:
+        return ['--coverage']
 
 
 class GnuCompiler(GnuLikeCompiler):
@@ -313,11 +329,11 @@
     Compilers imitating GCC (Clang/Intel) should use the GnuLikeCompiler ABC.
     """
 
-    def __init__(self, defines: T.Dict[str, str]):
+    def __init__(self, defines: T.Optional[T.Dict[str, str]]):
         super().__init__()
         self.id = 'gcc'
         self.defines = defines or {}
-        self.base_options.append('b_colorout')
+        self.base_options.update({OptionKey('b_colorout'), OptionKey('b_lto_threads')})
 
     def get_colorout_args(self, colortype: str) -> T.List[str]:
         if mesonlib.version_compare(self.version, '>=4.9.0'):
@@ -325,6 +341,7 @@
         return []
 
     def get_warn_args(self, level: str) -> T.List[str]:
+        # Mypy doesn't understand cooperative inheritance
         args = super().get_warn_args(level)
         if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args:
             # -Wpedantic was added in 4.8.0
@@ -349,14 +366,33 @@
     def openmp_flags(self) -> T.List[str]:
         return ['-fopenmp']
 
-    def has_arguments(self, args, env, code, mode):
+    def has_arguments(self, args: T.List[str], env: 'Environment', code: str,
+                      mode: str) -> T.Tuple[bool, bool]:
         # For some compiler command line arguments, the GNU compilers will
         # emit a warning on stderr indicating that an option is valid for a
         # another language, but still complete with exit_success
-        with self._build_wrapper(code, env, args, None, mode, disable_cache=False, want_output=True) as p:
+        with self._build_wrapper(code, env, args, None, mode) as p:
             result = p.returncode == 0
-            if self.language in {'cpp', 'objcpp'} and 'is valid for C/ObjC' in p.stde:
+            if self.language in {'cpp', 'objcpp'} and 'is valid for C/ObjC' in p.stderr:
                 result = False
-            if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stde:
+            if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stderr:
                 result = False
         return result, p.cached
+
+    def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
+        # GCC only warns about unknown or ignored attributes, so force an
+        # error.
+        return ['-Werror=attributes']
+
+    def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]:
+        return ['-r', '-o', prelink_name] + obj_list
+
+    def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]:
+        if threads == 0:
+            if mesonlib.version_compare(self.version, '>= 10.0'):
+                return ['-flto=auto']
+            # This matches clang's behavior of using the number of cpus
+            return [f'-flto={multiprocessing.cpu_count()}']
+        elif threads > 0:
+            return [f'-flto={threads}']
+        return super().get_lto_compile_args(threads=threads)
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/intel.py meson-0.61.2/mesonbuild/compilers/mixins/intel.py
--- meson-0.53.2/mesonbuild/compilers/mixins/intel.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/intel.py	2022-01-17 10:50:45.000000000 +0000
@@ -24,12 +24,10 @@
 import typing as T
 
 from ... import mesonlib
+from ..compilers import CompileCheckMode
 from .gnu import GnuLikeCompiler
 from .visualstudio import VisualStudioLikeCompiler
 
-if T.TYPE_CHECKING:
-    import subprocess  # noqa: F401
-
 # XXX: avoid circular dependencies
 # TODO: this belongs in a posix compiler class
 # NOTE: the default Intel optimization is -O2, unlike GNU which defaults to -O0.
@@ -69,15 +67,16 @@
         's': ['-Os'],
     }
 
-    def __init__(self):
+    def __init__(self) -> None:
         super().__init__()
         # As of 19.0.0 ICC doesn't have sanitizer, color, or lto support.
         #
         # It does have IPO, which serves much the same purpose as LOT, but
         # there is an unfortunate rule for using IPO (you can't control the
         # name of the output file) which break assumptions meson makes
-        self.base_options = ['b_pch', 'b_lundef', 'b_asneeded', 'b_pgo',
-                             'b_coverage', 'b_ndebug', 'b_staticpic', 'b_pie']
+        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'
 
@@ -97,21 +96,16 @@
         else:
             return ['-openmp']
 
-    def compiles(self, *args, **kwargs) -> T.Tuple[bool, bool]:
-        # This covers a case that .get('foo', []) doesn't, that extra_args is
-        # defined and is None
-        extra_args = kwargs.get('extra_args') or []
-        kwargs['extra_args'] = [
-            extra_args,
+    def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
+        extra_args = [
             '-diag-error', '10006',  # ignoring unknown option
             '-diag-error', '10148',  # Option not supported
             '-diag-error', '10155',  # ignoring argument required
             '-diag-error', '10156',  # ignoring not argument allowed
             '-diag-error', '10157',  # Ignoring argument of the wrong type
             '-diag-error', '10158',  # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't
-            '-diag-error', '1292',   # unknown __attribute__
         ]
-        return super().compiles(*args, **kwargs)
+        return super().get_compiler_check_args(mode) + extra_args
 
     def get_profile_generate_args(self) -> T.List[str]:
         return ['-prof-gen=threadsafe']
@@ -125,6 +119,9 @@
     def get_optimization_args(self, optimization_level: str) -> T.List[str]:
         return self.OPTIM_ARGS[optimization_level]
 
+    def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
+        return ['-diag-error', '1292']
+
 
 class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
 
@@ -140,23 +137,22 @@
     }  # type: T.Dict[str, T.List[str]]
 
     OPTIM_ARGS = {
-        '0': ['/O0'],
-        'g': ['/O0'],
+        '0': ['/Od'],
+        'g': ['/Od'],
         '1': ['/O1'],
         '2': ['/O2'],
         '3': ['/O3'],
         's': ['/Os'],
     }
 
-    def __init__(self, target: str):
+    def __init__(self, target: str) -> None:
         super().__init__(target)
         self.id = 'intel-cl'
 
-    def compile(self, code, *, extra_args: T.Optional[T.List[str]] = None, **kwargs) -> T.Iterator['subprocess.Popen']:
-        # This covers a case that .get('foo', []) doesn't, that extra_args is
-        if kwargs.get('mode', 'compile') != 'link':
-            extra_args = extra_args.copy() if extra_args is not None else []
-            extra_args.extend([
+    def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
+        args = super().get_compiler_check_args(mode)
+        if mode is not CompileCheckMode.LINK:
+            args.extend([
                 '/Qdiag-error:10006',  # ignoring unknown option
                 '/Qdiag-error:10148',  # Option not supported
                 '/Qdiag-error:10155',  # ignoring argument required
@@ -164,17 +160,14 @@
                 '/Qdiag-error:10157',  # Ignoring argument of the wrong type
                 '/Qdiag-error:10158',  # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't
             ])
-        return super().compile(code, extra_args, **kwargs)
+        return args
 
     def get_toolset_version(self) -> T.Optional[str]:
-        # Avoid circular dependencies....
-        from ...environment import search_version
-
         # ICL provides a cl.exe that returns the version of MSVC it tries to
         # emulate, so we'll get the version from that and pass it to the same
         # function the real MSVC uses to calculate the toolset version.
         _, _, err = mesonlib.Popen_safe(['cl.exe'])
-        v1, v2, *_ = search_version(err).split('.')
+        v1, v2, *_ = mesonlib.search_version(err).split('.')
         version = int(v1 + v2)
         return self._calculate_toolset_version(version)
 
@@ -186,3 +179,6 @@
 
     def get_optimization_args(self, optimization_level: str) -> T.List[str]:
         return self.OPTIM_ARGS[optimization_level]
+
+    def get_pch_base_name(self, header: str) -> str:
+        return os.path.basename(header)
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/islinker.py meson-0.61.2/mesonbuild/compilers/mixins/islinker.py
--- meson-0.53.2/mesonbuild/compilers/mixins/islinker.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/islinker.py	2022-01-02 20:12:32.000000000 +0000
@@ -20,28 +20,23 @@
 classes for those cases.
 """
 
-import os
 import typing as T
 
-from ... import mesonlib
+from ...mesonlib import EnvironmentException, MesonException, is_windows
 
 if T.TYPE_CHECKING:
-    from ...coredata import OptionDictType
+    from ...coredata import KeyedOptionDictType
     from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
 
 
-class LinkerEnvVarsMixin:
-
-    """Mixin reading LDFLAGS from the environment."""
-
-    def get_linker_args_from_envvars(self) -> T.List[str]:
-        flags = os.environ.get('LDFLAGS')
-        if not flags:
-            return []
-        return mesonlib.split_args(flags)
-
-
-class BasicLinkerIsCompilerMixin:
+class BasicLinkerIsCompilerMixin(Compiler):
 
     """Provides a baseline of methods that a linker would implement.
 
@@ -53,11 +48,11 @@
     def sanitizer_link_args(self, value: str) -> T.List[str]:
         return []
 
-    def get_lto_link_args(self) -> T.List[str]:
+    def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]:
         return []
 
     def can_linker_accept_rsp(self) -> bool:
-        return mesonlib.is_windows()
+        return is_windows()
 
     def get_linker_exelist(self) -> T.List[str]:
         return self.exelist.copy()
@@ -71,7 +66,7 @@
     def get_linker_lib_prefix(self) -> str:
         return ''
 
-    def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+    def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
         return []
 
     def has_multi_link_args(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
@@ -83,50 +78,51 @@
     def get_std_shared_lib_link_args(self) -> T.List[str]:
         return []
 
-    def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
+    def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
         return self.get_std_shared_lib_link_args()
 
     def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
-        raise mesonlib.EnvironmentException(
-            'Linker {} does not support link_whole'.format(self.id))
+        raise EnvironmentException(f'Linker {self.id} does not support link_whole')
 
     def get_allow_undefined_link_args(self) -> T.List[str]:
-        raise mesonlib.EnvironmentException(
-            'Linker {} does not support allow undefined'.format(self.id))
+        raise EnvironmentException(f'Linker {self.id} does not support allow undefined')
 
     def get_pie_link_args(self) -> T.List[str]:
-        m = 'Linker {} does not support position-independent executable'
-        raise mesonlib.EnvironmentException(m.format(self.id))
+        raise EnvironmentException(f'Linker {self.id} does not support position-independent executable')
 
     def get_undefined_link_args(self) -> T.List[str]:
         return []
 
     def get_coverage_link_args(self) -> T.List[str]:
-        m = "Linker {} doesn't implement coverage data generation.".format(self.id)
-        raise mesonlib.EnvironmentException(m)
+        return []
 
     def no_undefined_link_args(self) -> T.List[str]:
         return []
 
     def bitcode_args(self) -> T.List[str]:
-        raise mesonlib.MesonException("This linker doesn't support bitcode bundles")
+        raise MesonException("This linker doesn't support bitcode bundles")
 
-    def get_soname_args(self, for_machine: 'mesonlib.MachineChoice',
-                        prefix: str, shlib_name: str, suffix: str, soversion: str,
-                        darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        raise mesonlib.MesonException("This linker doesn't support soname args")
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str,
+                        darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        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,
-                         install_rpath: str) -> T.List[str]:
+                         rpath_paths: T.Tuple[str, ...], build_rpath: str,
+                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+        return ([], set())
+
+    def get_asneeded_args(self) -> T.List[str]:
         return []
 
-    def get_linker_debug_crt_args(self) -> T.List[str]:
+    def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
         return []
 
-    def get_asneeded_args(self) -> T.List[str]:
+    def get_link_debugfile_name(self, target: str) -> str:
+        return ''
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
         return []
 
-    def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
+    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
         return []
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/pgi.py meson-0.61.2/mesonbuild/compilers/mixins/pgi.py
--- meson-0.53.2/mesonbuild/compilers/mixins/pgi.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/pgi.py	2022-01-17 10:50:45.000000000 +0000
@@ -19,6 +19,17 @@
 from pathlib import Path
 
 from ..compilers import clike_debug_args, clike_optimization_args
+from ...mesonlib import OptionKey
+
+if T.TYPE_CHECKING:
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
 
 pgi_buildtype_args = {
     'plain': [],
@@ -30,16 +41,18 @@
 }  # type: T.Dict[str, T.List[str]]
 
 
-class PGICompiler:
-    def __init__(self):
-        self.base_options = ['b_pch']
+class PGICompiler(Compiler):
+
+    def __init__(self) -> None:
+        self.base_options = {OptionKey('b_pch')}
         self.id = 'pgi'
 
         default_warn_args = ['-Minform=inform']
         self.warn_args = {'0': [],
                           '1': default_warn_args,
                           '2': default_warn_args,
-                          '3': default_warn_args}
+                          '3': default_warn_args
+        }  # type: T.Dict[str, T.List[str]]
 
     def get_module_incdir_args(self) -> T.Tuple[str]:
         return ('-module', )
@@ -74,9 +87,6 @@
                 parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
         return parameter_list
 
-    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
-        return []
-
     def get_always_args(self) -> T.List[str]:
         return []
 
@@ -90,10 +100,10 @@
         if self.language == 'cpp':
             return ['--pch',
                     '--pch_dir', str(hdr.parent),
-                    '-I{}'.format(hdr.parent)]
+                    f'-I{hdr.parent}']
         else:
             return []
 
-    def thread_flags(self, env):
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
         # PGI cannot accept -pthread, it's already threaded
         return []
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/visualstudio.py meson-0.61.2/mesonbuild/compilers/mixins/visualstudio.py
--- meson-0.53.2/mesonbuild/compilers/mixins/visualstudio.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/visualstudio.py	2022-01-17 10:50:45.000000000 +0000
@@ -20,11 +20,20 @@
 import os
 import typing as T
 
+from ... import arglist
 from ... import mesonlib
 from ... import mlog
 
 if T.TYPE_CHECKING:
     from ...environment import Environment
+    from ...dependencies import Dependency
+    from .clike import CLikeCompiler as Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
 
 vs32_instruction_set_args = {
     'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX
@@ -52,31 +61,22 @@
     'neon': None,
 }  # T.Dicst[str, T.Optional[T.List[str]]]
 
-msvc_buildtype_args = {
-    'plain': [],
-    'debug': ["/ZI", "/Ob0", "/Od", "/RTC1"],
-    'debugoptimized': ["/Zi", "/Ob1"],
-    'release': ["/Ob2", "/Gw"],
-    'minsize': ["/Zi", "/Gw"],
-    'custom': [],
-}  # type: T.Dict[str, T.List[str]]
-
 msvc_optimization_args = {
-    '0': [],
-    'g': ['/O0'],
+    '0': ['/Od'],
+    'g': [], # No specific flag to optimize debugging, /Zi or /ZI will create debug information
     '1': ['/O1'],
     '2': ['/O2'],
-    '3': ['/O2'],
-    's': ['/O1'], # Implies /Os.
+    '3': ['/O2', '/Gw'],
+    's': ['/O1', '/Gw'],
 }  # type: T.Dict[str, T.List[str]]
 
 msvc_debug_args = {
     False: [],
-    True: []  # Fixme!
+    True: ['/Zi']
 }  # type: T.Dict[bool, T.List[str]]
 
 
-class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
+class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta):
 
     """A common interface for all compilers implementing an MSVC-style
     interface.
@@ -88,10 +88,8 @@
 
     std_warn_args = ['/W3']
     std_opt_args = ['/O2']
-    # XXX: this is copied in this patch only to avoid circular dependencies
-    #ignore_libs = unixy_compiler_internal_libs
-    ignore_libs = ('m', 'c', 'pthread', 'dl', 'rt', 'execinfo')
-    internal_libs = ()
+    ignore_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS + ['execinfo']
+    internal_libs = []  # type: T.List[str]
 
     crt_args = {
         'none': [],
@@ -103,9 +101,11 @@
 
     # /showIncludes is needed for build dependency tracking in Ninja
     # See: https://ninja-build.org/manual.html#_deps
-    always_args = ['/nologo', '/showIncludes']
+    # Assume UTF-8 sources by default, but self.unix_args_to_native() removes it
+    # if `/source-charset` is set too.
+    always_args = ['/nologo', '/showIncludes', '/utf-8']
     warn_args = {
-        '0': ['/W1'],
+        '0': [],
         '1': ['/W2'],
         '2': ['/W3'],
         '3': ['/W4'],
@@ -114,7 +114,7 @@
     INVOKES_LINKER = False
 
     def __init__(self, target: str):
-        self.base_options = ['b_pch', 'b_ndebug', 'b_vscrt'] # FIXME add lto, pgo and the like
+        self.base_options = {mesonlib.OptionKey(o) for o in ['b_pch', 'b_ndebug', 'b_vscrt']} # FIXME add lto, pgo and the like
         self.target = target
         self.is_64 = ('x64' in target) or ('x86_64' in target)
         # do some canonicalization of target machine
@@ -122,20 +122,21 @@
             self.machine = 'x64'
         elif '86' in target:
             self.machine = 'x86'
+        elif 'aarch64' in target:
+            self.machine = 'arm64'
+        elif 'arm' in target:
+            self.machine = 'arm'
         else:
             self.machine = target
+        if mesonlib.version_compare(self.version, '>=19.28.29910'): # VS 16.9.0 includes cl 19.28.29910
+            self.base_options.add(mesonlib.OptionKey('b_sanitize'))
+        assert self.linker is not None
         self.linker.machine = self.machine
 
     # Override CCompiler.get_always_args
     def get_always_args(self) -> T.List[str]:
         return self.always_args
 
-    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
-        args = msvc_buildtype_args[buildtype]
-        if self.id == 'msvc' and mesonlib.version_compare(self.version, '<18.0'):
-            args = [arg for arg in args if arg != '/Gw']
-        return args
-
     def get_pch_suffix(self) -> str:
         return 'pch'
 
@@ -145,10 +146,12 @@
         pchname = '.'.join(chopped)
         return pchname
 
+    def get_pch_base_name(self, header: str) -> str:
+        # This needs to be implemented by inheriting classes
+        raise NotImplementedError
+
     def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
-        base = os.path.basename(header)
-        if self.id == 'clang-cl':
-            base = header
+        base = self.get_pch_base_name(header)
         pchname = self.get_pch_name(header)
         return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)]
 
@@ -159,33 +162,35 @@
         return ['/c']
 
     def get_no_optimization_args(self) -> T.List[str]:
-        return ['/Od']
+        return ['/Od', '/Oi-']
+
+    def sanitizer_compile_args(self, value: str) -> T.List[str]:
+        if value == 'none':
+            return []
+        if value != 'address':
+            raise mesonlib.MesonException('VS only supports address sanitizer at the moment.')
+        return ['/fsanitize=address']
 
     def get_output_args(self, target: str) -> T.List[str]:
         if target.endswith('.exe'):
             return ['/Fe' + target]
         return ['/Fo' + target]
 
-    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
-        return msvc_optimization_args[optimization_level]
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return []
 
     def get_debug_args(self, is_debug: bool) -> T.List[str]:
         return msvc_debug_args[is_debug]
 
-    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
-        return []
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        args = msvc_optimization_args[optimization_level]
+        if mesonlib.version_compare(self.version, '<18.0'):
+            args = [arg for arg in args if arg != '/Gw']
+        return args
 
     def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]:
         return ['/link'] + args
 
-    def get_gui_app_args(self, value: bool) -> T.List[str]:
-        # the default is for the linker to guess the subsystem based on presence
-        # of main or WinMain symbols, so always be explicit
-        if value:
-            return ['/SUBSYSTEM:WINDOWS']
-        else:
-            return ['/SUBSYSTEM:CONSOLE']
-
     def get_pic_args(self) -> T.List[str]:
         return [] # PIC is handled by the loader on Windows
 
@@ -200,20 +205,19 @@
         objname = os.path.splitext(pchname)[0] + '.obj'
         return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname]
 
-    def gen_import_library_args(self, implibname: str) -> T.List[str]:
-        "The name of the outputted import library"
-        return ['/IMPLIB:' + implibname]
-
     def openmp_flags(self) -> T.List[str]:
         return ['/openmp']
 
+    def openmp_link_flags(self) -> T.List[str]:
+        return []
+
     # FIXME, no idea what these should be.
     def thread_flags(self, env: 'Environment') -> T.List[str]:
         return []
 
     @classmethod
     def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
-        result = []
+        result: T.List[str] = []
         for i in args:
             # -mms-bitfields is specific to MinGW-GCC
             # -pthread is only valid for GCC
@@ -247,6 +251,13 @@
             # -pthread in link flags is only used on Linux
             elif i == '-pthread':
                 continue
+            # cl.exe does not allow specifying both, so remove /utf-8 that we
+            # added automatically in the case the user overrides it manually.
+            elif i.startswith('/source-charset:') or i.startswith('/execution-charset:'):
+                try:
+                    result.remove('/utf-8')
+                except ValueError:
+                    pass
             result.append(i)
         return result
 
@@ -283,37 +294,22 @@
     # Visual Studio is special. It ignores some arguments it does not
     # understand and you can't tell it to error out on those.
     # http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t
-    def has_arguments(self, args: T.List[str], env: 'Environment', code, mode: str) -> T.Tuple[bool, bool]:
+    def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: str) -> T.Tuple[bool, bool]:
         warning_text = '4044' if mode == 'link' else '9002'
-        if self.id == 'clang-cl' and mode != 'link':
-            args = args + ['-Werror=unknown-argument']
         with self._build_wrapper(code, env, extra_args=args, mode=mode) as p:
             if p.returncode != 0:
                 return False, p.cached
-            return not(warning_text in p.stde or warning_text in p.stdo), p.cached
+            return not(warning_text in p.stderr or warning_text in p.stdout), p.cached
 
     def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]:
         pdbarr = rel_obj.split('.')[:-1]
         pdbarr += ['pdb']
         args = ['/Fd' + '.'.join(pdbarr)]
-        # When generating a PDB file with PCH, all compile commands write
-        # to the same PDB file. Hence, we need to serialize the PDB
-        # writes using /FS since we do parallel builds. This slows down the
-        # build obviously, which is why we only do this when PCH is on.
-        # This was added in Visual Studio 2013 (MSVC 18.0). Before that it was
-        # always on: https://msdn.microsoft.com/en-us/library/dn502518.aspx
-        if pch and self.id == 'msvc' and mesonlib.version_compare(self.version, '>=18.0'):
-            args = ['/FS'] + args
         return args
 
     def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]:
         if self.is_64:
             return vs64_instruction_set_args.get(instruction_set, None)
-        if self.id == 'msvc' and self.version.split('.')[0] == '16' and instruction_set == 'avx':
-            # VS documentation says that this exists and should work, but
-            # it does not. The headers do not contain AVX intrinsics
-            # and the can not be called.
-            return None
         return vs32_instruction_set_args.get(instruction_set, None)
 
     def _calculate_toolset_version(self, version: int) -> T.Optional[str]:
@@ -337,14 +333,12 @@
             return '14.1' # (Visual Studio 2017)
         elif version < 1930:
             return '14.2' # (Visual Studio 2019)
-        mlog.warning('Could not find toolset for version {!r}'.format(self.version))
+        elif version < 1940:
+            return '14.3' # (Visual Studio 2022)
+        mlog.warning(f'Could not find toolset for version {self.version!r}')
         return None
 
     def get_toolset_version(self) -> T.Optional[str]:
-        if self.id == 'clang-cl':
-            # I have no idea
-            return '14.1'
-
         # See boost/config/compiler/visualc.cpp for up to date mapping
         try:
             version = int(''.join(self.version.split('.')[0:2]))
@@ -360,20 +354,25 @@
     def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
         if crt_val in self.crt_args:
             return self.crt_args[crt_val]
-        assert(crt_val == 'from_buildtype')
+        assert crt_val in ['from_buildtype', 'static_from_buildtype']
+        dbg = 'mdd'
+        rel = 'md'
+        if crt_val == 'static_from_buildtype':
+            dbg = 'mtd'
+            rel = 'mt'
         # Match what build type flags used to do.
         if buildtype == 'plain':
             return []
         elif buildtype == 'debug':
-            return self.crt_args['mdd']
+            return self.crt_args[dbg]
         elif buildtype == 'debugoptimized':
-            return self.crt_args['md']
+            return self.crt_args[rel]
         elif buildtype == 'release':
-            return self.crt_args['md']
+            return self.crt_args[rel]
         elif buildtype == 'minsize':
-            return self.crt_args['md']
+            return self.crt_args[rel]
         else:
-            assert(buildtype == 'custom')
+            assert buildtype == 'custom'
             raise mesonlib.EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".')
 
     def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
@@ -384,6 +383,75 @@
     def get_argument_syntax(self) -> str:
         return 'msvc'
 
-    @classmethod
-    def use_linker_args(cls, linker: str) -> T.List[str]:
-        return []
+
+class MSVCCompiler(VisualStudioLikeCompiler):
+
+    """Specific to the Microsoft Compilers."""
+
+    def __init__(self, target: str):
+        super().__init__(target)
+        self.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)
+        # When generating a PDB file with PCH, all compile commands write
+        # to the same PDB file. Hence, we need to serialize the PDB
+        # writes using /FS since we do parallel builds. This slows down the
+        # build obviously, which is why we only do this when PCH is on.
+        # This was added in Visual Studio 2013 (MSVC 18.0). Before that it was
+        # always on: https://msdn.microsoft.com/en-us/library/dn502518.aspx
+        if pch and mesonlib.version_compare(self.version, '>=18.0'):
+            args = ['/FS'] + args
+        return args
+
+    def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]:
+        if self.version.split('.')[0] == '16' and instruction_set == 'avx':
+            # VS documentation says that this exists and should work, but
+            # it does not. The headers do not contain AVX intrinsics
+            # and they can not be called.
+            return None
+        return super().get_instruction_set_args(instruction_set)
+
+    def get_pch_base_name(self, header: str) -> str:
+        return os.path.basename(header)
+
+
+class ClangClCompiler(VisualStudioLikeCompiler):
+
+    """Specific to Clang-CL."""
+
+    def __init__(self, target: str):
+        super().__init__(target)
+        self.id = 'clang-cl'
+
+        # Assembly
+        self.can_compile_suffixes.add('s')
+
+    def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: str) -> T.Tuple[bool, bool]:
+        if mode != 'link':
+            args = args + ['-Werror=unknown-argument']
+        return super().has_arguments(args, env, code, mode)
+
+    def get_toolset_version(self) -> T.Optional[str]:
+        # XXX: what is the right thing to do here?
+        return '14.1'
+
+    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':
+            converted = []
+            for i in dep.get_compile_args():
+                if i.startswith('-isystem'):
+                    converted += ['/clang:' + i]
+                else:
+                    converted += [i]
+            return converted
+        else:
+            return dep.get_compile_args()
\ No newline at end of file
diff -Nru meson-0.53.2/mesonbuild/compilers/mixins/xc16.py meson-0.61.2/mesonbuild/compilers/mixins/xc16.py
--- meson-0.53.2/mesonbuild/compilers/mixins/xc16.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/mixins/xc16.py	2022-01-17 10:50:45.000000000 +0000
@@ -0,0 +1,127 @@
+# Copyright 2012-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Representations specific to the Microchip XC16 C compiler family."""
+
+import os
+import typing as T
+
+from ...mesonlib import EnvironmentException
+
+if T.TYPE_CHECKING:
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+xc16_buildtype_args = {
+    'plain': [],
+    'debug': [],
+    'debugoptimized': [],
+    'release': [],
+    'minsize': [],
+    'custom': [],
+}  # type: T.Dict[str, T.List[str]]
+
+xc16_optimization_args = {
+    '0': ['-O0'],
+    'g': ['-O0'],
+    '1': ['-O1'],
+    '2': ['-O2'],
+    '3': ['-O3'],
+    's': ['-Os']
+}  # type: T.Dict[str, T.List[str]]
+
+xc16_debug_args = {
+    False: [],
+    True: []
+}  # type: T.Dict[bool, T.List[str]]
+
+
+class Xc16Compiler(Compiler):
+
+    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]
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + [],
+                          '3': default_warn_args + []}  # type: T.Dict[str, T.List[str]]
+
+    def get_always_args(self) -> T.List[str]:
+        return []
+
+    def get_pic_args(self) -> T.List[str]:
+        # PIC support is not enabled by default for xc16,
+        # if users want to use it, they need to add the required arguments explicitly
+        return []
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return xc16_buildtype_args[buildtype]
+
+    def get_pch_suffix(self) -> str:
+        return 'pch'
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        return []
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def get_coverage_args(self) -> T.List[str]:
+        return []
+
+    def get_no_stdinc_args(self) -> T.List[str]:
+        return ['-nostdinc']
+
+    def get_no_stdlib_link_args(self) -> T.List[str]:
+        return ['--nostdlib']
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return xc16_optimization_args[optimization_level]
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return xc16_debug_args[is_debug]
+
+    @classmethod
+    def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
+        result = []
+        for i in args:
+            if i.startswith('-D'):
+                i = '-D' + i[2:]
+            if i.startswith('-I'):
+                i = '-I' + i[2:]
+            if i.startswith('-Wl,-rpath='):
+                continue
+            elif i == '--print-search-dirs':
+                continue
+            elif i.startswith('-L'):
+                continue
+            result.append(i)
+        return result
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:9] == '-I':
+                parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
+
+        return parameter_list
diff -Nru meson-0.53.2/mesonbuild/compilers/objcpp.py meson-0.61.2/mesonbuild/compilers/objcpp.py
--- meson-0.53.2/mesonbuild/compilers/objcpp.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/objcpp.py	2021-11-02 19:58:13.000000000 +0000
@@ -12,10 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os.path, subprocess
 import typing as T
 
-from ..mesonlib import EnvironmentException, MachineChoice
+from .. import coredata
+from ..mesonlib import MachineChoice, OptionKey
 
 from .mixins.clike import CLikeCompiler
 from .compilers import Compiler
@@ -23,53 +23,43 @@
 from .mixins.clang import ClangCompiler
 
 if T.TYPE_CHECKING:
+    from ..programs import ExternalProgram
     from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..linkers import DynamicLinker
 
 class ObjCPPCompiler(CLikeCompiler, Compiler):
 
     language = 'objcpp'
 
-    def __init__(self, exelist, version, for_machine: MachineChoice,
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
                  is_cross: bool, info: 'MachineInfo',
-                 exe_wrap: T.Optional[str], **kwargs):
-        Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
-        CLikeCompiler.__init__(self, is_cross, exe_wrap)
+                 exe_wrap: T.Optional['ExternalProgram'],
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        Compiler.__init__(self, exelist, version, for_machine, info,
+                          is_cross=is_cross, full_version=full_version,
+                          linker=linker)
+        CLikeCompiler.__init__(self, exe_wrap)
 
     @staticmethod
-    def get_display_language():
+    def get_display_language() -> str:
         return 'Objective-C++'
 
-    def sanity_check(self, work_dir, environment):
-        # TODO try to use sanity_check_impl instead of duplicated code
-        source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm')
-        binary_name = os.path.join(work_dir, 'sanitycheckobjcpp')
-        extra_flags = environment.coredata.get_external_args(self.for_machine, self.language)
-        if self.is_cross:
-            extra_flags += self.get_compile_only_args()
-        else:
-            extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language)
-        with open(source_name, 'w') as ofile:
-            ofile.write('#import\n'
-                        'class MyClass;'
-                        'int main(void) { return 0; }\n')
-        pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
-        pc.wait()
-        if pc.returncode != 0:
-            raise EnvironmentException('ObjC++ compiler %s can not compile programs.' % self.name_string())
-        if self.is_cross:
-            # Can't check if the binaries run so we have to assume they do
-            return
-        pe = subprocess.Popen(binary_name)
-        pe.wait()
-        if pe.returncode != 0:
-            raise EnvironmentException('Executables created by ObjC++ compiler %s are not runnable.' % self.name_string())
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
+        code = '#import\nclass MyClass;int main(void) { return 0; }\n'
+        return self._sanity_check_impl(work_dir, environment, 'sanitycheckobjcpp.mm', code)
 
 
 class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
-    def __init__(self, exelist, version, for_machine: MachineChoice,
-                 is_cross, info: 'MachineInfo', exe_wrapper=None,
-                 defines=None, **kwargs):
-        ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 defines: T.Optional[T.Dict[str, str]] = None,
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
+                                info, exe_wrapper, linker=linker, full_version=full_version)
         GnuCompiler.__init__(self, defines)
         default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
         self.warn_args = {'0': [],
@@ -79,13 +69,41 @@
 
 
 class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
-    def __init__(self, exelist, version, for_machine: MachineChoice,
-                 is_cross, info: 'MachineInfo', exe_wrapper=None,
-                 **kwargs):
-        ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
-        ClangCompiler.__init__(self)
+
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 defines: T.Optional[T.Dict[str, str]] = None,
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
+                                info, exe_wrapper, linker=linker, full_version=full_version)
+        ClangCompiler.__init__(self, defines)
         default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
         self.warn_args = {'0': [],
                           '1': default_warn_args,
                           '2': default_warn_args + ['-Wextra'],
                           '3': default_warn_args + ['-Wextra', '-Wpedantic']}
+
+    def get_options(self) -> 'coredata.KeyedOptionDictType':
+        opts = super().get_options()
+        opts.update({
+            OptionKey('std', machine=self.for_machine, lang='cpp'): coredata.UserComboOption(
+                'C++ language standard to use',
+                ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17'],
+                'none',
+            )
+        })
+        return opts
+
+    def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
+        args = []
+        std = options[OptionKey('std', machine=self.for_machine, lang='cpp')]
+        if std.value != 'none':
+            args.append('-std=' + std.value)
+        return args
+
+
+class AppleClangObjCPPCompiler(ClangObjCPPCompiler):
+
+    """Handle the differences between Apple's clang and vanilla clang."""
diff -Nru meson-0.53.2/mesonbuild/compilers/objc.py meson-0.61.2/mesonbuild/compilers/objc.py
--- meson-0.53.2/mesonbuild/compilers/objc.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/objc.py	2021-10-11 16:26:46.000000000 +0000
@@ -12,10 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os.path, subprocess
 import typing as T
 
-from ..mesonlib import EnvironmentException, MachineChoice
+from .. import coredata
+from ..mesonlib import MachineChoice, OptionKey
 
 from .compilers import Compiler
 from .mixins.clike import CLikeCompiler
@@ -23,54 +23,44 @@
 from .mixins.clang import ClangCompiler
 
 if T.TYPE_CHECKING:
+    from ..programs import ExternalProgram
     from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..linkers import DynamicLinker
 
 
 class ObjCCompiler(CLikeCompiler, Compiler):
 
     language = 'objc'
 
-    def __init__(self, exelist, version, for_machine: MachineChoice,
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
                  is_cross: bool, info: 'MachineInfo',
-                 exe_wrap: T.Optional[str], **kwargs):
-        Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
-        CLikeCompiler.__init__(self, is_cross, exe_wrap)
+                 exe_wrap: T.Optional['ExternalProgram'],
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        Compiler.__init__(self, exelist, version, for_machine, info,
+                          is_cross=is_cross, full_version=full_version,
+                          linker=linker)
+        CLikeCompiler.__init__(self, exe_wrap)
 
     @staticmethod
-    def get_display_language():
+    def get_display_language() -> str:
         return 'Objective-C'
 
-    def sanity_check(self, work_dir, environment):
-        # TODO try to use sanity_check_impl instead of duplicated code
-        source_name = os.path.join(work_dir, 'sanitycheckobjc.m')
-        binary_name = os.path.join(work_dir, 'sanitycheckobjc')
-        extra_flags = environment.coredata.get_external_args(self.for_machine, self.language)
-        if self.is_cross:
-            extra_flags += self.get_compile_only_args()
-        else:
-            extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language)
-        with open(source_name, 'w') as ofile:
-            ofile.write('#import\n'
-                        'int main(void) { return 0; }\n')
-        pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
-        pc.wait()
-        if pc.returncode != 0:
-            raise EnvironmentException('ObjC compiler %s can not compile programs.' % self.name_string())
-        if self.is_cross:
-            # Can't check if the binaries run so we have to assume they do
-            return
-        pe = subprocess.Popen(binary_name)
-        pe.wait()
-        if pe.returncode != 0:
-            raise EnvironmentException('Executables created by ObjC compiler %s are not runnable.' % self.name_string())
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
+        code = '#import\nint main(void) { return 0; }\n'
+        return self._sanity_check_impl(work_dir, environment, 'sanitycheckobjc.m', code)
 
 
 class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
-    def __init__(self, exelist, version, for_machine: MachineChoice,
-                 is_cross, info: 'MachineInfo', exe_wrapper=None,
-                 defines=None, **kwargs):
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 defines: T.Optional[T.Dict[str, str]] = None,
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
         ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross,
-                              info, exe_wrapper, **kwargs)
+                              info, exe_wrapper, linker=linker, full_version=full_version)
         GnuCompiler.__init__(self, defines)
         default_warn_args = ['-Wall', '-Winvalid-pch']
         self.warn_args = {'0': [],
@@ -80,14 +70,39 @@
 
 
 class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
-    def __init__(self, exelist, version, for_machine: MachineChoice,
-                 is_cross, info: 'MachineInfo', exe_wrapper=None,
-                 **kwargs):
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 defines: T.Optional[T.Dict[str, str]] = None,
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
         ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross,
-                              info, exe_wrapper, **kwargs)
-        ClangCompiler.__init__(self)
+                              info, exe_wrapper, linker=linker, full_version=full_version)
+        ClangCompiler.__init__(self, defines)
         default_warn_args = ['-Wall', '-Winvalid-pch']
         self.warn_args = {'0': [],
                           '1': default_warn_args,
                           '2': default_warn_args + ['-Wextra'],
                           '3': default_warn_args + ['-Wextra', '-Wpedantic']}
+
+    def get_options(self) -> 'coredata.KeyedOptionDictType':
+        opts = super().get_options()
+        opts.update({
+            OptionKey('std', machine=self.for_machine, lang='c'): coredata.UserComboOption(
+                'C language standard to use',
+                ['none', 'c89', 'c99', 'c11', 'c17', 'gnu89', 'gnu99', 'gnu11', 'gnu17'],
+                'none',
+            )
+        })
+        return opts
+
+    def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
+        args = []
+        std = options[OptionKey('std', machine=self.for_machine, lang='c')]
+        if std.value != 'none':
+            args.append('-std=' + std.value)
+        return args
+
+class AppleClangObjCCompiler(ClangObjCCompiler):
+
+    """Handle the differences between Apple's clang and vanilla clang."""
diff -Nru meson-0.53.2/mesonbuild/compilers/rust.py meson-0.61.2/mesonbuild/compilers/rust.py
--- meson-0.53.2/mesonbuild/compilers/rust.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/rust.py	2022-01-17 10:50:45.000000000 +0000
@@ -13,57 +13,81 @@
 # limitations under the License.
 
 import subprocess, os.path
+import textwrap
 import typing as T
 
-from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe
+from .. import coredata
+from ..mesonlib import (
+    EnvironmentException, MachineChoice, MesonException, Popen_safe,
+    OptionKey,
+)
 from .compilers import Compiler, rust_buildtype_args, clike_debug_args
 
 if T.TYPE_CHECKING:
+    from ..coredata import KeyedOptionDictType
     from ..envconfig import MachineInfo
     from ..environment import Environment  # noqa: F401
+    from ..linkers import DynamicLinker
+    from ..programs import ExternalProgram
 
-rust_optimization_args = {'0': [],
-                          'g': ['-C', 'opt-level=0'],
-                          '1': ['-C', 'opt-level=1'],
-                          '2': ['-C', 'opt-level=2'],
-                          '3': ['-C', 'opt-level=3'],
-                          's': ['-C', 'opt-level=s'],
-                          }
+
+rust_optimization_args = {
+    '0': [],
+    'g': ['-C', 'opt-level=0'],
+    '1': ['-C', 'opt-level=1'],
+    '2': ['-C', 'opt-level=2'],
+    '3': ['-C', 'opt-level=3'],
+    's': ['-C', 'opt-level=s'],
+}  # type: T.Dict[str, T.List[str]]
 
 class RustCompiler(Compiler):
 
     # rustc doesn't invoke the compiler itself, it doesn't need a LINKER_PREFIX
     language = 'rust'
 
-    def __init__(self, exelist, version, for_machine: MachineChoice,
-                 is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
-        super().__init__(exelist, version, for_machine, info, **kwargs)
+    _WARNING_LEVELS: T.Dict[str, T.List[str]] = {
+        '0': ['-A', 'warnings'],
+        '1': [],
+        '2': [],
+        '3': ['-W', 'warnings'],
+    }
+
+    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, info,
+                         is_cross=is_cross, full_version=full_version,
+                         linker=linker)
         self.exe_wrapper = exe_wrapper
         self.id = 'rustc'
-        self.is_cross = is_cross
+        self.base_options.add(OptionKey('b_colorout'))
+        if 'link' in self.linker.id:
+            self.base_options.add(OptionKey('b_vscrt'))
 
-    def needs_static_linker(self):
+    def needs_static_linker(self) -> bool:
         return False
 
-    def name_string(self):
-        return ' '.join(self.exelist)
-
-    def sanity_check(self, work_dir, environment):
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
         source_name = os.path.join(work_dir, 'sanity.rs')
         output_name = os.path.join(work_dir, 'rusttest')
-        with open(source_name, 'w') as ofile:
-            ofile.write('''fn main() {
-}
-''')
+        with open(source_name, 'w', encoding='utf-8') as ofile:
+            ofile.write(textwrap.dedent(
+                '''fn main() {
+                }
+                '''))
         pc = subprocess.Popen(self.exelist + ['-o', output_name, source_name],
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               cwd=work_dir)
-        stdo, stde = pc.communicate()
-        stdo = stdo.decode('utf-8', errors='replace')
-        stde = stde.decode('utf-8', errors='replace')
+        _stdo, _stde = pc.communicate()
+        assert isinstance(_stdo, bytes)
+        assert isinstance(_stde, bytes)
+        stdo = _stdo.decode('utf-8', errors='replace')
+        stde = _stde.decode('utf-8', errors='replace')
         if pc.returncode != 0:
-            raise EnvironmentException('Rust compiler %s can not compile programs.\n%s\n%s' % (
+            raise EnvironmentException('Rust compiler {} can not compile programs.\n{}\n{}'.format(
                 self.name_string(),
                 stdo,
                 stde))
@@ -71,7 +95,7 @@
             if self.exe_wrapper is None:
                 # Can't check if the binaries run so we have to assume they do
                 return
-            cmdlist = self.exe_wrapper + [output_name]
+            cmdlist = self.exe_wrapper.get_command() + [output_name]
         else:
             cmdlist = [output_name]
         pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
@@ -79,37 +103,113 @@
         if pe.returncode != 0:
             raise EnvironmentException('Executables created by Rust compiler %s are not runnable.' % self.name_string())
 
-    def get_dependency_gen_args(self, outfile):
+    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
         return ['--dep-info', outfile]
 
-    def get_buildtype_args(self, buildtype):
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
         return rust_buildtype_args[buildtype]
 
-    def get_sysroot(self):
+    def get_sysroot(self) -> str:
         cmd = self.exelist + ['--print', 'sysroot']
         p, stdo, stde = Popen_safe(cmd)
         return stdo.split('\n')[0]
 
-    def get_debug_args(self, is_debug):
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
         return clike_debug_args[is_debug]
 
-    def get_optimization_args(self, optimization_level):
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
         return rust_optimization_args[optimization_level]
 
-    def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
+                                               build_dir: str) -> T.List[str]:
         for idx, i in enumerate(parameter_list):
             if i[:2] == '-L':
                 for j in ['dependency', 'crate', 'native', 'framework', 'all']:
                     combined_len = len(j) + 3
-                    if i[:combined_len] == '-L{}='.format(j):
+                    if i[:combined_len] == f'-L{j}=':
                         parameter_list[idx] = i[:combined_len] + os.path.normpath(os.path.join(build_dir, i[combined_len:]))
                         break
 
         return parameter_list
 
-    def get_std_exe_link_args(self):
-        return []
+    def get_output_args(self, outputname: str) -> T.List[str]:
+        return ['-o', outputname]
+
+    @classmethod
+    def use_linker_args(cls, linker: str) -> T.List[str]:
+        return ['-C', f'linker={linker}']
 
     # Rust does not have a use_linker_args because it dispatches to a gcc-like
     # C compiler for dynamic linking, as such we invoke the C compiler's
     # use_linker_args method instead.
+
+    def get_options(self) -> 'KeyedOptionDictType':
+        key = OptionKey('std', machine=self.for_machine, lang=self.language)
+        return {
+            key: coredata.UserComboOption(
+                'Rust edition to use',
+                ['none', '2015', '2018', '2021'],
+                'none',
+            ),
+        }
+
+    def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        args = []
+        key = OptionKey('std', machine=self.for_machine, lang=self.language)
+        std = options[key]
+        if std.value != 'none':
+            args.append('--edition=' + std.value)
+        return args
+
+    def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+        # Rust handles this for us, we don't need to do anything
+        return []
+
+    def get_colorout_args(self, colortype: str) -> T.List[str]:
+        if colortype in {'always', 'never', 'auto'}:
+            return [f'--color={colortype}']
+        raise MesonException(f'Invalid color type for rust {colortype}')
+
+    def get_linker_always_args(self) -> T.List[str]:
+        args: T.List[str] = []
+        for a in super().get_linker_always_args():
+            args.extend(['-C', f'link-arg={a}'])
+        return args
+
+    def get_werror_args(self) -> T.List[str]:
+        # Use -D warnings, which makes every warning not explicitly allowed an
+        # error
+        return ['-D', 'warnings']
+
+    def get_warn_args(self, level: str) -> T.List[str]:
+        # TODO: I'm not really sure what to put here, Rustc doesn't have warning
+        return self._WARNING_LEVELS[level]
+
+    def get_no_warn_args(self) -> T.List[str]:
+        return self._WARNING_LEVELS["0"]
+
+    def get_pic_args(self) -> T.List[str]:
+        # This defaults to
+        return ['-C', 'relocation-model=pic']
+
+    def get_pie_args(self) -> T.List[str]:
+        # Rustc currently has no way to toggle this, it's controlled by whether
+        # pic is on by rustc
+        return []
+
+
+class ClippyRustCompiler(RustCompiler):
+
+    """Clippy is a linter that wraps Rustc.
+
+    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'
diff -Nru meson-0.53.2/mesonbuild/compilers/swift.py meson-0.61.2/mesonbuild/compilers/swift.py
--- meson-0.53.2/mesonbuild/compilers/swift.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/swift.py	2022-01-17 10:50:45.000000000 +0000
@@ -21,89 +21,93 @@
 
 if T.TYPE_CHECKING:
     from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..linkers import DynamicLinker
 
-swift_optimization_args = {'0': [],
-                           'g': [],
-                           '1': ['-O'],
-                           '2': ['-O'],
-                           '3': ['-O'],
-                           's': ['-O'],
-                           }
+swift_optimization_args = {
+    '0': [],
+    'g': [],
+    '1': ['-O'],
+    '2': ['-O'],
+    '3': ['-O'],
+    's': ['-O'],
+}  # type: T.Dict[str, T.List[str]]
 
 class SwiftCompiler(Compiler):
 
     LINKER_PREFIX = ['-Xlinker']
     language = 'swift'
 
-    def __init__(self, exelist, version, for_machine: MachineChoice,
-                 is_cross, info: 'MachineInfo', **kwargs):
-        super().__init__(exelist, version, for_machine, info, **kwargs)
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo', full_version: T.Optional[str] = None,
+                 linker: T.Optional['DynamicLinker'] = None):
+        super().__init__(exelist, version, for_machine, info,
+                         is_cross=is_cross, full_version=full_version,
+                         linker=linker)
         self.version = version
         self.id = 'llvm'
-        self.is_cross = is_cross
 
-    def name_string(self):
-        return ' '.join(self.exelist)
-
-    def needs_static_linker(self):
+    def needs_static_linker(self) -> bool:
         return True
 
-    def get_werror_args(self):
+    def get_werror_args(self) -> T.List[str]:
         return ['--fatal-warnings']
 
-    def get_dependency_gen_args(self, outtarget, outfile):
+    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
         return ['-emit-dependencies']
 
-    def depfile_for_object(self, objfile):
+    def depfile_for_object(self, objfile: str) -> str:
         return os.path.splitext(objfile)[0] + '.' + self.get_depfile_suffix()
 
-    def get_depfile_suffix(self):
+    def get_depfile_suffix(self) -> str:
         return 'd'
 
-    def get_output_args(self, target):
+    def get_output_args(self, target: str) -> T.List[str]:
         return ['-o', target]
 
-    def get_header_import_args(self, headername):
+    def get_header_import_args(self, headername: str) -> T.List[str]:
         return ['-import-objc-header', headername]
 
-    def get_warn_args(self, level):
+    def get_warn_args(self, level: str) -> T.List[str]:
         return []
 
-    def get_buildtype_args(self, buildtype):
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
         return swift_buildtype_args[buildtype]
 
-    def get_std_exe_link_args(self):
+    def get_std_exe_link_args(self) -> T.List[str]:
         return ['-emit-executable']
 
-    def get_module_args(self, modname):
+    def get_module_args(self, modname: str) -> T.List[str]:
         return ['-module-name', modname]
 
-    def get_mod_gen_args(self):
+    def get_mod_gen_args(self) -> T.List[str]:
         return ['-emit-module']
 
-    def get_include_args(self, dirname):
-        return ['-I' + dirname]
+    def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
+        return ['-I' + path]
 
-    def get_compile_only_args(self):
+    def get_compile_only_args(self) -> T.List[str]:
         return ['-c']
 
-    def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
+                                               build_dir: str) -> T.List[str]:
         for idx, i in enumerate(parameter_list):
             if i[:2] == '-I' or i[:2] == '-L':
                 parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
 
         return parameter_list
 
-    def sanity_check(self, work_dir, environment):
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
         src = 'swifttest.swift'
         source_name = os.path.join(work_dir, src)
         output_name = os.path.join(work_dir, 'swifttest')
-        extra_flags = environment.coredata.get_external_args(self.for_machine, self.language)
+        extra_flags: T.List[str] = []
+        extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
         if self.is_cross:
             extra_flags += self.get_compile_only_args()
         else:
             extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language)
-        with open(source_name, 'w') as ofile:
+        with open(source_name, 'w', encoding='utf-8') as ofile:
             ofile.write('''print("Swift compilation is working.")
 ''')
         pc = subprocess.Popen(self.exelist + extra_flags + ['-emit-executable', '-o', output_name, src], cwd=work_dir)
@@ -116,8 +120,8 @@
         if subprocess.call(output_name) != 0:
             raise EnvironmentException('Executables created by Swift compiler %s are not runnable.' % self.name_string())
 
-    def get_debug_args(self, is_debug):
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
         return clike_debug_args[is_debug]
 
-    def get_optimization_args(self, optimization_level):
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
         return swift_optimization_args[optimization_level]
diff -Nru meson-0.53.2/mesonbuild/compilers/vala.py meson-0.61.2/mesonbuild/compilers/vala.py
--- meson-0.53.2/mesonbuild/compilers/vala.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/compilers/vala.py	2022-01-17 10:50:45.000000000 +0000
@@ -16,70 +16,68 @@
 import typing as T
 
 from .. import mlog
-from ..mesonlib import EnvironmentException, MachineChoice, version_compare
+from ..mesonlib import EnvironmentException, MachineChoice, version_compare, OptionKey
 
-from .compilers import Compiler
+from .compilers import Compiler, LibType
 
 if T.TYPE_CHECKING:
     from ..envconfig import MachineInfo
+    from ..environment import Environment
 
 class ValaCompiler(Compiler):
 
     language = 'vala'
 
-    def __init__(self, exelist, version, for_machine: MachineChoice,
-                 is_cross, info: 'MachineInfo'):
-        super().__init__(exelist, version, for_machine, info)
+    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.is_cross = is_cross
         self.id = 'valac'
-        self.base_options = ['b_colorout']
+        self.base_options = {OptionKey('b_colorout')}
 
-    def name_string(self):
-        return ' '.join(self.exelist)
-
-    def needs_static_linker(self):
+    def needs_static_linker(self) -> bool:
         return False # Because compiles into C.
 
-    def get_optimization_args(self, optimization_level):
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
         return []
 
-    def get_debug_args(self, is_debug):
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
         return ['--debug'] if is_debug else []
 
-    def get_output_args(self, target):
+    def get_output_args(self, target: str) -> T.List[str]:
         return [] # Because compiles into C.
 
-    def get_compile_only_args(self):
+    def get_compile_only_args(self) -> T.List[str]:
         return [] # Because compiles into C.
 
-    def get_pic_args(self):
+    def get_pic_args(self) -> T.List[str]:
         return []
 
-    def get_pie_args(self):
+    def get_pie_args(self) -> T.List[str]:
         return []
 
-    def get_pie_link_args(self):
+    def get_pie_link_args(self) -> T.List[str]:
         return []
 
-    def get_always_args(self):
+    def get_always_args(self) -> T.List[str]:
         return ['-C']
 
-    def get_warn_args(self, warning_level):
+    def get_warn_args(self, warning_level: str) -> T.List[str]:
         return []
 
-    def get_no_warn_args(self):
+    def get_no_warn_args(self) -> T.List[str]:
         return ['--disable-warnings']
 
-    def get_werror_args(self):
+    def get_werror_args(self) -> T.List[str]:
         return ['--fatal-warnings']
 
-    def get_colorout_args(self, colortype):
+    def get_colorout_args(self, colortype: str) -> T.List[str]:
         if version_compare(self.version, '>=0.37.1'):
             return ['--color=' + colortype]
         return []
 
-    def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
+                                               build_dir: str) -> T.List[str]:
         for idx, i in enumerate(parameter_list):
             if i[:9] == '--girdir=':
                 parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
@@ -92,32 +90,34 @@
 
         return parameter_list
 
-    def sanity_check(self, work_dir, environment):
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
         code = 'class MesonSanityCheck : Object { }'
-        extra_flags = environment.coredata.get_external_args(self.for_machine, self.language)
+        extra_flags: T.List[str] = []
+        extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
         if self.is_cross:
             extra_flags += self.get_compile_only_args()
         else:
             extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language)
         with self.cached_compile(code, environment.coredata, extra_args=extra_flags, mode='compile') as p:
             if p.returncode != 0:
-                msg = 'Vala compiler {!r} can not compile programs' \
-                      ''.format(self.name_string())
+                msg = f'Vala compiler {self.name_string()!r} can not compile programs'
                 raise EnvironmentException(msg)
 
-    def get_buildtype_args(self, buildtype):
-        if buildtype == 'debug' or buildtype == 'debugoptimized' or buildtype == 'minsize':
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        if buildtype in {'debug', 'debugoptimized', 'minsize'}:
             return ['--debug']
         return []
 
-    def find_library(self, libname, env, extra_dirs, *args):
+    def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
+                     libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]:
         if extra_dirs and isinstance(extra_dirs, str):
             extra_dirs = [extra_dirs]
         # Valac always looks in the default vapi dir, so only search there if
         # no extra dirs are specified.
         if not extra_dirs:
             code = 'class MesonFindLibrary : Object { }'
-            args = env.coredata.get_external_args(self.for_machine, self.language)
+            args: T.List[str] = []
+            args += env.coredata.get_external_args(self.for_machine, self.language)
             vapi_args = ['--pkg', libname]
             args += vapi_args
             with self.cached_compile(code, env.coredata, extra_args=args, mode='compile') as p:
@@ -128,11 +128,11 @@
             vapi = os.path.join(d, libname + '.vapi')
             if os.path.isfile(vapi):
                 return [vapi]
-        mlog.debug('Searched {!r} and {!r} wasn\'t found'.format(extra_dirs, libname))
+        mlog.debug(f'Searched {extra_dirs!r} and {libname!r} wasn\'t found')
         return None
 
-    def thread_flags(self, env):
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
         return []
 
-    def thread_link_flags(self, env):
+    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
         return []
diff -Nru meson-0.53.2/mesonbuild/coredata.py meson-0.61.2/mesonbuild/coredata.py
--- meson-0.53.2/mesonbuild/coredata.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/coredata.py	2022-02-14 19:03:13.000000000 +0000
@@ -1,4 +1,4 @@
-# Copyright 2012-2019 The Meson development team
+# Copyright 2012-2021 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.
@@ -12,15 +12,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from . import mlog
+from . import mlog, mparser
 import pickle, os, uuid
 import sys
 from itertools import chain
 from pathlib import PurePath
 from collections import OrderedDict
 from .mesonlib import (
-    MesonException, MachineChoice, PerMachine,
-    default_libdir, default_libexecdir, default_prefix, split_args
+    HoldableObject,
+    MesonException, EnvironmentException, MachineChoice, PerMachine,
+    PerMachineDefaultable, default_libdir, default_libexecdir,
+    default_prefix, split_args, OptionKey, OptionType, stringlistify,
 )
 from .wrap import WrapMode
 import ast
@@ -32,21 +34,40 @@
 
 if T.TYPE_CHECKING:
     from . import dependencies
-    from .compilers import Compiler  # noqa: F401
+    from .compilers.compilers import Compiler, CompileResult
     from .environment import Environment
+    from .mesonlib import OptionOverrideProxy, FileOrString
+    from .cmake.traceparser import CMakeCacheEntry
 
-    OptionDictType = T.Dict[str, 'UserOption[T.Any]']
+    OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], OptionOverrideProxy]
+    KeyedOptionDictType = T.Union[T.Dict['OptionKey', 'UserOption[T.Any]'], OptionOverrideProxy]
+    CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], str]
+
+# Check major_versions_differ() if changing versioning scheme.
+#
+# 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.2'
 
-version = '0.53.2'
-backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode']
+backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode']
 
 default_yielding = False
 
 # Can't bind this near the class method it seems, sadly.
 _T = T.TypeVar('_T')
 
-class UserOption(T.Generic[_T]):
-    def __init__(self, description, choices, yielding):
+
+class MesonVersionMismatchException(MesonException):
+    '''Build directory generated with Meson version is incompatible with current version'''
+    def __init__(self, old_version: str, current_version: str) -> None:
+        super().__init__(f'Build directory has been generated with Meson version {old_version}, '
+                         f'which is incompatible with the current version {current_version}.')
+        self.old_version = old_version
+        self.current_version = current_version
+
+
+class UserOption(T.Generic[_T], HoldableObject):
+    def __init__(self, description: str, choices: T.Optional[T.Union[str, T.List[_T]]], yielding: T.Optional[bool]):
         super().__init__()
         self.choices = choices
         self.description = description
@@ -55,8 +76,13 @@
         if not isinstance(yielding, bool):
             raise MesonException('Value of "yielding" must be a boolean.')
         self.yielding = yielding
+        self.deprecated: T.Union[bool, T.Dict[str, str], T.List[str]] = False
+
+    def listify(self, value: T.Any) -> T.List[T.Any]:
+        return [value]
 
-    def printable_value(self):
+    def printable_value(self) -> T.Union[str, int, bool, T.List[T.Union[str, int, bool]]]:
+        assert isinstance(self.value, (str, int, bool, list))
         return self.value
 
     # Check that the input is a valid value and return the
@@ -65,30 +91,32 @@
     def validate_value(self, value: T.Any) -> _T:
         raise RuntimeError('Derived option class did not override validate_value.')
 
-    def set_value(self, newvalue):
+    def set_value(self, newvalue: T.Any) -> None:
         self.value = self.validate_value(newvalue)
 
 class UserStringOption(UserOption[str]):
-    def __init__(self, description, value, choices=None, yielding=None):
-        super().__init__(description, choices, yielding)
+    def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None):
+        super().__init__(description, None, yielding)
         self.set_value(value)
 
-    def validate_value(self, value):
+    def validate_value(self, value: T.Any) -> str:
         if not isinstance(value, str):
             raise MesonException('Value "%s" for string option is not a string.' % str(value))
         return value
 
 class UserBooleanOption(UserOption[bool]):
-    def __init__(self, description, value, yielding=None):
+    def __init__(self, description: str, value, yielding: T.Optional[bool] = None) -> None:
         super().__init__(description, [True, False], yielding)
         self.set_value(value)
 
     def __bool__(self) -> bool:
         return self.value
 
-    def validate_value(self, value) -> bool:
+    def validate_value(self, value: T.Any) -> bool:
         if isinstance(value, bool):
             return value
+        if not isinstance(value, str):
+            raise MesonException(f'Value {value} cannot be converted to a boolean')
         if value.lower() == 'true':
             return True
         if value.lower() == 'false':
@@ -96,19 +124,20 @@
         raise MesonException('Value %s is not boolean (true or false).' % value)
 
 class UserIntegerOption(UserOption[int]):
-    def __init__(self, description, min_value, max_value, value, yielding=None):
-        super().__init__(description, [True, False], yielding)
+    def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None):
+        min_value, max_value, default_value = value
         self.min_value = min_value
         self.max_value = max_value
-        self.set_value(value)
         c = []
         if min_value is not None:
             c.append('>=' + str(min_value))
         if max_value is not None:
             c.append('<=' + str(max_value))
-        self.choices = ', '.join(c)
+        choices = ', '.join(c)
+        super().__init__(description, choices, yielding)
+        self.set_value(default_value)
 
-    def validate_value(self, value) -> int:
+    def validate_value(self, value: T.Any) -> int:
         if isinstance(value, str):
             value = self.toint(value)
         if not isinstance(value, int):
@@ -119,35 +148,42 @@
             raise MesonException('New value %d is more than maximum value %d.' % (value, self.max_value))
         return value
 
-    def toint(self, valuestring) -> int:
+    def toint(self, valuestring: str) -> int:
         try:
             return int(valuestring)
         except ValueError:
             raise MesonException('Value string "%s" is not convertible to an integer.' % valuestring)
 
-class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, int]]):
-    def __init__(self, description, value, yielding=None):
-        super().__init__(description, 0, 0o777, value, yielding)
+class OctalInt(int):
+    # NinjaBackend.get_user_option_args uses str() to converts it to a command line option
+    # UserUmaskOption.toint() uses int(str, 8) to convert it to an integer
+    # So we need to use oct instead of dec here if we do not want values to be misinterpreted.
+    def __str__(self):
+        return oct(int(self))
+
+class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]):
+    def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None):
+        super().__init__(description, (0, 0o777, value), yielding)
         self.choices = ['preserve', '0000-0777']
 
-    def printable_value(self):
+    def printable_value(self) -> str:
         if self.value == 'preserve':
             return self.value
         return format(self.value, '04o')
 
-    def validate_value(self, value):
+    def validate_value(self, value: T.Any) -> T.Union[str, OctalInt]:
         if value is None or value == 'preserve':
             return 'preserve'
-        return super().validate_value(value)
+        return OctalInt(super().validate_value(value))
 
-    def toint(self, valuestring):
+    def toint(self, valuestring: T.Union[str, OctalInt]) -> int:
         try:
             return int(valuestring, 8)
         except ValueError as e:
-            raise MesonException('Invalid mode: {}'.format(e))
+            raise MesonException(f'Invalid mode: {e}')
 
 class UserComboOption(UserOption[str]):
-    def __init__(self, description, choices: T.List[str], value, yielding=None):
+    def __init__(self, description: str, choices: T.List[str], value: T.Any, yielding: T.Optional[bool] = None):
         super().__init__(description, choices, yielding)
         if not isinstance(self.choices, list):
             raise MesonException('Combo choices must be an array.')
@@ -156,20 +192,28 @@
                 raise MesonException('Combo choice elements must be strings.')
         self.set_value(value)
 
-    def validate_value(self, value):
+    def validate_value(self, value: T.Any) -> str:
         if value not in self.choices:
-            optionsstring = ', '.join(['"%s"' % (item,) for item in self.choices])
-            raise MesonException('Value "%s" for combo option is not one of the choices. Possible choices are: %s.' % (value, optionsstring))
+            if isinstance(value, bool):
+                _type = 'boolean'
+            elif isinstance(value, (int, float)):
+                _type = 'number'
+            else:
+                _type = 'string'
+            optionsstring = ', '.join([f'"{item}"' for item in self.choices])
+            raise MesonException('Value "{}" (of type "{}") for combo option "{}" is not one of the choices.'
+                                 ' Possible choices are (as string): {}.'.format(
+                                     value, _type, self.description, optionsstring))
         return value
 
 class UserArrayOption(UserOption[T.List[str]]):
-    def __init__(self, description, value, split_args=False, user_input=False, allow_dups=False, **kwargs):
+    def __init__(self, description: str, value: T.Union[str, T.List[str]], split_args: bool = False, user_input: bool = False, allow_dups: bool = False, **kwargs: T.Any) -> None:
         super().__init__(description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None))
         self.split_args = split_args
         self.allow_dups = allow_dups
         self.value = self.validate_value(value, user_input=user_input)
 
-    def validate_value(self, value, user_input: bool = True) -> T.List[str]:
+    def listify(self, value: T.Union[str, T.List[str]], user_input: bool = True) -> T.List[str]:
         # User input is for options defined on the command line (via -D
         # options). Users can put their input in as a comma separated
         # string, but for defining options in meson_options.txt the format
@@ -182,7 +226,7 @@
                 try:
                     newvalue = ast.literal_eval(value)
                 except ValueError:
-                    raise MesonException('malformed option {}'.format(value))
+                    raise MesonException(f'malformed option {value}')
             elif value == '':
                 newvalue = []
             else:
@@ -193,7 +237,11 @@
         elif isinstance(value, list):
             newvalue = value
         else:
-            raise MesonException('"{}" should be a string array, but it is not'.format(newvalue))
+            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]:
+        newvalue = self.listify(value, user_input)
 
         if not self.allow_dups and len(set(newvalue)) != len(newvalue):
             msg = 'Duplicated values in array option is deprecated. ' \
@@ -201,7 +249,7 @@
             mlog.deprecation(msg)
         for i in newvalue:
             if not isinstance(i, str):
-                raise MesonException('String array element "{0}" is not a string.'.format(str(newvalue)))
+                raise MesonException(f'String array element "{newvalue!s}" is not a string.')
         if self.choices:
             bad = [x for x in newvalue if x not in self.choices]
             if bad:
@@ -209,33 +257,30 @@
                     ', '.join(bad), ', '.join(self.choices)))
         return newvalue
 
+    def extend_value(self, value: T.Union[str, T.List[str]]) -> None:
+        """Extend the value with an additional value."""
+        new = self.validate_value(value)
+        self.set_value(self.value + new)
+
 
 class UserFeatureOption(UserComboOption):
     static_choices = ['enabled', 'disabled', 'auto']
 
-    def __init__(self, description, value, yielding=None):
+    def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None):
         super().__init__(description, self.static_choices, value, yielding)
+        self.name: T.Optional[str] = None  # TODO: Refactor options to all store their name
 
-    def is_enabled(self):
+    def is_enabled(self) -> bool:
         return self.value == 'enabled'
 
-    def is_disabled(self):
+    def is_disabled(self) -> bool:
         return self.value == 'disabled'
 
-    def is_auto(self):
+    def is_auto(self) -> bool:
         return self.value == 'auto'
 
-
-def load_configs(filenames: T.List[str]) -> configparser.ConfigParser:
-    """Load configuration files from a named subdirectory."""
-    config = configparser.ConfigParser()
-    config.read(filenames)
-    return config
-
-
 if T.TYPE_CHECKING:
-    CacheKeyType = T.Tuple[T.Tuple[T.Any, ...], ...]
-    SubCacheKeyType = T.Tuple[T.Any, ...]
+    from .dependencies.detect import TV_DepID
 
 
 class DependencyCacheType(enum.Enum):
@@ -259,15 +304,15 @@
 
     def __init__(self, type_: DependencyCacheType):
         self.types = [type_]
-        self.__cache = {}  # type: T.Dict[SubCacheKeyType, dependencies.Dependency]
+        self.__cache: T.Dict[T.Tuple[str, ...], 'dependencies.Dependency'] = {}
 
-    def __getitem__(self, key: 'SubCacheKeyType') -> 'dependencies.Dependency':
+    def __getitem__(self, key: T.Tuple[str, ...]) -> 'dependencies.Dependency':
         return self.__cache[key]
 
-    def __setitem__(self, key: 'SubCacheKeyType', value: 'dependencies.Dependency') -> None:
+    def __setitem__(self, key: T.Tuple[str, ...], value: 'dependencies.Dependency') -> None:
         self.__cache[key] = value
 
-    def __contains__(self, key: 'SubCacheKeyType') -> bool:
+    def __contains__(self, key: T.Tuple[str, ...]) -> bool:
         return key in self.__cache
 
     def values(self) -> T.Iterable['dependencies.Dependency']:
@@ -282,30 +327,32 @@
     successfully lookup by providing a simple get/put interface.
     """
 
-    def __init__(self, builtins_per_machine: PerMachine[T.Dict[str, UserOption[T.Any]]], for_machine: MachineChoice):
-        self.__cache = OrderedDict()  # type: T.MutableMapping[CacheKeyType, DependencySubCache]
-        self.__builtins_per_machine = builtins_per_machine
-        self.__for_machine = for_machine
-
-    def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[T.Any, ...]:
-        if type_ is DependencyCacheType.PKG_CONFIG:
-            return tuple(self.__builtins_per_machine[self.__for_machine]['pkg_config_path'].value)
-        elif type_ is DependencyCacheType.CMAKE:
-            return tuple(self.__builtins_per_machine[self.__for_machine]['cmake_prefix_path'].value)
-        assert type_ is DependencyCacheType.OTHER, 'Someone forgot to update subkey calculations for a new type'
-        return tuple()
+    def __init__(self, builtins: 'KeyedOptionDictType', for_machine: MachineChoice):
+        self.__cache = OrderedDict()  # type: T.MutableMapping[TV_DepID, DependencySubCache]
+        self.__builtins = builtins
+        self.__pkg_conf_key = OptionKey('pkg_config_path', machine=for_machine)
+        self.__cmake_key = OptionKey('cmake_prefix_path', machine=for_machine)
+
+    def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[str, ...]:
+        data: T.Dict[str, T.List[str]] = {
+            DependencyCacheType.PKG_CONFIG: stringlistify(self.__builtins[self.__pkg_conf_key].value),
+            DependencyCacheType.CMAKE: stringlistify(self.__builtins[self.__cmake_key].value),
+            DependencyCacheType.OTHER: [],
+        }
+        assert type_ in data, 'Someone forgot to update subkey calculations for a new type'
+        return tuple(data[type_])
 
-    def __iter__(self) -> T.Iterator['CacheKeyType']:
+    def __iter__(self) -> T.Iterator['TV_DepID']:
         return self.keys()
 
-    def put(self, key: 'CacheKeyType', dep: 'dependencies.Dependency') -> None:
+    def put(self, key: 'TV_DepID', dep: 'dependencies.Dependency') -> None:
         t = DependencyCacheType.from_type(dep)
         if key not in self.__cache:
             self.__cache[key] = DependencySubCache(t)
         subkey = self.__calculate_subkey(t)
         self.__cache[key][subkey] = dep
 
-    def get(self, key: 'CacheKeyType') -> T.Optional['dependencies.Dependency']:
+    def get(self, key: 'TV_DepID') -> T.Optional['dependencies.Dependency']:
         """Get a value from the cache.
 
         If there is no cache entry then None will be returned.
@@ -327,10 +374,10 @@
         for c in self.__cache.values():
             yield from c.values()
 
-    def keys(self) -> T.Iterator['CacheKeyType']:
+    def keys(self) -> T.Iterator['TV_DepID']:
         return iter(self.__cache.keys())
 
-    def items(self) -> T.Iterator[T.Tuple['CacheKeyType', T.List['dependencies.Dependency']]]:
+    def items(self) -> T.Iterator[T.Tuple['TV_DepID', T.List['dependencies.Dependency']]]:
         for k, v in self.__cache.items():
             vs = []
             for t in v.types:
@@ -342,6 +389,34 @@
     def clear(self) -> None:
         self.__cache.clear()
 
+
+class CMakeStateCache:
+    """Class that stores internal CMake compiler states.
+
+    This cache is used to reduce the startup overhead of CMake by caching
+    all internal CMake compiler variables.
+    """
+
+    def __init__(self) -> None:
+        self.__cache: T.Dict[str, T.Dict[str, T.List[str]]] = {}
+        self.cmake_cache: T.Dict[str, 'CMakeCacheEntry'] = {}
+
+    def __iter__(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
+        return iter(self.__cache.items())
+
+    def items(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
+        return iter(self.__cache.items())
+
+    def update(self, language: str, variables: T.Dict[str, T.List[str]]):
+        if language not in self.__cache:
+            self.__cache[language] = {}
+        self.__cache[language].update(variables)
+
+    @property
+    def languages(self) -> T.Set[str]:
+        return set(self.__cache.keys())
+
+
 # Can't bind this near the class method it seems, sadly.
 _V = T.TypeVar('_V')
 
@@ -351,7 +426,7 @@
 
 class CoreData:
 
-    def __init__(self, options: argparse.Namespace, scratch_dir: str):
+    def __init__(self, options: argparse.Namespace, scratch_dir: str, meson_command: T.List[str]):
         self.lang_guids = {
             'default': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
             'c': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
@@ -362,23 +437,33 @@
         self.test_guid = str(uuid.uuid4()).upper()
         self.regen_guid = str(uuid.uuid4()).upper()
         self.install_guid = str(uuid.uuid4()).upper()
+        self.meson_command = meson_command
         self.target_guids = {}
         self.version = version
-        self.init_builtins()
-        self.backend_options = {} # : T.Dict[str, UserOption]
-        self.user_options = {} # : T.Dict[str, UserOption]
-        self.compiler_options = PerMachine({}, {})
-        self.base_options = {} # : T.Dict[str, UserOption]
+        self.options: 'KeyedOptionDictType' = {}
         self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
-        self.compilers = PerMachine(OrderedDict(), OrderedDict())
+        self.compilers = PerMachine(OrderedDict(), OrderedDict())  # type: PerMachine[T.Dict[str, Compiler]]
+
+        # Set of subprojects that have already been initialized once, this is
+        # required to be stored and reloaded with the coredata, as we don't
+        # want to overwrite options for such subprojects.
+        self.initialized_subprojects: T.Set[str] = set()
+
+        # For host == build configuraitons these caches should be the same.
+        self.deps: PerMachine[DependencyCache] = PerMachineDefaultable.default(
+            self.is_cross_build(),
+            DependencyCache(self.options, MachineChoice.BUILD),
+            DependencyCache(self.options, MachineChoice.HOST))
+
+        self.compiler_check_cache: T.Dict['CompilerCheckCacheKey', 'CompileResult'] = OrderedDict()
+
+        # CMake cache
+        self.cmake_cache: PerMachine[CMakeStateCache] = PerMachine(CMakeStateCache(), CMakeStateCache())
 
-        build_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD)
-        host_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD)
-        self.deps = PerMachine(build_cache, host_cache)  # type: PerMachine[DependencyCache]
-        self.compiler_check_cache = OrderedDict()
         # Only to print a warning if it changes between Meson invocations.
         self.config_files = self.__load_config_files(options, scratch_dir, 'native')
-        self.libdir_cross_fixup()
+        self.builtin_options_libdir_cross_fixup()
+        self.init_builtins('')
 
     @staticmethod
     def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: str) -> T.List[str]:
@@ -407,9 +492,9 @@
                     # in this case we've been passed some kind of pipe, copy
                     # the contents of that file into the meson private (scratch)
                     # directory so that it can be re-read when wiping/reconfiguring
-                    copy = os.path.join(scratch_dir, '{}.{}.ini'.format(uuid.uuid4(), ftype))
-                    with open(f, 'r') as rf:
-                        with open(copy, 'w') as wf:
+                    copy = os.path.join(scratch_dir, f'{uuid.uuid4()}.{ftype}.ini')
+                    with open(f, encoding='utf-8') as rf:
+                        with open(copy, 'w', encoding='utf-8') as wf:
                             wf.write(rf.read())
                     real.append(copy)
 
@@ -435,21 +520,20 @@
             if found_invalid:
                 mlog.log('Found invalid candidates for', ftype, 'file:', *found_invalid)
             mlog.log('Could not find any valid candidate for', ftype, 'files:', *missing)
-            raise MesonException('Cannot find specified {} file: {}'.format(ftype, f))
+            raise MesonException(f'Cannot find specified {ftype} file: {f}')
         return real
 
-    def libdir_cross_fixup(self):
+    def builtin_options_libdir_cross_fixup(self):
         # By default set libdir to "lib" when cross compiling since
         # getting the "system default" is always wrong on multiarch
         # platforms as it gets a value like lib/x86_64-linux-gnu.
         if self.cross_files:
-            self.builtins['libdir'].value = 'lib'
+            BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib'
 
     def sanitize_prefix(self, prefix):
         prefix = os.path.expanduser(prefix)
         if not os.path.isabs(prefix):
-            raise MesonException('prefix value {!r} must be an absolute path'
-                                 ''.format(prefix))
+            raise MesonException(f'prefix value {prefix!r} must be an absolute path')
         if prefix.endswith('/') or prefix.endswith('\\'):
             # On Windows we need to preserve the trailing slash if the
             # string is of type 'C:\' because 'C:' is not an absolute path.
@@ -463,7 +547,7 @@
                 prefix = prefix[:-1]
         return prefix
 
-    def sanitize_dir_option_value(self, prefix, option, value):
+    def sanitize_dir_option_value(self, prefix: str, option: OptionKey, value: T.Any) -> T.Any:
         '''
         If the option is an installation directory option and the value is an
         absolute path, check that it resides within prefix and return the value
@@ -471,83 +555,129 @@
 
         This way everyone can do f.ex, get_option('libdir') and be sure to get
         the library directory relative to prefix.
+
+        .as_posix() keeps the posix-like file separators Meson uses.
         '''
-        if option.endswith('dir') and os.path.isabs(value) and \
-           option not in builtin_dir_noprefix_options:
+        try:
+            value = PurePath(value)
+        except TypeError:
+            return value
+        if option.name.endswith('dir') and value.is_absolute() and \
+           option not in BULITIN_DIR_NOPREFIX_OPTIONS:
             # Value must be a subdir of the prefix
             # commonpath will always return a path in the native format, so we
             # must use pathlib.PurePath to do the same conversion before
             # comparing.
-            if os.path.commonpath([value, prefix]) != str(PurePath(prefix)):
-                m = 'The value of the {!r} option is {!r} which must be a ' \
-                    'subdir of the prefix {!r}.\nNote that if you pass a ' \
-                    'relative path, it is assumed to be a subdir of prefix.'
-                raise MesonException(m.format(option, value, prefix))
-            # Convert path to be relative to prefix
-            skip = len(prefix) + 1
-            value = value[skip:]
-        return value
+            msg = ('The value of the \'{!s}\' option is \'{!s}\' which must be a '
+                   'subdir of the prefix {!r}.\nNote that if you pass a '
+                   'relative path, it is assumed to be a subdir of prefix.')
+            # os.path.commonpath doesn't understand case-insensitive filesystems,
+            # but PurePath().relative_to() does.
+            try:
+                value = value.relative_to(prefix)
+            except ValueError:
+                raise MesonException(msg.format(option, value, prefix))
+            if '..' in str(value):
+                raise MesonException(msg.format(option, value, prefix))
+        return value.as_posix()
 
-    def init_builtins(self):
+    def init_builtins(self, subproject: str) -> None:
         # Create builtin options with default values
-        self.builtins = {}
-        for key, opt in builtin_options.items():
-            self.builtins[key] = opt.init_option(key, default_prefix())
-        self.builtins_per_machine = PerMachine({}, {})
+        for key, opt in BUILTIN_OPTIONS.items():
+            self.add_builtin_option(self.options, key.evolve(subproject=subproject), opt)
         for for_machine in iter(MachineChoice):
-            for key, opt in builtin_options_per_machine.items():
-                self.builtins_per_machine[for_machine][key] = opt.init_option()
+            for key, opt in BUILTIN_OPTIONS_PER_MACHINE.items():
+                self.add_builtin_option(self.options, key.evolve(subproject=subproject, machine=for_machine), opt)
 
-    def init_backend_options(self, backend_name):
+    @staticmethod
+    def add_builtin_option(opts_map: 'KeyedOptionDictType', key: OptionKey,
+                           opt: 'BuiltinOption') -> None:
+        if key.subproject:
+            if opt.yielding:
+                # This option is global and not per-subproject
+                return
+            value = opts_map[key.as_root()].value
+        else:
+            value = None
+        opts_map[key] = opt.init_option(key, value, default_prefix())
+
+    def init_backend_options(self, backend_name: str) -> None:
         if backend_name == 'ninja':
-            self.backend_options['backend_max_links'] = \
-                UserIntegerOption(
-                    'Maximum number of linker processes to run or 0 for no '
-                    'limit',
-                    0, None, 0)
+            self.options[OptionKey('backend_max_links')] = UserIntegerOption(
+                'Maximum number of linker processes to run or 0 for no '
+                'limit',
+                (0, None, 0))
         elif backend_name.startswith('vs'):
-            self.backend_options['backend_startup_project'] = \
-                UserStringOption(
-                    'Default project to execute in Visual Studio',
-                    '')
-
-    def get_builtin_option(self, optname):
-        for opts in self._get_all_builtin_options():
-            v = opts.get(optname)
-            if v is None:
-                continue
-            if optname == 'wrap_mode':
-                return WrapMode.from_string(v.value)
-            return v.value
-        raise RuntimeError('Tried to get unknown builtin option %s.' % optname)
-
-    def _try_set_builtin_option(self, optname, value):
-        for opts in self._get_all_builtin_options():
-            opt = opts.get(optname)
-            if opt is None:
-                continue
-            if optname == 'prefix':
+            self.options[OptionKey('backend_startup_project')] = UserStringOption(
+                'Default project to execute in Visual Studio',
+                '')
+
+    def get_option(self, key: OptionKey) -> T.Union[str, int, bool, WrapMode]:
+        try:
+            v = self.options[key].value
+            if key.name == 'wrap_mode':
+                return WrapMode[v]
+            return v
+        except KeyError:
+            pass
+
+        try:
+            v = self.options[key.as_root()]
+            if v.yielding:
+                if key.name == 'wrap_mode':
+                    return WrapMode[v.value]
+                return v.value
+        except KeyError:
+            pass
+
+        raise MesonException(f'Tried to get unknown builtin option {str(key)}')
+
+    def set_option(self, key: OptionKey, value) -> None:
+        if key.is_builtin():
+            if key.name == 'prefix':
                 value = self.sanitize_prefix(value)
             else:
-                prefix = self.builtins['prefix'].value
-                value = self.sanitize_dir_option_value(prefix, optname, value)
-            break
-        else:
-            return False
-        opt.set_value(value)
-        # Make sure that buildtype matches other settings.
-        if optname == 'buildtype':
-            self.set_others_from_buildtype(value)
-        else:
-            self.set_buildtype_from_others()
-        return True
+                prefix = self.options[OptionKey('prefix')].value
+                value = self.sanitize_dir_option_value(prefix, key, value)
+
+        try:
+            opt = self.options[key]
+        except KeyError:
+            raise MesonException(f'Tried to set unknown builtin option {str(key)}')
+
+        if opt.deprecated is True:
+            mlog.deprecation(f'Option {key.name!r} is deprecated')
+        elif isinstance(opt.deprecated, list):
+            for v in opt.listify(value):
+                if v in opt.deprecated:
+                    mlog.deprecation(f'Option {key.name!r} value {v!r} is deprecated')
+        elif isinstance(opt.deprecated, dict):
+            def replace(v):
+                newvalue = opt.deprecated.get(v)
+                if newvalue is not None:
+                    mlog.deprecation(f'Option {key.name!r} value {v!r} is replaced by {newvalue!r}')
+                    return newvalue
+                return v
+            newvalue = [replace(v) for v in opt.listify(value)]
+            value = ','.join(newvalue)
 
-    def set_builtin_option(self, optname, value):
-        res = self._try_set_builtin_option(optname, value)
-        if not res:
-            raise RuntimeError('Tried to set unknown builtin option %s.' % optname)
+        opt.set_value(value)
 
-    def set_others_from_buildtype(self, value):
+        if key.name == 'buildtype':
+            self._set_others_from_buildtype(value)
+        elif key.name in {'wrap_mode', 'force_fallback_for'}:
+            # We could have the system dependency cached for a dependency that
+            # is now forced to use subproject fallback. We probably could have
+            # more fine grained cache invalidation, but better be safe.
+            self.clear_deps_cache()
+
+    def clear_deps_cache(self):
+        self.deps.host.clear()
+        self.deps.build.clear()
+
+    def get_nondefault_buildtype_args(self):
+        result = []
+        value = self.options[OptionKey('buildtype')].value
         if value == 'plain':
             opt = '0'
             debug = False
@@ -564,240 +694,280 @@
             opt = 's'
             debug = True
         else:
-            assert(value == 'custom')
-            return
-        self.builtins['optimization'].set_value(opt)
-        self.builtins['debug'].set_value(debug)
+            assert value == 'custom'
+            return []
+        actual_opt = self.options[OptionKey('optimization')].value
+        actual_debug = self.options[OptionKey('debug')].value
+        if actual_opt != opt:
+            result.append(('optimization', actual_opt, opt))
+        if actual_debug != debug:
+            result.append(('debug', actual_debug, debug))
+        return result
 
-    def set_buildtype_from_others(self):
-        opt = self.builtins['optimization'].value
-        debug = self.builtins['debug'].value
-        if opt == '0' and not debug:
-            mode = 'plain'
-        elif opt == '0' and debug:
-            mode = 'debug'
-        elif opt == '2' and debug:
-            mode = 'debugoptimized'
-        elif opt == '3' and not debug:
-            mode = 'release'
-        elif opt == 's' and debug:
-            mode = 'minsize'
+    def _set_others_from_buildtype(self, value: str) -> None:
+        if value == 'plain':
+            opt = '0'
+            debug = False
+        elif value == 'debug':
+            opt = '0'
+            debug = True
+        elif value == 'debugoptimized':
+            opt = '2'
+            debug = True
+        elif value == 'release':
+            opt = '3'
+            debug = False
+        elif value == 'minsize':
+            opt = 's'
+            debug = True
         else:
-            mode = 'custom'
-        self.builtins['buildtype'].set_value(mode)
+            assert value == 'custom'
+            return
+        self.options[OptionKey('optimization')].set_value(opt)
+        self.options[OptionKey('debug')].set_value(debug)
 
     @staticmethod
-    def get_prefixed_options_per_machine(
-        options_per_machine # : PerMachine[T.Dict[str, _V]]]
-    ) -> T.Iterable[T.Dict[str, _V]]:
-        for for_machine in iter(MachineChoice):
-            prefix = for_machine.get_prefix()
-            yield {
-                prefix + k: v
-                for k, v in options_per_machine[for_machine].items()
-            }
-
-    def _get_all_nonbuiltin_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
-        yield self.backend_options
-        yield self.user_options
-        yield from self.get_prefixed_options_per_machine(self.compiler_options)
-        yield self.base_options
-
-    def _get_all_builtin_options(self) -> T.Dict[str, UserOption]:
-        yield from self.get_prefixed_options_per_machine(self.builtins_per_machine)
-        yield self.builtins
-
-    def get_all_options(self) -> T.Dict[str, UserOption]:
-        yield from self._get_all_nonbuiltin_options()
-        yield from self._get_all_builtin_options()
-
-    def validate_option_value(self, option_name, override_value):
-        for opts in self.get_all_options():
-            opt = opts.get(option_name)
-            if opt is not None:
+    def is_per_machine_option(optname: OptionKey) -> bool:
+        if optname.name in BUILTIN_OPTIONS_PER_MACHINE:
+            return True
+        return optname.lang is not None
+
+    def validate_option_value(self, option_name: OptionKey, override_value):
+        try:
+            opt = self.options[option_name]
+        except KeyError:
+            raise MesonException(f'Tried to validate unknown option {str(option_name)}')
+        try:
+            return opt.validate_value(override_value)
+        except MesonException as e:
+            raise type(e)(('Validation failed for option %s: ' % option_name) + str(e)) \
+                .with_traceback(sys.exc_info()[2])
+
+    def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.Union[str, T.List[str]]:
+        return self.options[OptionKey('args', machine=for_machine, lang=lang)].value
+
+    def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.Union[str, T.List[str]]:
+        return self.options[OptionKey('link_args', machine=for_machine, lang=lang)].value
+
+    def update_project_options(self, options: 'KeyedOptionDictType') -> None:
+        for key, value in options.items():
+            if not key.is_project():
+                continue
+            if key not in self.options:
+                self.options[key] = value
+                continue
+
+            oldval = self.options[key]
+            if type(oldval) != type(value):
+                self.options[key] = value
+            elif oldval.choices != value.choices:
+                # If the choices have changed, use the new value, but attempt
+                # to keep the old options. If they are not valid keep the new
+                # defaults but warn.
+                self.options[key] = value
                 try:
-                    return opt.validate_value(override_value)
-                except MesonException as e:
-                    raise type(e)(('Validation failed for option %s: ' % option_name) + str(e)) \
-                        .with_traceback(sys.exc_info()[2])
-        raise MesonException('Tried to validate unknown option %s.' % option_name)
-
-    def get_external_args(self, for_machine: MachineChoice, lang):
-        return self.compiler_options[for_machine][lang + '_args'].value
-
-    def get_external_link_args(self, for_machine: MachineChoice, lang):
-        return self.compiler_options[for_machine][lang + '_link_args'].value
-
-    def merge_user_options(self, options):
-        for (name, value) in options.items():
-            if name not in self.user_options:
-                self.user_options[name] = value
-            else:
-                oldval = self.user_options[name]
-                if type(oldval) != type(value):
-                    self.user_options[name] = value
+                    value.set_value(oldval.value)
+                except MesonException:
+                    mlog.warning(f'Old value(s) of {key} are no longer valid, resetting to default ({value.value}).')
 
-    def is_cross_build(self) -> bool:
+    def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
+        if when_building_for == MachineChoice.BUILD:
+            return False
         return len(self.cross_files) > 0
 
-    def strip_build_option_names(self, options):
-        res = {}
-        for k, v in options.items():
-            if k.startswith('build.'):
-                k = k.split('.', 1)[1]
-            res[k] = v
-        return res
-
-    def copy_build_options_from_regular_ones(self):
-        assert(not self.is_cross_build())
-        for k, o in self.builtins_per_machine.host.items():
-            self.builtins_per_machine.build[k].set_value(o.value)
-        for k, o in self.compiler_options.host.items():
-            if k in self.compiler_options.build:
-                self.compiler_options.build[k].set_value(o.value)
+    def copy_build_options_from_regular_ones(self) -> None:
+        assert not self.is_cross_build()
+        for k in BUILTIN_OPTIONS_PER_MACHINE:
+            o = self.options[k]
+            self.options[k.as_build()].set_value(o.value)
+        for bk, bv in self.options.items():
+            if bk.machine is MachineChoice.BUILD:
+                hk = bk.as_host()
+                try:
+                    hv = self.options[hk]
+                    bv.set_value(hv.value)
+                except KeyError:
+                    continue
 
-    def set_options(self, options, *, subproject='', warn_unknown=True):
+    def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '') -> None:
         if not self.is_cross_build():
-            options = self.strip_build_option_names(options)
+            options = {k: v for k, v in options.items() if k.machine is not MachineChoice.BUILD}
         # Set prefix first because it's needed to sanitize other options
-        if 'prefix' in options:
-            prefix = self.sanitize_prefix(options['prefix'])
-            self.builtins['prefix'].set_value(prefix)
-            for key in builtin_dir_noprefix_options:
+        pfk = OptionKey('prefix')
+        if pfk in options:
+            prefix = self.sanitize_prefix(options[pfk])
+            self.options[OptionKey('prefix')].set_value(prefix)
+            for key in BULITIN_DIR_NOPREFIX_OPTIONS:
                 if key not in options:
-                    self.builtins[key].set_value(builtin_options[key].prefixed_default(key, prefix))
+                    self.options[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix))
 
-        unknown_options = []
+        unknown_options: T.List[OptionKey] = []
         for k, v in options.items():
-            if k == 'prefix':
+            if k == pfk:
                 continue
-            if self._try_set_builtin_option(k, v):
-                continue
-            for opts in self._get_all_nonbuiltin_options():
-                tgt = opts.get(k)
-                if tgt is None:
-                    continue
-                tgt.set_value(v)
-                break
-            else:
+            elif k in self.options:
+                self.set_option(k, v)
+            elif k.machine != MachineChoice.BUILD:
                 unknown_options.append(k)
-        if unknown_options and warn_unknown:
-            unknown_options = ', '.join(sorted(unknown_options))
-            sub = 'In subproject {}: '.format(subproject) if subproject else ''
-            mlog.warning('{}Unknown options: "{}"'.format(sub, unknown_options))
+        if unknown_options:
+            unknown_options_str = ', '.join(sorted(str(s) for s in unknown_options))
+            sub = f'In subproject {subproject}: ' if subproject else ''
+            raise MesonException(f'{sub}Unknown options: "{unknown_options_str}"')
+
         if not self.is_cross_build():
             self.copy_build_options_from_regular_ones()
 
-    def set_default_options(self, default_options, subproject, env):
-        # Set defaults first from conf files (cross or native), then
-        # override them as nec as necessary.
-        for k, v in env.paths.host:
-            if v is not None:
-                env.cmd_line_options.setdefault(k, v)
-
-        # Set default options as if they were passed to the command line.
-        # Subprojects can only define default for user options.
-        from . import optinterpreter
-        for k, v in default_options.items():
-            if subproject:
-                if optinterpreter.is_invalid_name(k, log=False):
-                    continue
-                k = subproject + ':' + k
-            env.cmd_line_options.setdefault(k, v)
+    def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], subproject: str, env: 'Environment') -> None:
+        # Preserve order: if env.options has 'buildtype' it must come after
+        # 'optimization' if it is in default_options.
+        options: T.MutableMapping[OptionKey, T.Any]
+        if not subproject:
+            options = OrderedDict(default_options)
+            options.update(env.options)
+            env.options = options
 
-        # Create a subset of cmd_line_options, keeping only options for this
-        # subproject. Also take builtin options if it's the main project.
+        # Create a subset of options, keeping only project and builtin
+        # options for this subproject.
         # Language and backend specific options will be set later when adding
         # languages and setting the backend (builtin options must be set first
         # to know which backend we'll use).
-        options = {}
+        options = OrderedDict()
 
-        # Some options default to environment variables if they are
-        # unset, set those now. These will either be overwritten
-        # below, or they won't. These should only be set on the first run.
-        if env.first_invocation:
-            p_env = os.environ.get('PKG_CONFIG_PATH')
-            if p_env:
-                # PKG_CONFIG_PATH may contain duplicates, which must be
-                # removed, else a duplicates-in-array-option warning arises.
-                pkg_config_paths = []
-                for k in p_env.split(':'):
-                    if k not in pkg_config_paths:
-                        pkg_config_paths.append(k)
-                options['pkg_config_path'] = pkg_config_paths
-
-        for k, v in env.cmd_line_options.items():
-            if subproject:
-                if not k.startswith(subproject + ':'):
-                    continue
-            elif k not in builtin_options.keys() \
-                    and 'build.' + k not in builtin_options_per_machine.keys() \
-                    and k not in builtin_options_per_machine.keys():
-                if ':' in k:
-                    continue
-                if optinterpreter.is_invalid_name(k, log=False):
-                    continue
+        for k, v in chain(default_options.items(), env.options.items()):
+            # If this is a subproject, don't use other subproject options
+            if k.subproject and k.subproject != subproject:
+                continue
+            # If the option is a builtin and is yielding then it's not allowed per subproject.
+            #
+            # Always test this using the HOST machine, as many builtin options
+            # are not valid for the BUILD machine, but the yielding value does
+            # not differ between them even when they are valid for both.
+            if subproject and k.is_builtin() and self.options[k.evolve(subproject='', machine=MachineChoice.HOST)].yielding:
+                continue
+            # Skip base, compiler, and backend options, they are handled when
+            # adding languages and setting backend.
+            if k.type in {OptionType.COMPILER, OptionType.BACKEND, OptionType.BASE}:
+                continue
             options[k] = v
 
         self.set_options(options, subproject=subproject)
 
+    def add_compiler_options(self, options: 'KeyedOptionDictType', lang: str, for_machine: MachineChoice,
+                             env: 'Environment') -> None:
+        for k, o in options.items():
+            value = env.options.get(k)
+            if value is not None:
+                o.set_value(value)
+            self.options.setdefault(k, o)
+
     def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
                       for_machine: MachineChoice, env: 'Environment') -> None:
         """Add global language arguments that are needed before compiler/linker detection."""
         from .compilers import compilers
+        # These options are all new at this point, because the compiler is
+        # responsible for adding its own options, thus calling
+        # `self.options.update()`` is perfectly safe.
+        self.options.update(compilers.get_global_options(lang, comp, for_machine, env))
 
-        optprefix = lang + '_'
-        for k, o in compilers.get_global_options(lang, comp, env.properties[for_machine]).items():
-            if not k.startswith(optprefix):
-                raise MesonException('Internal error, %s has incorrect prefix.' % k)
-            # prefixed compiler options affect just this machine
-            opt_prefix = for_machine.get_prefix()
-            if opt_prefix + k in env.cmd_line_options:
-                o.set_value(env.cmd_line_options[opt_prefix + k])
-            self.compiler_options[for_machine].setdefault(k, o)
-
-    def process_new_compiler(self, lang: str, comp: T.Type['Compiler'], env: 'Environment') -> None:
+    def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None:
         from . import compilers
 
         self.compilers[comp.for_machine][lang] = comp
-        enabled_opts = []
+        self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env)
 
-        optprefix = lang + '_'
-        for k, o in comp.get_options().items():
-            if not k.startswith(optprefix):
-                raise MesonException('Internal error, %s has incorrect prefix.' % k)
-            # prefixed compiler options affect just this machine
-            opt_prefix = comp.for_machine.get_prefix()
-            if opt_prefix + k in env.cmd_line_options:
-                o.set_value(env.cmd_line_options[opt_prefix + k])
-            self.compiler_options[comp.for_machine].setdefault(k, o)
-
-        enabled_opts = []
-        for optname in comp.base_options:
-            if optname in self.base_options:
+        enabled_opts: T.List[OptionKey] = []
+        for key in comp.base_options:
+            if key in self.options:
                 continue
-            oobj = compilers.base_options[optname]
-            if optname in env.cmd_line_options:
-                oobj.set_value(env.cmd_line_options[optname])
-                enabled_opts.append(optname)
-            self.base_options[optname] = oobj
+            oobj = compilers.base_options[key]
+            if key in env.options:
+                oobj.set_value(env.options[key])
+                enabled_opts.append(key)
+            self.options[key] = oobj
         self.emit_base_options_warnings(enabled_opts)
 
-    def emit_base_options_warnings(self, enabled_opts: list):
-        if 'b_bitcode' in enabled_opts:
-            mlog.warning('Base option \'b_bitcode\' is enabled, which is incompatible with many linker options. Incompatible options such as such as \'b_asneeded\' have been disabled.')
-            mlog.warning('Please see https://mesonbuild.com/Builtin-options.html#Notes_about_Apple_Bitcode_support for more details.')
+    def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:
+        if OptionKey('b_bitcode') in enabled_opts:
+            mlog.warning('Base option \'b_bitcode\' is enabled, which is incompatible with many linker options. Incompatible options such as \'b_asneeded\' have been disabled.', fatal=False)
+            mlog.warning('Please see https://mesonbuild.com/Builtin-options.html#Notes_about_Apple_Bitcode_support for more details.', fatal=False)
 
 class CmdLineFileParser(configparser.ConfigParser):
-    def __init__(self):
+    def __init__(self) -> None:
         # We don't want ':' as key delimiter, otherwise it would break when
         # storing subproject options like "subproject:option=value"
         super().__init__(delimiters=['='], interpolation=None)
 
-def get_cmd_line_file(build_dir):
+    def optionxform(self, option: str) -> str:
+        # Don't call str.lower() on keys
+        return option
+
+class MachineFileParser():
+    def __init__(self, filenames: T.List[str]) -> None:
+        self.parser = CmdLineFileParser()
+        self.constants = {'True': True, 'False': False}
+        self.sections = {}
+
+        self.parser.read(filenames)
+
+        # Parse [constants] first so they can be used in other sections
+        if self.parser.has_section('constants'):
+            self.constants.update(self._parse_section('constants'))
+
+        for s in self.parser.sections():
+            if s == 'constants':
+                continue
+            self.sections[s] = self._parse_section(s)
+
+    def _parse_section(self, s):
+        self.scope = self.constants.copy()
+        section = {}
+        for entry, value in self.parser.items(s):
+            if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry:
+                raise EnvironmentException(f'Malformed variable name {entry!r} in machine file.')
+            # Windows paths...
+            value = value.replace('\\', '\\\\')
+            try:
+                ast = mparser.Parser(value, 'machinefile').parse()
+                res = self._evaluate_statement(ast.lines[0])
+            except MesonException:
+                raise EnvironmentException(f'Malformed value in machine file variable {entry!r}.')
+            except KeyError as e:
+                raise EnvironmentException(f'Undefined constant {e.args[0]!r} in machine file variable {entry!r}.')
+            section[entry] = res
+            self.scope[entry] = res
+        return section
+
+    def _evaluate_statement(self, node):
+        if isinstance(node, (mparser.StringNode)):
+            return node.value
+        elif isinstance(node, mparser.BooleanNode):
+            return node.value
+        elif isinstance(node, mparser.NumberNode):
+            return node.value
+        elif isinstance(node, mparser.ArrayNode):
+            return [self._evaluate_statement(arg) for arg in node.args.arguments]
+        elif isinstance(node, mparser.IdNode):
+            return self.scope[node.value]
+        elif isinstance(node, mparser.ArithmeticNode):
+            l = self._evaluate_statement(node.left)
+            r = self._evaluate_statement(node.right)
+            if node.operation == 'add':
+                if (isinstance(l, str) and isinstance(r, str)) or \
+                   (isinstance(l, list) and isinstance(r, list)):
+                    return l + r
+            elif node.operation == 'div':
+                if isinstance(l, str) and isinstance(r, str):
+                    return os.path.join(l, r)
+        raise EnvironmentException('Unsupported node type')
+
+def parse_machine_files(filenames):
+    parser = MachineFileParser(filenames)
+    return parser.sections
+
+def get_cmd_line_file(build_dir: str) -> str:
     return os.path.join(build_dir, 'meson-private', 'cmd_line.txt')
 
-def read_cmd_line_file(build_dir, options):
+def read_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
     filename = get_cmd_line_file(build_dir)
     if not os.path.isfile(filename):
         return
@@ -807,7 +977,7 @@
 
     # Do a copy because config is not really a dict. options.cmd_line_options
     # overrides values from the file.
-    d = dict(config['options'])
+    d = {OptionKey.from_string(k): v for k, v in config['options'].items()}
     d.update(options.cmd_line_options)
     options.cmd_line_options = d
 
@@ -819,67 +989,63 @@
         # literal_eval to get it into the list of strings.
         options.native_file = ast.literal_eval(properties.get('native_file', '[]'))
 
-def cmd_line_options_to_string(options):
-    return {k: str(v) for k, v in options.cmd_line_options.items()}
-
-def write_cmd_line_file(build_dir, options):
+def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
     filename = get_cmd_line_file(build_dir)
     config = CmdLineFileParser()
 
-    properties = {}
+    properties = OrderedDict()
     if options.cross_file:
         properties['cross_file'] = options.cross_file
     if options.native_file:
         properties['native_file'] = options.native_file
 
-    config['options'] = cmd_line_options_to_string(options)
+    config['options'] = {str(k): str(v) for k, v in options.cmd_line_options.items()}
     config['properties'] = properties
-    with open(filename, 'w') as f:
+    with open(filename, 'w', encoding='utf-8') as f:
         config.write(f)
 
-def update_cmd_line_file(build_dir, options):
+def update_cmd_line_file(build_dir: str, options: argparse.Namespace):
     filename = get_cmd_line_file(build_dir)
     config = CmdLineFileParser()
     config.read(filename)
-    config['options'].update(cmd_line_options_to_string(options))
-    with open(filename, 'w') as f:
+    config['options'].update({str(k): str(v) for k, v in options.cmd_line_options.items()})
+    with open(filename, 'w', encoding='utf-8') as f:
         config.write(f)
 
-def get_cmd_line_options(build_dir, options):
-    copy = argparse.Namespace(**vars(options))
-    read_cmd_line_file(build_dir, copy)
-    cmdline = ['-D{}={}'.format(k, v) for k, v in copy.cmd_line_options.items()]
+def format_cmd_line_options(options: argparse.Namespace) -> str:
+    cmdline = ['-D{}={}'.format(str(k), v) for k, v in options.cmd_line_options.items()]
     if options.cross_file:
-        cmdline += ['--cross-file {}'.format(f) for f in options.cross_file]
+        cmdline += [f'--cross-file {f}' for f in options.cross_file]
     if options.native_file:
-        cmdline += ['--native-file {}'.format(f) for f in options.native_file]
+        cmdline += [f'--native-file {f}' for f in options.native_file]
     return ' '.join([shlex.quote(x) for x in cmdline])
 
-def major_versions_differ(v1, v2):
-    return v1.split('.')[0:2] != v2.split('.')[0:2]
+def major_versions_differ(v1: str, v2: str) -> bool:
+    v1_major, v1_minor = v1.rsplit('.', 1)
+    v2_major, v2_minor = v2.rsplit('.', 1)
+    # Major version differ, or one is development version but not the other.
+    return v1_major != v2_major or ('99' in {v1_minor, v2_minor} and v1_minor != v2_minor)
 
-def load(build_dir):
+def load(build_dir: str) -> CoreData:
     filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
-    load_fail_msg = 'Coredata file {!r} is corrupted. Try with a fresh build tree.'.format(filename)
+    load_fail_msg = f'Coredata file {filename!r} is corrupted. Try with a fresh build tree.'
     try:
         with open(filename, 'rb') as f:
             obj = pickle.load(f)
     except (pickle.UnpicklingError, EOFError):
         raise MesonException(load_fail_msg)
-    except AttributeError:
+    except (ModuleNotFoundError, AttributeError):
         raise MesonException(
-            "Coredata file {!r} references functions or classes that don't "
+            f"Coredata file {filename!r} references functions or classes that don't "
             "exist. This probably means that it was generated with an old "
-            "version of meson.".format(filename))
+            "version of meson.")
     if not isinstance(obj, CoreData):
         raise MesonException(load_fail_msg)
     if major_versions_differ(obj.version, version):
-        raise MesonException('Build directory has been generated with Meson version %s, '
-                             'which is incompatible with current version %s.\n' %
-                             (obj.version, version))
+        raise MesonVersionMismatchException(obj.version, version)
     return obj
 
-def save(obj, build_dir):
+def save(obj: CoreData, build_dir: str) -> str:
     filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
     prev_filename = filename + '.prev'
     tempfilename = filename + '~'
@@ -896,41 +1062,45 @@
     return filename
 
 
-def register_builtin_arguments(parser):
-    for n, b in builtin_options.items():
-        b.add_to_argparse(n, parser, '', '')
-    for n, b in builtin_options_per_machine.items():
-        b.add_to_argparse(n, parser, '', ' (just for host machine)')
-        b.add_to_argparse(n, parser, 'build.', ' (just for build machine)')
+def register_builtin_arguments(parser: argparse.ArgumentParser) -> None:
+    for n, b in BUILTIN_OPTIONS.items():
+        b.add_to_argparse(str(n), parser, '')
+    for n, b in BUILTIN_OPTIONS_PER_MACHINE.items():
+        b.add_to_argparse(str(n), parser, ' (just for host machine)')
+        b.add_to_argparse(str(n.as_build()), parser, ' (just for build machine)')
     parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option",
                         help='Set the value of an option, can be used several times to set multiple options.')
 
-def create_options_dict(options):
-    result = {}
+def create_options_dict(options: T.List[str], subproject: str = '') -> T.Dict[OptionKey, str]:
+    result: T.OrderedDict[OptionKey, str] = OrderedDict()
     for o in options:
         try:
             (key, value) = o.split('=', 1)
         except ValueError:
-            raise MesonException('Option {!r} must have a value separated by equals sign.'.format(o))
-        result[key] = value
+            raise MesonException(f'Option {o!r} must have a value separated by equals sign.')
+        k = OptionKey.from_string(key)
+        if subproject:
+            k = k.evolve(subproject=subproject)
+        result[k] = value
     return result
 
-def parse_cmd_line_options(args):
+def parse_cmd_line_options(args: argparse.Namespace) -> None:
     args.cmd_line_options = create_options_dict(args.projectoptions)
 
     # Merge builtin options set with --option into the dict.
-    for name in chain(
-            builtin_options.keys(),
-            ('build.' + k for k in builtin_options_per_machine.keys()),
-            builtin_options_per_machine.keys(),
+    for key in chain(
+            BUILTIN_OPTIONS.keys(),
+            (k.as_build() for k in BUILTIN_OPTIONS_PER_MACHINE.keys()),
+            BUILTIN_OPTIONS_PER_MACHINE.keys(),
     ):
+        name = str(key)
         value = getattr(args, name, None)
         if value is not None:
-            if name in args.cmd_line_options:
+            if key in args.cmd_line_options:
                 cmdline_name = BuiltinOption.argparse_name_to_arg(name)
                 raise MesonException(
-                    'Got argument {0} as both -D{0} and {1}. Pick one.'.format(name, cmdline_name))
-            args.cmd_line_options[name] = value
+                    f'Got argument {name} as both -D{name} and {cmdline_name}. Pick one.')
+            args.cmd_line_options[key] = value
             delattr(args, name)
 
 
@@ -940,10 +1110,10 @@
 
     """Class for a builtin option type.
 
-    Currently doesn't support UserIntegerOption, or a few other cases.
+    There are some cases that are not fully supported yet.
     """
 
-    def __init__(self, opt_type: T.Type[_U], description: str, default: T.Any, yielding: T.Optional[bool] = None, *,
+    def __init__(self, opt_type: T.Type[_U], description: str, default: T.Any, yielding: bool = True, *,
                  choices: T.Any = None):
         self.opt_type = opt_type
         self.description = description
@@ -951,17 +1121,20 @@
         self.choices = choices
         self.yielding = yielding
 
-    def init_option(self, name: str = 'prefix', prefix: str = '') -> _U:
+    def init_option(self, name: 'OptionKey', value: T.Optional[T.Any], prefix: str) -> _U:
         """Create an instance of opt_type and return it."""
-        keywords = {'yielding': self.yielding, 'value': self.prefixed_default(name, prefix)}
+        if value is None:
+            value = self.prefixed_default(name, prefix)
+        keywords = {'yielding': self.yielding, 'value': value}
         if self.choices:
             keywords['choices'] = self.choices
         return self.opt_type(self.description, **keywords)
 
     def _argparse_action(self) -> T.Optional[str]:
-        if self.default is True:
-            return 'store_false'
-        elif self.default is False:
+        # If the type is a boolean, the presence of the argument in --foo form
+        # is to enable it. Disabling happens by using -Dfoo=false, which is
+        # parsed under `args.projectoptions` and does not hit this codepath.
+        if isinstance(self.default, bool):
             return 'store_true'
         return None
 
@@ -979,17 +1152,17 @@
         else:
             return '--' + name.replace('_', '-')
 
-    def prefixed_default(self, name: str, prefix: str = '') -> T.Any:
+    def prefixed_default(self, name: 'OptionKey', prefix: str = '') -> T.Any:
         if self.opt_type in [UserComboOption, UserIntegerOption]:
             return self.default
         try:
-            return builtin_dir_noprefix_options[name][prefix]
+            return BULITIN_DIR_NOPREFIX_OPTIONS[name][prefix]
         except KeyError:
             pass
         return self.default
 
-    def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, prefix: str, help_suffix: str) -> None:
-        kwargs = {}
+    def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffix: str) -> None:
+        kwargs = OrderedDict()
 
         c = self._argparse_choices()
         b = self._argparse_action()
@@ -1001,60 +1174,76 @@
         if c and not b:
             kwargs['choices'] = c
         kwargs['default'] = argparse.SUPPRESS
-        kwargs['dest'] = prefix + name
+        kwargs['dest'] = name
 
-        cmdline_name = self.argparse_name_to_arg(prefix + name)
+        cmdline_name = self.argparse_name_to_arg(name)
         parser.add_argument(cmdline_name, help=h + help_suffix, **kwargs)
 
+
 # Update `docs/markdown/Builtin-options.md` after changing the options below
-builtin_options = OrderedDict([
-    # Directories
-    ('prefix',     BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())),
-    ('bindir',     BuiltinOption(UserStringOption, 'Executable directory', 'bin')),
-    ('datadir',    BuiltinOption(UserStringOption, 'Data file directory', 'share')),
-    ('includedir', BuiltinOption(UserStringOption, 'Header file directory', 'include')),
-    ('infodir',    BuiltinOption(UserStringOption, 'Info page directory', 'share/info')),
-    ('libdir',     BuiltinOption(UserStringOption, 'Library directory', default_libdir())),
-    ('libexecdir', BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())),
-    ('localedir',  BuiltinOption(UserStringOption, 'Locale data directory', 'share/locale')),
-    ('localstatedir',   BuiltinOption(UserStringOption, 'Localstate data directory', 'var')),
-    ('mandir',          BuiltinOption(UserStringOption, 'Manual page directory', 'share/man')),
-    ('sbindir',         BuiltinOption(UserStringOption, 'System executable directory', 'sbin')),
-    ('sharedstatedir',  BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')),
-    ('sysconfdir',      BuiltinOption(UserStringOption, 'Sysconf data directory', 'etc')),
-    # Core options
-    ('auto_features',   BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')),
-    ('backend',         BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist)),
-    ('buildtype',       BuiltinOption(UserComboOption, 'Build type to use', 'debug',
-                                      choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'])),
-    ('debug',           BuiltinOption(UserBooleanOption, 'Debug', True)),
-    ('default_library', BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'])),
-    ('errorlogs',       BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)),
-    ('install_umask',   BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')),
-    ('layout',          BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])),
-    ('optimization',    BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['0', 'g', '1', '2', '3', 's'])),
-    ('stdsplit',        BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)),
-    ('strip',           BuiltinOption(UserBooleanOption, 'Strip targets on install', False)),
-    ('unity',           BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])),
-    ('warning_level',   BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3'])),
-    ('werror',          BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False)),
-    ('wrap_mode',       BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback'])),
+# Also update mesonlib._BUILTIN_NAMES. See the comment there for why this is required.
+BUILTIN_DIR_OPTIONS: 'KeyedOptionDictType' = OrderedDict([
+    (OptionKey('prefix'),          BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())),
+    (OptionKey('bindir'),          BuiltinOption(UserStringOption, 'Executable directory', 'bin')),
+    (OptionKey('datadir'),         BuiltinOption(UserStringOption, 'Data file directory', 'share')),
+    (OptionKey('includedir'),      BuiltinOption(UserStringOption, 'Header file directory', 'include')),
+    (OptionKey('infodir'),         BuiltinOption(UserStringOption, 'Info page directory', 'share/info')),
+    (OptionKey('libdir'),          BuiltinOption(UserStringOption, 'Library directory', default_libdir())),
+    (OptionKey('libexecdir'),      BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())),
+    (OptionKey('localedir'),       BuiltinOption(UserStringOption, 'Locale data directory', 'share/locale')),
+    (OptionKey('localstatedir'),   BuiltinOption(UserStringOption, 'Localstate data directory', 'var')),
+    (OptionKey('mandir'),          BuiltinOption(UserStringOption, 'Manual page directory', 'share/man')),
+    (OptionKey('sbindir'),         BuiltinOption(UserStringOption, 'System executable directory', 'sbin')),
+    (OptionKey('sharedstatedir'),  BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')),
+    (OptionKey('sysconfdir'),      BuiltinOption(UserStringOption, 'Sysconf data directory', 'etc')),
 ])
 
-builtin_options_per_machine = OrderedDict([
-    ('pkg_config_path', BuiltinOption(UserArrayOption, 'T.List of additional paths for pkg-config to search', [])),
-    ('cmake_prefix_path', BuiltinOption(UserArrayOption, 'T.List of additional prefixes for cmake to search', [])),
+BUILTIN_CORE_OPTIONS: 'KeyedOptionDictType' = OrderedDict([
+    (OptionKey('auto_features'),   BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')),
+    (OptionKey('backend'),         BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist)),
+    (OptionKey('buildtype'),       BuiltinOption(UserComboOption, 'Build type to use', 'debug',
+                                                 choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'])),
+    (OptionKey('debug'),           BuiltinOption(UserBooleanOption, 'Debug', True)),
+    (OptionKey('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'],
+                                                 yielding=False)),
+    (OptionKey('errorlogs'),       BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)),
+    (OptionKey('install_umask'),   BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')),
+    (OptionKey('layout'),          BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])),
+    (OptionKey('optimization'),    BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['0', 'g', '1', '2', '3', 's'])),
+    (OptionKey('stdsplit'),        BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)),
+    (OptionKey('strip'),           BuiltinOption(UserBooleanOption, 'Strip targets on install', False)),
+    (OptionKey('unity'),           BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])),
+    (OptionKey('unity_size'),      BuiltinOption(UserIntegerOption, 'Unity block size', (2, None, 4))),
+    (OptionKey('warning_level'),   BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3'], yielding=False)),
+    (OptionKey('werror'),          BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)),
+    (OptionKey('wrap_mode'),       BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])),
+    (OptionKey('force_fallback_for'), BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])),
+
+    # Python module
+    (OptionKey('platlibdir', module='python'),
+     BuiltinOption(UserStringOption, 'Directory for site-specific, platform-specific files.', '')),
+    (OptionKey('purelibdir', module='python'),
+     BuiltinOption(UserStringOption, 'Directory for site-specific, non-platform-specific files.', '')),
+])
+
+BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items()))
+
+BUILTIN_OPTIONS_PER_MACHINE: 'KeyedOptionDictType' = OrderedDict([
+    (OptionKey('pkg_config_path'), BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])),
+    (OptionKey('cmake_prefix_path'), BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])),
 ])
 
 # Special prefix-dependent defaults for installation directories that reside in
 # a path outside of the prefix in FHS and common usage.
-builtin_dir_noprefix_options = {
-    'sysconfdir':     {'/usr': '/etc'},
-    'localstatedir':  {'/usr': '/var',     '/usr/local': '/var/local'},
-    'sharedstatedir': {'/usr': '/var/lib', '/usr/local': '/var/local/lib'},
+BULITIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = {
+    OptionKey('sysconfdir'):     {'/usr': '/etc'},
+    OptionKey('localstatedir'):  {'/usr': '/var',     '/usr/local': '/var/local'},
+    OptionKey('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'},
+    OptionKey('platlibdir', module='python'): {},
+    OptionKey('purelibdir', module='python'): {},
 }
 
-forbidden_target_names = {'clean': None,
+FORBIDDEN_TARGET_NAMES = {'clean': None,
                           'clean-ctlist': None,
                           'clean-gcno': None,
                           'clean-gcda': None,
diff -Nru meson-0.53.2/mesonbuild/dependencies/base.py meson-0.61.2/mesonbuild/dependencies/base.py
--- meson-0.53.2/mesonbuild/dependencies/base.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/base.py	2021-12-26 16:24:25.000000000 +0000
@@ -15,31 +15,22 @@
 # This file contains the detection logic for external dependencies.
 # Custom logic for several other packages are in separate files.
 import copy
-import functools
 import os
-import re
-import json
-import shlex
-import shutil
-import stat
-import textwrap
-import platform
+import itertools
 import typing as T
 from enum import Enum
-from pathlib import Path, PurePath
 
 from .. import mlog
-from .. import mesonlib
 from ..compilers import clib_langs
-from ..environment import BinaryTable, Environment, MachineInfo
-from ..cmake import CMakeExecutor, CMakeTraceParser, CMakeException
-from ..mesonlib import MachineChoice, MesonException, OrderedSet, PerMachine
-from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify, stringlistify, extract_as_list, split_args
-from ..mesonlib import Version, LibType
-
-# These must be defined in this file to avoid cyclical references.
-packages = {}
-_packages_accept_language = set()
+from ..mesonlib import LibType, MachineChoice, MesonException, HoldableObject
+from ..mesonlib import version_compare_many
+from ..interpreterbase import FeatureDeprecated
+
+if T.TYPE_CHECKING:
+    from ..compilers.compilers import Compiler
+    from ..environment import Environment
+    from ..build import BuildTarget, CustomTarget
+    from ..mesonlib import FileOrString
 
 
 class DependencyException(MesonException):
@@ -50,8 +41,9 @@
     # Auto means to use whatever dependency checking mechanisms in whatever order meson thinks is best.
     AUTO = 'auto'
     PKGCONFIG = 'pkg-config'
-    QMAKE = 'qmake'
     CMAKE = 'cmake'
+    # The dependency is provided by the standard library and does not need to be linked
+    BUILTIN = 'builtin'
     # Just specify the standard link arguments, assuming the operating system provides the library.
     SYSTEM = 'system'
     # This is only supported on OSX - search the frameworks directory by name.
@@ -65,46 +57,18 @@
     CUPSCONFIG = 'cups-config'
     PCAPCONFIG = 'pcap-config'
     LIBWMFCONFIG = 'libwmf-config'
+    QMAKE = 'qmake'
     # Misc
     DUB = 'dub'
 
 
-class Dependency:
-    @classmethod
-    def _process_method_kw(cls, kwargs):
-        method = kwargs.get('method', 'auto')
-        if isinstance(method, DependencyMethods):
-            return method
-        if method not in [e.value for e in DependencyMethods]:
-            raise DependencyException('method {!r} is invalid'.format(method))
-        method = DependencyMethods(method)
-
-        # This sets per-tool config methods which are deprecated to to the new
-        # generic CONFIG_TOOL value.
-        if method in [DependencyMethods.SDLCONFIG, DependencyMethods.CUPSCONFIG,
-                      DependencyMethods.PCAPCONFIG, DependencyMethods.LIBWMFCONFIG]:
-            mlog.warning(textwrap.dedent("""\
-                Configuration method {} has been deprecated in favor of
-                'config-tool'. This will be removed in a future version of
-                meson.""".format(method)))
-            method = DependencyMethods.CONFIG_TOOL
-
-        # Set the detection method. If the method is set to auto, use any available method.
-        # If method is set to a specific string, allow only that detection method.
-        if method == DependencyMethods.AUTO:
-            methods = cls.get_methods()
-        elif method in cls.get_methods():
-            methods = [method]
-        else:
-            raise DependencyException(
-                'Unsupported detection method: {}, allowed methods are {}'.format(
-                    method.value,
-                    mlog.format_list([x.value for x in [DependencyMethods.AUTO] + cls.get_methods()])))
+DependencyTypeName = T.NewType('DependencyTypeName', str)
+
 
-        return methods
+class Dependency(HoldableObject):
 
     @classmethod
-    def _process_include_type_kw(cls, kwargs) -> str:
+    def _process_include_type_kw(cls, kwargs: T.Dict[str, T.Any]) -> str:
         if 'include_type' not in kwargs:
             return 'preserve'
         if not isinstance(kwargs['include_type'], str):
@@ -113,27 +77,35 @@
             raise DependencyException("include_type may only be one of ['preserve', 'system', 'non-system']")
         return kwargs['include_type']
 
-    def __init__(self, type_name, kwargs):
+    def __init__(self, type_name: DependencyTypeName, kwargs: T.Dict[str, T.Any]) -> None:
         self.name = "null"
-        self.version = None
-        self.language = None # None means C-like
+        self.version:  T.Optional[str] = None
+        self.language: T.Optional[str] = None # None means C-like
         self.is_found = False
         self.type_name = type_name
-        self.compile_args = []
-        self.link_args = []
+        self.compile_args: T.List[str] = []
+        self.link_args:    T.List[str] = []
         # Raw -L and -l arguments without manual library searching
         # If None, self.link_args will be used
-        self.raw_link_args = None
-        self.sources = []
-        self.methods = self._process_method_kw(kwargs)
+        self.raw_link_args: T.Optional[T.List[str]] = None
+        self.sources: T.List[T.Union['FileOrString', 'CustomTarget']] = []
         self.include_type = self._process_include_type_kw(kwargs)
-        self.ext_deps = []  # type: T.List[Dependency]
+        self.ext_deps: T.List[Dependency] = []
 
-    def __repr__(self):
-        s = '<{0} {1}: {2}>'
-        return s.format(self.__class__.__name__, self.name, self.is_found)
+    def __repr__(self) -> str:
+        return f'<{self.__class__.__name__} {self.name}: {self.is_found}>'
+
+    def is_built(self) -> bool:
+        return False
 
-    def get_compile_args(self):
+    def summary_value(self) -> T.Union[str, mlog.AnsiDecorator, mlog.AnsiText]:
+        if not self.found():
+            return mlog.red('NO')
+        if not self.version:
+            return mlog.green('YES')
+        return mlog.AnsiText(mlog.green('YES'), ' ', mlog.cyan(self.version))
+
+    def get_compile_args(self) -> T.List[str]:
         if self.include_type == 'system':
             converted = []
             for i in self.compile_args:
@@ -152,27 +124,33 @@
             return converted
         return self.compile_args
 
-    def get_link_args(self, raw: bool = False) -> T.List[str]:
+    def get_all_compile_args(self) -> T.List[str]:
+        """Get the compile arguments from this dependency and it's sub dependencies."""
+        return list(itertools.chain(self.get_compile_args(),
+                                    *(d.get_all_compile_args() for d in self.ext_deps)))
+
+    def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
         if raw and self.raw_link_args is not None:
             return self.raw_link_args
         return self.link_args
 
-    def found(self):
+    def get_all_link_args(self) -> T.List[str]:
+        """Get the link arguments from this dependency and it's sub dependencies."""
+        return list(itertools.chain(self.get_link_args(),
+                                    *(d.get_all_link_args() for d in self.ext_deps)))
+
+    def found(self) -> bool:
         return self.is_found
 
-    def get_sources(self):
+    def get_sources(self) -> T.List[T.Union['FileOrString', 'CustomTarget']]:
         """Source files that need to be added to the target.
         As an example, gtest-all.cc when using GTest."""
         return self.sources
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.AUTO]
-
-    def get_name(self):
+    def get_name(self) -> str:
         return self.name
 
-    def get_version(self):
+    def get_version(self) -> str:
         if self.version:
             return self.version
         else:
@@ -181,18 +159,18 @@
     def get_include_type(self) -> str:
         return self.include_type
 
-    def get_exe_args(self, compiler):
+    def get_exe_args(self, compiler: 'Compiler') -> T.List[str]:
         return []
 
-    def get_pkgconfig_variable(self, variable_name, kwargs):
-        raise DependencyException('{!r} is not a pkgconfig dependency'.format(self.name))
+    def get_pkgconfig_variable(self, variable_name: str, kwargs: T.Dict[str, T.Any]) -> str:
+        raise DependencyException(f'{self.name!r} is not a pkgconfig dependency')
 
-    def get_configtool_variable(self, variable_name):
-        raise DependencyException('{!r} is not a config-tool dependency'.format(self.name))
+    def get_configtool_variable(self, variable_name: str) -> str:
+        raise DependencyException(f'{self.name!r} is not a config-tool dependency')
 
     def get_partial_dependency(self, *, compile_args: bool = False,
                                link_args: bool = False, links: bool = False,
-                               includes: bool = False, sources: bool = False):
+                               includes: bool = False, sources: bool = False) -> 'Dependency':
         """Create a new dependency that contains part of the parent dependency.
 
         The following options can be inherited:
@@ -208,35 +186,42 @@
         """
         raise RuntimeError('Unreachable code in partial_dependency called')
 
-    def _add_sub_dependency(self, dep_type: T.Type['Dependency'], env: Environment,
-                            kwargs: T.Dict[str, T.Any], *,
-                            method: DependencyMethods = DependencyMethods.AUTO) -> None:
-        """Add an internal dependency of of the given type.
-
-        This method is intended to simplify cases of adding a dependency on
-        another dependency type (such as threads). This will by default set
-        the method back to auto, but the 'method' keyword argument can be
-        used to overwrite this behavior.
+    def _add_sub_dependency(self, deplist: T.Iterable[T.Callable[[], 'Dependency']]) -> bool:
+        """Add an internal dependency from a list of possible dependencies.
+
+        This method is intended to make it easier to add additional
+        dependencies to another dependency internally.
+
+        Returns true if the dependency was successfully added, false
+        otherwise.
         """
-        kwargs = kwargs.copy()
-        kwargs['method'] = method
-        self.ext_deps.append(dep_type(env, kwargs))
+        for d in deplist:
+            dep = d()
+            if dep.is_found:
+                self.ext_deps.append(dep)
+                return True
+        return False
 
     def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
-                     configtool: T.Optional[str] = None, default_value: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
                      pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
         if default_value is not None:
             return default_value
-        raise DependencyException('No default provided for dependency {!r}, which is not pkg-config, cmake, or config-tool based.'.format(self))
+        raise DependencyException(f'No default provided for dependency {self!r}, which is not pkg-config, cmake, or config-tool based.')
 
-    def generate_system_dependency(self, include_type: str) -> T.Type['Dependency']:
+    def generate_system_dependency(self, include_type: str) -> 'Dependency':
         new_dep = copy.deepcopy(self)
         new_dep.include_type = self._process_include_type_kw({'include_type': include_type})
         return new_dep
 
 class InternalDependency(Dependency):
-    def __init__(self, version, incdirs, compile_args, link_args, libraries, whole_libraries, sources, ext_deps):
-        super().__init__('internal', {})
+    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'],
+                 sources: T.Sequence[T.Union['FileOrString', 'CustomTarget']],
+                 ext_deps: T.List[Dependency], variables: T.Dict[str, T.Any]):
+        super().__init__(DependencyTypeName('internal'), {})
         self.version = version
         self.is_found = True
         self.include_directories = incdirs
@@ -244,20 +229,42 @@
         self.link_args = link_args
         self.libraries = libraries
         self.whole_libraries = whole_libraries
-        self.sources = sources
+        self.sources = list(sources)
         self.ext_deps = ext_deps
+        self.variables = variables
+
+    def __deepcopy__(self, memo: T.Dict[int, 'InternalDependency']) -> 'InternalDependency':
+        result = self.__class__.__new__(self.__class__)
+        assert isinstance(result, InternalDependency)
+        memo[id(self)] = result
+        for k, v in self.__dict__.items():
+            if k in ['libraries', 'whole_libraries']:
+                setattr(result, k, copy.copy(v))
+            else:
+                setattr(result, k, copy.deepcopy(v, memo))
+        return result
 
-    def get_pkgconfig_variable(self, variable_name, kwargs):
+    def summary_value(self) -> mlog.AnsiDecorator:
+        # Omit the version.  Most of the time it will be just the project
+        # version, which is uninteresting in the summary.
+        return mlog.green('YES')
+
+    def is_built(self) -> bool:
+        if self.sources or self.libraries or self.whole_libraries:
+            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:
         raise DependencyException('Method "get_pkgconfig_variable()" is '
                                   'invalid for an internal dependency')
 
-    def get_configtool_variable(self, variable_name):
+    def get_configtool_variable(self, variable_name: str) -> str:
         raise DependencyException('Method "get_configtool_variable()" is '
                                   'invalid for an internal dependency')
 
     def get_partial_dependency(self, *, compile_args: bool = False,
                                link_args: bool = False, links: bool = False,
-                               includes: bool = False, sources: bool = False):
+                               includes: bool = False, sources: bool = False) -> 'InternalDependency':
         final_compile_args = self.compile_args.copy() if compile_args else []
         final_link_args = self.link_args.copy() if link_args else []
         final_libraries = self.libraries.copy() if links else []
@@ -270,17 +277,38 @@
         return InternalDependency(
             self.version, final_includes, final_compile_args,
             final_link_args, final_libraries, final_whole_libraries,
-            final_sources, final_deps)
+            final_sources, final_deps, self.variables)
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
+                     pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
+        val = self.variables.get(internal, default_value)
+        if val is not None:
+            # TODO: Try removing this assert by better typing self.variables
+            if isinstance(val, str):
+                return val
+            if isinstance(val, list):
+                for i in val:
+                    assert isinstance(i, str)
+                return val
+        raise DependencyException(f'Could not get an internal variable and no default provided for {self!r}')
+
+    def generate_link_whole_dependency(self) -> Dependency:
+        new_dep = copy.deepcopy(self)
+        new_dep.whole_libraries += new_dep.libraries
+        new_dep.libraries = []
+        return new_dep
 
 class HasNativeKwarg:
-    def __init__(self, kwargs):
+    def __init__(self, kwargs: T.Dict[str, T.Any]):
         self.for_machine = self.get_for_machine_from_kwargs(kwargs)
 
-    def get_for_machine_from_kwargs(self, kwargs):
+    def get_for_machine_from_kwargs(self, kwargs: T.Dict[str, T.Any]) -> MachineChoice:
         return MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST
 
 class ExternalDependency(Dependency, HasNativeKwarg):
-    def __init__(self, type_name, environment, language, kwargs):
+    def __init__(self, type_name: DependencyTypeName, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
         Dependency.__init__(self, type_name, kwargs)
         self.env = environment
         self.name = type_name # default
@@ -292,36 +320,19 @@
         self.required = kwargs.get('required', True)
         self.silent = kwargs.get('silent', False)
         self.static = kwargs.get('static', False)
+        self.libtype = LibType.STATIC if self.static else LibType.PREFER_SHARED
         if not isinstance(self.static, bool):
             raise DependencyException('Static keyword must be boolean')
         # Is this dependency to be run on the build platform?
         HasNativeKwarg.__init__(self, kwargs)
-        self.clib_compiler = None
-        # Set the compiler that will be used by this dependency
-        # This is only used for configuration checks
-        compilers = self.env.coredata.compilers[self.for_machine]
-        # Set the compiler for this dependency if a language is specified,
-        # else try to pick something that looks usable.
-        if self.language:
-            if self.language not in compilers:
-                m = self.name.capitalize() + ' requires a {0} compiler, but ' \
-                    '{0} is not in the list of project languages'
-                raise DependencyException(m.format(self.language.capitalize()))
-            self.clib_compiler = compilers[self.language]
-        else:
-            # Try to find a compiler that can find C libraries for
-            # running compiler.find_library()
-            for lang in clib_langs:
-                self.clib_compiler = compilers.get(lang, None)
-                if self.clib_compiler:
-                    break
+        self.clib_compiler = detect_compiler(self.name, environment, self.for_machine, self.language)
 
-    def get_compiler(self):
+    def get_compiler(self) -> 'Compiler':
         return self.clib_compiler
 
     def get_partial_dependency(self, *, compile_args: bool = False,
                                link_args: bool = False, links: bool = False,
-                               includes: bool = False, sources: bool = False):
+                               includes: bool = False, sources: bool = False) -> Dependency:
         new = copy.copy(self)
         if not compile_args:
             new.compile_args = []
@@ -330,37 +341,38 @@
         if not sources:
             new.sources = []
         if not includes:
-            new.include_directories = []
+            pass # TODO maybe filter compile_args?
         if not sources:
             new.sources = []
 
         return new
 
-    def log_details(self):
+    def log_details(self) -> str:
         return ''
 
-    def log_info(self):
+    def log_info(self) -> str:
         return ''
 
-    def log_tried(self):
+    def log_tried(self) -> str:
         return ''
 
     # Check if dependency version meets the requirements
-    def _check_version(self):
+    def _check_version(self) -> None:
         if not self.is_found:
             return
 
         if self.version_reqs:
             # an unknown version can never satisfy any requirement
             if not self.version:
-                found_msg = ['Dependency', mlog.bold(self.name), 'found:']
-                found_msg += [mlog.red('NO'), 'unknown version, but need:',
-                              self.version_reqs]
+                self.is_found = False
+                found_msg: mlog.TV_LoggableList = []
+                found_msg += ['Dependency', mlog.bold(self.name), 'found:']
+                found_msg += [mlog.red('NO'), 'unknown version, but need:', self.version_reqs]
                 mlog.log(*found_msg)
 
                 if self.required:
-                    m = 'Unknown version of dependency {!r}, but need {!r}.'
-                    raise DependencyException(m.format(self.name, self.version_reqs))
+                    m = f'Unknown version of dependency {self.name!r}, but need {self.version_reqs!r}.'
+                    raise DependencyException(m)
 
             else:
                 (self.is_found, not_found, found) = \
@@ -369,10 +381,10 @@
                     found_msg = ['Dependency', mlog.bold(self.name), 'found:']
                     found_msg += [mlog.red('NO'),
                                   'found', mlog.normal_cyan(self.version), 'but need:',
-                                  mlog.bold(', '.join(["'{}'".format(e) for e in not_found]))]
+                                  mlog.bold(', '.join([f"'{e}'" for e in not_found]))]
                     if found:
                         found_msg += ['; matched:',
-                                      ', '.join(["'{}'".format(e) for e in found])]
+                                      ', '.join([f"'{e}'" for e in found])]
                     mlog.log(*found_msg)
 
                     if self.required:
@@ -382,1655 +394,22 @@
 
 
 class NotFoundDependency(Dependency):
-    def __init__(self, environment):
-        super().__init__('not-found', {})
+    def __init__(self, name: str, environment: 'Environment') -> None:
+        super().__init__(DependencyTypeName('not-found'), {})
         self.env = environment
-        self.name = 'not-found'
+        self.name = name
         self.is_found = False
 
     def get_partial_dependency(self, *, compile_args: bool = False,
                                link_args: bool = False, links: bool = False,
-                               includes: bool = False, sources: bool = False):
+                               includes: bool = False, sources: bool = False) -> 'NotFoundDependency':
         return copy.copy(self)
 
 
-class ConfigToolDependency(ExternalDependency):
-
-    """Class representing dependencies found using a config tool."""
-
-    tools = None
-    tool_name = None
-    __strip_version = re.compile(r'^[0-9][0-9.]+')
-
-    def __init__(self, name, environment, language, kwargs):
-        super().__init__('config-tool', environment, language, kwargs)
-        self.name = name
-        self.tools = listify(kwargs.get('tools', self.tools))
-
-        req_version = kwargs.get('version', None)
-        tool, version = self.find_config(req_version)
-        self.config = tool
-        self.is_found = self.report_config(version, req_version)
-        if not self.is_found:
-            self.config = None
-            return
-        self.version = version
-        if getattr(self, 'finish_init', None):
-            self.finish_init(self)
-
-    def _sanitize_version(self, version):
-        """Remove any non-numeric, non-point version suffixes."""
-        m = self.__strip_version.match(version)
-        if m:
-            # Ensure that there isn't a trailing '.', such as an input like
-            # `1.2.3.git-1234`
-            return m.group(0).rstrip('.')
-        return version
-
-    @classmethod
-    def factory(cls, name, environment, language, kwargs, tools, tool_name, finish_init=None):
-        """Constructor for use in dependencies that can be found multiple ways.
-
-        In addition to the standard constructor values, this constructor sets
-        the tool_name and tools values of the instance.
-        """
-        # This deserves some explanation, because metaprogramming is hard.
-        # This uses type() to create a dynamic subclass of ConfigToolDependency
-        # with the tools and tool_name class attributes set, this class is then
-        # instantiated and returned. The reduce function (method) is also
-        # attached, since python's pickle module won't be able to do anything
-        # with this dynamically generated class otherwise.
-        def reduce(self):
-            return (cls._unpickle, (), self.__dict__)
-        sub = type('{}Dependency'.format(name.capitalize()), (cls, ),
-                   {'tools': tools, 'tool_name': tool_name, '__reduce__': reduce, 'finish_init': staticmethod(finish_init)})
-
-        return sub(name, environment, language, kwargs)
-
-    @classmethod
-    def _unpickle(cls):
-        return cls.__new__(cls)
-
-    def find_config(self, versions=None):
-        """Helper method that searches for config tool binaries in PATH and
-        returns the one that best matches the given version requirements.
-        """
-        if not isinstance(versions, list) and versions is not None:
-            versions = listify(versions)
-
-        tool = self.env.binaries[self.for_machine].lookup_entry(self.tool_name)
-        if tool is not None:
-            tools = [tool]
-        else:
-            if not self.env.machines.matches_build_machine(self.for_machine):
-                mlog.deprecation('No entry for {0} specified in your cross file. '
-                                 'Falling back to searching PATH. This may find a '
-                                 'native version of {0}! This will become a hard '
-                                 'error in a future version of meson'.format(self.tool_name))
-            tools = [[t] for t in self.tools]
-
-        best_match = (None, None)
-        for tool in tools:
-            if len(tool) == 1:
-                # In some situations the command can't be directly executed.
-                # For example Shell scripts need to be called through sh on
-                # Windows (see issue #1423).
-                potential_bin = ExternalProgram(tool[0], silent=True)
-                if not potential_bin.found():
-                    continue
-                tool = potential_bin.get_command()
-            try:
-                p, out = Popen_safe(tool + ['--version'])[:2]
-            except (FileNotFoundError, PermissionError):
-                continue
-            if p.returncode != 0:
-                continue
-
-            out = self._sanitize_version(out.strip())
-            # Some tools, like pcap-config don't supply a version, but also
-            # don't fail with --version, in that case just assume that there is
-            # only one version and return it.
-            if not out:
-                return (tool, None)
-            if versions:
-                is_found = version_compare_many(out, versions)[0]
-                # This allows returning a found version without a config tool,
-                # which is useful to inform the user that you found version x,
-                # but y was required.
-                if not is_found:
-                    tool = None
-            if best_match[1]:
-                if version_compare(out, '> {}'.format(best_match[1])):
-                    best_match = (tool, out)
-            else:
-                best_match = (tool, out)
-
-        return best_match
-
-    def report_config(self, version, req_version):
-        """Helper method to print messages about the tool."""
-
-        found_msg = [mlog.bold(self.tool_name), 'found:']
-
-        if self.config is None:
-            found_msg.append(mlog.red('NO'))
-            if version is not None and req_version is not None:
-                found_msg.append('found {!r} but need {!r}'.format(version, req_version))
-            elif req_version:
-                found_msg.append('need {!r}'.format(req_version))
-        else:
-            found_msg += [mlog.green('YES'), '({})'.format(' '.join(self.config)), version]
-
-        mlog.log(*found_msg)
-
-        return self.config is not None
-
-    def get_config_value(self, args, stage):
-        p, out, err = Popen_safe(self.config + args)
-        if p.returncode != 0:
-            if self.required:
-                raise DependencyException(
-                    'Could not generate {} for {}.\n{}'.format(
-                        stage, self.name, err))
-            return []
-        return split_args(out)
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.AUTO, DependencyMethods.CONFIG_TOOL]
-
-    def get_configtool_variable(self, variable_name):
-        p, out, _ = Popen_safe(self.config + ['--{}'.format(variable_name)])
-        if p.returncode != 0:
-            if self.required:
-                raise DependencyException(
-                    'Could not get variable "{}" for dependency {}'.format(
-                        variable_name, self.name))
-        variable = out.strip()
-        mlog.debug('Got config-tool variable {} : {}'.format(variable_name, variable))
-        return variable
-
-    def log_tried(self):
-        return self.type_name
-
-    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
-                     configtool: T.Optional[str] = None, default_value: T.Optional[str] = None,
-                     pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
-        if configtool:
-            # In the not required case '' (empty string) will be returned if the
-            # variable is not found. Since '' is a valid value to return we
-            # set required to True here to force and error, and use the
-            # finally clause to ensure it's restored.
-            restore = self.required
-            self.required = True
-            try:
-                return self.get_configtool_variable(configtool)
-            except DependencyException:
-                pass
-            finally:
-                self.required = restore
-        if default_value is not None:
-            return default_value
-        raise DependencyException('Could not get config-tool variable and no default provided for {!r}'.format(self))
-
-
-class PkgConfigDependency(ExternalDependency):
-    # The class's copy of the pkg-config path. Avoids having to search for it
-    # multiple times in the same Meson invocation.
-    class_pkgbin = PerMachine(None, None)
-    # We cache all pkg-config subprocess invocations to avoid redundant calls
-    pkgbin_cache = {}
-
-    def __init__(self, name, environment, kwargs, language=None):
-        super().__init__('pkgconfig', environment, language, kwargs)
-        self.name = name
-        self.is_libtool = False
-        # Store a copy of the pkg-config path on the object itself so it is
-        # stored in the pickled coredata and recovered.
-        self.pkgbin = None
-
-        # Create an iterator of options
-        def search():
-            # Lookup in cross or machine file.
-            potential_pkgpath = environment.binaries[self.for_machine].lookup_entry('pkgconfig')
-            if potential_pkgpath is not None:
-                mlog.debug('Pkg-config binary for {} specified from cross file, native file, '
-                           'or env var as {}'.format(self.for_machine, potential_pkgpath))
-                yield ExternalProgram.from_entry('pkgconfig', potential_pkgpath)
-                # We never fallback if the user-specified option is no good, so
-                # stop returning options.
-                return
-            mlog.debug('Pkg-config binary missing from cross or native file, or env var undefined.')
-            # Fallback on hard-coded defaults.
-            # TODO prefix this for the cross case instead of ignoring thing.
-            if environment.machines.matches_build_machine(self.for_machine):
-                for potential_pkgpath in environment.default_pkgconfig:
-                    mlog.debug('Trying a default pkg-config fallback at', potential_pkgpath)
-                    yield ExternalProgram(potential_pkgpath, silent=True)
-
-        # Only search for pkg-config for each machine the first time and store
-        # the result in the class definition
-        if PkgConfigDependency.class_pkgbin[self.for_machine] is False:
-            mlog.debug('Pkg-config binary for %s is cached as not found.' % self.for_machine)
-        elif PkgConfigDependency.class_pkgbin[self.for_machine] is not None:
-            mlog.debug('Pkg-config binary for %s is cached.' % self.for_machine)
-        else:
-            assert PkgConfigDependency.class_pkgbin[self.for_machine] is None
-            mlog.debug('Pkg-config binary for %s is not cached.' % self.for_machine)
-            for potential_pkgbin in search():
-                mlog.debug('Trying pkg-config binary {} for machine {} at {}'
-                           .format(potential_pkgbin.name, self.for_machine, potential_pkgbin.command))
-                version_if_ok = self.check_pkgconfig(potential_pkgbin)
-                if not version_if_ok:
-                    continue
-                if not self.silent:
-                    mlog.log('Found pkg-config:', mlog.bold(potential_pkgbin.get_path()),
-                             '(%s)' % version_if_ok)
-                PkgConfigDependency.class_pkgbin[self.for_machine] = potential_pkgbin
-                break
-            else:
-                if not self.silent:
-                    mlog.log('Found Pkg-config:', mlog.red('NO'))
-                # Set to False instead of None to signify that we've already
-                # searched for it and not found it
-                PkgConfigDependency.class_pkgbin[self.for_machine] = False
-
-        self.pkgbin = PkgConfigDependency.class_pkgbin[self.for_machine]
-        if self.pkgbin is False:
-            self.pkgbin = None
-            msg = 'Pkg-config binary for machine %s not found. Giving up.' % self.for_machine
-            if self.required:
-                raise DependencyException(msg)
-            else:
-                mlog.debug(msg)
-                return
-
-        mlog.debug('Determining dependency {!r} with pkg-config executable '
-                   '{!r}'.format(name, self.pkgbin.get_path()))
-        ret, self.version, _ = self._call_pkgbin(['--modversion', name])
-        if ret != 0:
-            return
-
-        self.is_found = True
-
-        try:
-            # Fetch cargs to be used while using this dependency
-            self._set_cargs()
-            # Fetch the libraries and library paths needed for using this
-            self._set_libs()
-        except DependencyException as e:
-            mlog.debug("pkg-config error with '%s': %s" % (name, e))
-            if self.required:
-                raise
-            else:
-                self.compile_args = []
-                self.link_args = []
-                self.is_found = False
-                self.reason = e
-
-    def __repr__(self):
-        s = '<{0} {1}: {2} {3}>'
-        return s.format(self.__class__.__name__, self.name, self.is_found,
-                        self.version_reqs)
-
-    def _call_pkgbin_real(self, args, env):
-        cmd = self.pkgbin.get_command() + args
-        p, out, err = Popen_safe(cmd, env=env)
-        rc, out, err = p.returncode, out.strip(), err.strip()
-        call = ' '.join(cmd)
-        mlog.debug("Called `{}` -> {}\n{}".format(call, rc, out))
-        return rc, out, err
-
-    def _call_pkgbin(self, args, env=None):
-        # Always copy the environment since we're going to modify it
-        # with pkg-config variables
-        if env is None:
-            env = os.environ.copy()
-        else:
-            env = env.copy()
-
-        extra_paths = self.env.coredata.builtins_per_machine[self.for_machine]['pkg_config_path'].value
-        sysroot = self.env.properties[self.for_machine].get_sys_root()
-        if sysroot:
-            env['PKG_CONFIG_SYSROOT_DIR'] = sysroot
-        new_pkg_config_path = ':'.join([p for p in extra_paths])
-        mlog.debug('PKG_CONFIG_PATH: ' + new_pkg_config_path)
-        env['PKG_CONFIG_PATH'] = new_pkg_config_path
-
-        fenv = frozenset(env.items())
-        targs = tuple(args)
-        cache = PkgConfigDependency.pkgbin_cache
-        if (self.pkgbin, targs, fenv) not in cache:
-            cache[(self.pkgbin, targs, fenv)] = self._call_pkgbin_real(args, env)
-        return cache[(self.pkgbin, targs, fenv)]
-
-    def _convert_mingw_paths(self, args: T.List[str]) -> T.List[str]:
-        '''
-        Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo
-        paths so convert them to C:/foo. We cannot resolve other paths starting
-        with / like /home/foo so leave them as-is so that the user gets an
-        error/warning from the compiler/linker.
-        '''
-        if not mesonlib.is_windows():
-            return args
-        converted = []
-        for arg in args:
-            pargs = []
-            # Library search path
-            if arg.startswith('-L/'):
-                pargs = PurePath(arg[2:]).parts
-                tmpl = '-L{}:/{}'
-            elif arg.startswith('-I/'):
-                pargs = PurePath(arg[2:]).parts
-                tmpl = '-I{}:/{}'
-            # Full path to library or .la file
-            elif arg.startswith('/'):
-                pargs = PurePath(arg).parts
-                tmpl = '{}:/{}'
-            elif arg.startswith(('-L', '-I')) or (len(arg) > 2 and arg[1] == ':'):
-                # clean out improper '\\ ' as comes from some Windows pkg-config files
-                arg = arg.replace('\\ ', ' ')
-            if len(pargs) > 1 and len(pargs[1]) == 1:
-                arg = tmpl.format(pargs[1], '/'.join(pargs[2:]))
-            converted.append(arg)
-        return converted
-
-    def _split_args(self, cmd):
-        # pkg-config paths follow Unix conventions, even on Windows; split the
-        # output using shlex.split rather than mesonlib.split_args
-        return shlex.split(cmd)
-
-    def _set_cargs(self):
-        env = None
-        if self.language == 'fortran':
-            # gfortran doesn't appear to look in system paths for INCLUDE files,
-            # so don't allow pkg-config to suppress -I flags for system paths
-            env = os.environ.copy()
-            env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1'
-        ret, out, err = self._call_pkgbin(['--cflags', self.name], env=env)
-        if ret != 0:
-            raise DependencyException('Could not generate cargs for %s:\n%s\n' %
-                                      (self.name, err))
-        self.compile_args = self._convert_mingw_paths(self._split_args(out))
-
-    def _search_libs(self, out, out_raw):
-        '''
-        @out: PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs
-        @out_raw: pkg-config --libs
-
-        We always look for the file ourselves instead of depending on the
-        compiler to find it with -lfoo or foo.lib (if possible) because:
-        1. We want to be able to select static or shared
-        2. We need the full path of the library to calculate RPATH values
-        3. De-dup of libraries is easier when we have absolute paths
-
-        Libraries that are provided by the toolchain or are not found by
-        find_library() will be added with -L -l pairs.
-        '''
-        # Library paths should be safe to de-dup
-        #
-        # First, figure out what library paths to use. Originally, we were
-        # doing this as part of the loop, but due to differences in the order
-        # of -L values between pkg-config and pkgconf, we need to do that as
-        # a separate step. See:
-        # https://github.com/mesonbuild/meson/issues/3951
-        # https://github.com/mesonbuild/meson/issues/4023
-        #
-        # Separate system and prefix paths, and ensure that prefix paths are
-        # always searched first.
-        prefix_libpaths = OrderedSet()
-        # We also store this raw_link_args on the object later
-        raw_link_args = self._convert_mingw_paths(self._split_args(out_raw))
-        for arg in raw_link_args:
-            if arg.startswith('-L') and not arg.startswith(('-L-l', '-L-L')):
-                path = arg[2:]
-                if not os.path.isabs(path):
-                    # Resolve the path as a compiler in the build directory would
-                    path = os.path.join(self.env.get_build_dir(), path)
-                prefix_libpaths.add(path)
-        # Library paths are not always ordered in a meaningful way
-        #
-        # Instead of relying on pkg-config or pkgconf to provide -L flags in a
-        # specific order, we reorder library paths ourselves, according to th
-        # order specified in PKG_CONFIG_PATH. See:
-        # https://github.com/mesonbuild/meson/issues/4271
-        #
-        # Only prefix_libpaths are reordered here because there should not be
-        # too many system_libpaths to cause library version issues.
-        pkg_config_path = os.environ.get('PKG_CONFIG_PATH')
-        if pkg_config_path:
-            pkg_config_path = pkg_config_path.split(os.pathsep)
-        else:
-            pkg_config_path = []
-        pkg_config_path = self._convert_mingw_paths(pkg_config_path)
-        prefix_libpaths = sort_libpaths(prefix_libpaths, pkg_config_path)
-        system_libpaths = OrderedSet()
-        full_args = self._convert_mingw_paths(self._split_args(out))
-        for arg in full_args:
-            if arg.startswith(('-L-l', '-L-L')):
-                # These are D language arguments, not library paths
-                continue
-            if arg.startswith('-L') and arg[2:] not in prefix_libpaths:
-                system_libpaths.add(arg[2:])
-        # Use this re-ordered path list for library resolution
-        libpaths = list(prefix_libpaths) + list(system_libpaths)
-        # Track -lfoo libraries to avoid duplicate work
-        libs_found = OrderedSet()
-        # Track not-found libraries to know whether to add library paths
-        libs_notfound = []
-        libtype = LibType.STATIC if self.static else LibType.PREFER_SHARED
-        # Generate link arguments for this library
-        link_args = []
-        for lib in full_args:
-            if lib.startswith(('-L-l', '-L-L')):
-                # These are D language arguments, add them as-is
-                pass
-            elif lib.startswith('-L'):
-                # We already handled library paths above
-                continue
-            elif lib.startswith('-l'):
-                # Don't resolve the same -lfoo argument again
-                if lib in libs_found:
-                    continue
-                if self.clib_compiler:
-                    args = self.clib_compiler.find_library(lib[2:], self.env,
-                                                           libpaths, libtype)
-                # If the project only uses a non-clib language such as D, Rust,
-                # C#, Python, etc, all we can do is limp along by adding the
-                # arguments as-is and then adding the libpaths at the end.
-                else:
-                    args = None
-                if args is not None:
-                    libs_found.add(lib)
-                    # Replace -l arg with full path to library if available
-                    # else, library is either to be ignored, or is provided by
-                    # the compiler, can't be resolved, and should be used as-is
-                    if args:
-                        if not args[0].startswith('-l'):
-                            lib = args[0]
-                    else:
-                        continue
-                else:
-                    # Library wasn't found, maybe we're looking in the wrong
-                    # places or the library will be provided with LDFLAGS or
-                    # LIBRARY_PATH from the environment (on macOS), and many
-                    # other edge cases that we can't account for.
-                    #
-                    # Add all -L paths and use it as -lfoo
-                    if lib in libs_notfound:
-                        continue
-                    if self.static:
-                        mlog.warning('Static library {!r} not found for dependency {!r}, may '
-                                     'not be statically linked'.format(lib[2:], self.name))
-                    libs_notfound.append(lib)
-            elif lib.endswith(".la"):
-                shared_libname = self.extract_libtool_shlib(lib)
-                shared_lib = os.path.join(os.path.dirname(lib), shared_libname)
-                if not os.path.exists(shared_lib):
-                    shared_lib = os.path.join(os.path.dirname(lib), ".libs", shared_libname)
-
-                if not os.path.exists(shared_lib):
-                    raise DependencyException('Got a libtools specific "%s" dependencies'
-                                              'but we could not compute the actual shared'
-                                              'library path' % lib)
-                self.is_libtool = True
-                lib = shared_lib
-                if lib in link_args:
-                    continue
-            link_args.append(lib)
-        # Add all -Lbar args if we have -lfoo args in link_args
-        if libs_notfound:
-            # Order of -L flags doesn't matter with ld, but it might with other
-            # linkers such as MSVC, so prepend them.
-            link_args = ['-L' + lp for lp in prefix_libpaths] + link_args
-        return link_args, raw_link_args
-
-    def _set_libs(self):
-        env = None
-        libcmd = [self.name, '--libs']
-        if self.static:
-            libcmd.append('--static')
-        # Force pkg-config to output -L fields even if they are system
-        # paths so we can do manual searching with cc.find_library() later.
-        env = os.environ.copy()
-        env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1'
-        ret, out, err = self._call_pkgbin(libcmd, env=env)
-        if ret != 0:
-            raise DependencyException('Could not generate libs for %s:\n%s\n' %
-                                      (self.name, err))
-        # Also get the 'raw' output without -Lfoo system paths for adding -L
-        # args with -lfoo when a library can't be found, and also in
-        # gnome.generate_gir + gnome.gtkdoc which need -L -l arguments.
-        ret, out_raw, err_raw = self._call_pkgbin(libcmd)
-        if ret != 0:
-            raise DependencyException('Could not generate libs for %s:\n\n%s' %
-                                      (self.name, out_raw))
-        self.link_args, self.raw_link_args = self._search_libs(out, out_raw)
-
-    def get_pkgconfig_variable(self, variable_name, kwargs):
-        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
-
-        ret, out, err = self._call_pkgbin(options)
-        variable = ''
-        if ret != 0:
-            if self.required:
-                raise DependencyException('dependency %s not found:\n%s\n' %
-                                          (self.name, err))
-        else:
-            variable = out.strip()
-
-            # pkg-config doesn't distinguish between empty and non-existent variables
-            # use the variable list to check for variable existence
-            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:
-                        variable = kwargs['default']
-                    else:
-                        mlog.warning("pkgconfig variable '%s' not defined for dependency %s." % (variable_name, self.name))
-
-        mlog.debug('Got pkgconfig variable %s : %s' % (variable_name, variable))
-        return variable
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG]
-
-    def check_pkgconfig(self, pkgbin):
-        if not pkgbin.found():
-            mlog.log('Did not find pkg-config by name {!r}'.format(pkgbin.name))
-            return None
-        try:
-            p, out = Popen_safe(pkgbin.get_command() + ['--version'])[0:2]
-            if p.returncode != 0:
-                mlog.warning('Found pkg-config {!r} but it failed when run'
-                             ''.format(' '.join(pkgbin.get_command())))
-                return None
-        except FileNotFoundError:
-            mlog.warning('We thought we found pkg-config {!r} but now it\'s not there. How odd!'
-                         ''.format(' '.join(pkgbin.get_command())))
-            return None
-        except PermissionError:
-            msg = 'Found pkg-config {!r} but didn\'t have permissions to run it.'.format(' '.join(pkgbin.get_command()))
-            if not mesonlib.is_windows():
-                msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.'
-            mlog.warning(msg)
-            return None
-        return out.strip()
-
-    def extract_field(self, la_file, fieldname):
-        with open(la_file) as f:
-            for line in f:
-                arr = line.strip().split('=')
-                if arr[0] == fieldname:
-                    return arr[1][1:-1]
-        return None
-
-    def extract_dlname_field(self, la_file):
-        return self.extract_field(la_file, 'dlname')
-
-    def extract_libdir_field(self, la_file):
-        return self.extract_field(la_file, 'libdir')
-
-    def extract_libtool_shlib(self, la_file):
-        '''
-        Returns the path to the shared library
-        corresponding to this .la file
-        '''
-        dlname = self.extract_dlname_field(la_file)
-        if dlname is None:
-            return None
-
-        # Darwin uses absolute paths where possible; since the libtool files never
-        # contain absolute paths, use the libdir field
-        if mesonlib.is_osx():
-            dlbasename = os.path.basename(dlname)
-            libdir = self.extract_libdir_field(la_file)
-            if libdir is None:
-                return dlbasename
-            return os.path.join(libdir, dlbasename)
-        # From the comments in extract_libtool(), older libtools had
-        # a path rather than the raw dlname
-        return os.path.basename(dlname)
-
-    def log_tried(self):
-        return self.type_name
-
-    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
-                     configtool: T.Optional[str] = None, default_value: T.Optional[str] = None,
-                     pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
-        if pkgconfig:
-            kwargs = {}
-            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)
-            except DependencyException:
-                pass
-        if default_value is not None:
-            return default_value
-        raise DependencyException('Could not get pkg-config variable and no default provided for {!r}'.format(self))
-
-class CMakeDependency(ExternalDependency):
-    # The class's copy of the CMake path. Avoids having to search for it
-    # multiple times in the same Meson invocation.
-    class_cmakeinfo = PerMachine(None, None)
-    # Version string for the minimum CMake version
-    class_cmake_version = '>=3.4'
-    # CMake generators to try (empty for no generator)
-    class_cmake_generators = ['', 'Ninja', 'Unix Makefiles', 'Visual Studio 10 2010']
-    class_working_generator = None
-
-    def _gen_exception(self, msg):
-        return DependencyException('Dependency {} not found: {}'.format(self.name, msg))
-
-    def _main_cmake_file(self) -> str:
-        return 'CMakeLists.txt'
-
-    def _extra_cmake_opts(self) -> T.List[str]:
-        return []
-
-    def _map_module_list(self, modules: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
-        # Map the input module list to something else
-        # This function will only be executed AFTER the initial CMake
-        # interpreter pass has completed. Thus variables defined in the
-        # CMakeLists.txt can be accessed here.
-        return modules
-
-    def _original_module_name(self, module: str) -> str:
-        # Reverse the module mapping done by _map_module_list for
-        # one module
-        return module
-
-    def __init__(self, name: str, environment: Environment, kwargs, language: str = None):
-        # Gather a list of all languages to support
-        self.language_list = []  # type: T.List[str]
-        if language is None:
-            compilers = None
-            if kwargs.get('native', False):
-                compilers = environment.coredata.compilers.build
-            else:
-                compilers = environment.coredata.compilers.host
-
-            candidates = ['c', 'cpp', 'fortran', 'objc', 'objcxx']
-            self.language_list += [x for x in candidates if x in compilers]
-        else:
-            self.language_list += [language]
-
-        # Add additional languages if required
-        if 'fortran' in self.language_list:
-            self.language_list += ['c']
-
-        # Ensure that the list is unique
-        self.language_list = list(set(self.language_list))
-
-        super().__init__('cmake', environment, language, kwargs)
-        self.name = name
-        self.is_libtool = False
-        # Store a copy of the CMake path on the object itself so it is
-        # stored in the pickled coredata and recovered.
-        self.cmakebin = None
-        self.cmakeinfo = None
-        self.traceparser = CMakeTraceParser()
-
-        # Where all CMake "build dirs" are located
-        self.cmake_root_dir = environment.scratch_dir
-
-        # T.List of successfully found modules
-        self.found_modules = []
-
-        self.cmakebin = CMakeExecutor(environment, CMakeDependency.class_cmake_version, self.for_machine, silent=self.silent)
-        if not self.cmakebin.found():
-            self.cmakebin = None
-            msg = 'No CMake binary for machine %s not found. Giving up.' % self.for_machine
-            if self.required:
-                raise DependencyException(msg)
-            mlog.debug(msg)
-            return
-
-        if CMakeDependency.class_cmakeinfo[self.for_machine] is None:
-            CMakeDependency.class_cmakeinfo[self.for_machine] = self._get_cmake_info()
-        self.cmakeinfo = CMakeDependency.class_cmakeinfo[self.for_machine]
-        if self.cmakeinfo is None:
-            raise self._gen_exception('Unable to obtain CMake system information')
-
-        modules = [(x, True) for x in stringlistify(extract_as_list(kwargs, 'modules'))]
-        modules += [(x, False) for x in stringlistify(extract_as_list(kwargs, 'optional_modules'))]
-        cm_path = stringlistify(extract_as_list(kwargs, 'cmake_module_path'))
-        cm_path = [x if os.path.isabs(x) else os.path.join(environment.get_source_dir(), x) for x in cm_path]
-        cm_args = stringlistify(extract_as_list(kwargs, 'cmake_args'))
-        if cm_path:
-            cm_args.append('-DCMAKE_MODULE_PATH=' + ';'.join(cm_path))
-
-        pref_path = self.env.coredata.builtins_per_machine[self.for_machine]['cmake_prefix_path'].value
-        if 'CMAKE_PREFIX_PATH' in os.environ:
-            env_pref_path = os.environ['CMAKE_PREFIX_PATH'].split(os.pathsep)
-            env_pref_path = [x for x in env_pref_path if x]  # Filter out empty strings
-            if not pref_path:
-                pref_path = []
-            pref_path += env_pref_path
-        if pref_path:
-            cm_args.append('-DCMAKE_PREFIX_PATH={}'.format(';'.join(pref_path)))
-
-        if not self._preliminary_find_check(name, cm_path, pref_path, environment.machines[self.for_machine]):
-            mlog.debug('Preliminary CMake check failed. Aborting.')
-            return
-        self._detect_dep(name, modules, cm_args)
-
-    def __repr__(self):
-        s = '<{0} {1}: {2} {3}>'
-        return s.format(self.__class__.__name__, self.name, self.is_found,
-                        self.version_reqs)
-
-    def _get_cmake_info(self):
-        mlog.debug("Extracting basic cmake information")
-        res = {}
-
-        # Try different CMake generators since specifying no generator may fail
-        # in cygwin for some reason
-        gen_list = []
-        # First try the last working generator
-        if CMakeDependency.class_working_generator is not None:
-            gen_list += [CMakeDependency.class_working_generator]
-        gen_list += CMakeDependency.class_cmake_generators
-
-        for i in gen_list:
-            mlog.debug('Try CMake generator: {}'.format(i if len(i) > 0 else 'auto'))
-
-            # Prepare options
-            cmake_opts = ['--trace-expand', '.']
-            if len(i) > 0:
-                cmake_opts = ['-G', i] + cmake_opts
-
-            # Run CMake
-            ret1, out1, err1 = self._call_cmake(cmake_opts, 'CMakePathInfo.txt')
-
-            # Current generator was successful
-            if ret1 == 0:
-                CMakeDependency.class_working_generator = i
-                break
-
-            mlog.debug('CMake failed to gather system information for generator {} with error code {}'.format(i, ret1))
-            mlog.debug('OUT:\n{}\n\n\nERR:\n{}\n\n'.format(out1, err1))
-
-        # Check if any generator succeeded
-        if ret1 != 0:
-            return None
-
-        try:
-            temp_parser = CMakeTraceParser()
-            temp_parser.parse(err1)
-        except MesonException:
-            return None
-
-        # Extract the variables and sanity check them
-        root_paths = set(temp_parser.get_cmake_var('MESON_FIND_ROOT_PATH'))
-        root_paths.update(set(temp_parser.get_cmake_var('MESON_CMAKE_SYSROOT')))
-        root_paths = sorted(root_paths)
-        root_paths = list(filter(lambda x: os.path.isdir(x), root_paths))
-        module_paths = set(temp_parser.get_cmake_var('MESON_PATHS_LIST'))
-        rooted_paths = []
-        for j in [Path(x) for x in root_paths]:
-            for i in [Path(x) for x in module_paths]:
-                rooted_paths.append(str(j / i.relative_to(i.anchor)))
-        module_paths = sorted(module_paths.union(rooted_paths))
-        module_paths = list(filter(lambda x: os.path.isdir(x), module_paths))
-        archs = temp_parser.get_cmake_var('MESON_ARCH_LIST')
-
-        common_paths = ['lib', 'lib32', 'lib64', 'libx32', 'share']
-        for i in archs:
-            common_paths += [os.path.join('lib', i)]
-
-        res = {
-            'module_paths': module_paths,
-            'cmake_root': temp_parser.get_cmake_var('MESON_CMAKE_ROOT')[0],
-            'archs': archs,
-            'common_paths': common_paths
-        }
-
-        mlog.debug('  -- Module search paths:    {}'.format(res['module_paths']))
-        mlog.debug('  -- CMake root:             {}'.format(res['cmake_root']))
-        mlog.debug('  -- CMake architectures:    {}'.format(res['archs']))
-        mlog.debug('  -- CMake lib search paths: {}'.format(res['common_paths']))
-
-        return res
-
-    @staticmethod
-    @functools.lru_cache(maxsize=None)
-    def _cached_listdir(path: str) -> T.Tuple[T.Tuple[str, str]]:
-        try:
-            return tuple((x, str(x).lower()) for x in os.listdir(path))
-        except OSError:
-            return ()
-
-    @staticmethod
-    @functools.lru_cache(maxsize=None)
-    def _cached_isdir(path: str) -> bool:
-        try:
-            return os.path.isdir(path)
-        except OSError:
-            return False
-
-    def _preliminary_find_check(self, name: str, module_path: T.List[str], prefix_path: T.List[str], machine: MachineInfo) -> bool:
-        lname = str(name).lower()
-
-        # Checks , /cmake, /CMake
-        def find_module(path: str) -> bool:
-            for i in [path, os.path.join(path, 'cmake'), os.path.join(path, 'CMake')]:
-                if not self._cached_isdir(i):
-                    continue
-
-                # Check the directory case insensitve
-                content = self._cached_listdir(i)
-                candidates = ['Find{}.cmake', '{}Config.cmake', '{}-config.cmake']
-                candidates = [x.format(name).lower() for x in candidates]
-                if any([x[1] in candidates for x in content]):
-                    return True
-            return False
-
-        # Search in /(lib/|lib*|share) for cmake files
-        def search_lib_dirs(path: str) -> bool:
-            for i in [os.path.join(path, x) for x in self.cmakeinfo['common_paths']]:
-                if not self._cached_isdir(i):
-                    continue
-
-                # Check /(lib/|lib*|share)/cmake/*/
-                cm_dir = os.path.join(i, 'cmake')
-                if self._cached_isdir(cm_dir):
-                    content = self._cached_listdir(cm_dir)
-                    content = list(filter(lambda x: x[1].startswith(lname), content))
-                    for k in content:
-                        if find_module(os.path.join(cm_dir, k[0])):
-                            return True
-
-                # /(lib/|lib*|share)/*/
-                # /(lib/|lib*|share)/*/(cmake|CMake)/
-                content = self._cached_listdir(i)
-                content = list(filter(lambda x: x[1].startswith(lname), content))
-                for k in content:
-                    if find_module(os.path.join(i, k[0])):
-                        return True
-
-            return False
-
-        # Check the user provided and system module paths
-        for i in module_path + [os.path.join(self.cmakeinfo['cmake_root'], 'Modules')]:
-            if find_module(i):
-                return True
-
-        # Check the user provided prefix paths
-        for i in prefix_path:
-            if search_lib_dirs(i):
-                return True
-
-        # Check the system paths
-        for i in self.cmakeinfo['module_paths']:
-            if find_module(i):
-                return True
-
-            if search_lib_dirs(i):
-                return True
-
-            content = self._cached_listdir(i)
-            content = list(filter(lambda x: x[1].startswith(lname), content))
-            for k in content:
-                if search_lib_dirs(os.path.join(i, k[0])):
-                    return True
-
-            # Mac framework support
-            if machine.is_darwin():
-                for j in ['{}.framework', '{}.app']:
-                    j = j.format(lname)
-                    if j in content:
-                        if find_module(os.path.join(i, j[0], 'Resources')) or find_module(os.path.join(i, j[0], 'Version')):
-                            return True
-
-        # Check the environment path
-        env_path = os.environ.get('{}_DIR'.format(name))
-        if env_path and find_module(env_path):
-            return True
-
-        return False
-
-    def _detect_dep(self, name: str, modules: T.List[T.Tuple[str, bool]], args: T.List[str]):
-        # Detect a dependency with CMake using the '--find-package' mode
-        # and the trace output (stderr)
-        #
-        # When the trace output is enabled CMake prints all functions with
-        # parameters to stderr as they are executed. Since CMake 3.4.0
-        # variables ("${VAR}") are also replaced in the trace output.
-        mlog.debug('\nDetermining dependency {!r} with CMake executable '
-                   '{!r}'.format(name, self.cmakebin.executable_path()))
-
-        # Try different CMake generators since specifying no generator may fail
-        # in cygwin for some reason
-        gen_list = []
-        # First try the last working generator
-        if CMakeDependency.class_working_generator is not None:
-            gen_list += [CMakeDependency.class_working_generator]
-        gen_list += CMakeDependency.class_cmake_generators
-
-        for i in gen_list:
-            mlog.debug('Try CMake generator: {}'.format(i if len(i) > 0 else 'auto'))
-
-            # Prepare options
-            cmake_opts = ['--trace-expand', '-DNAME={}'.format(name), '-DARCHS={}'.format(';'.join(self.cmakeinfo['archs']))] + args + ['.']
-            cmake_opts += self._extra_cmake_opts()
-            if len(i) > 0:
-                cmake_opts = ['-G', i] + cmake_opts
-
-            # Run CMake
-            ret1, out1, err1 = self._call_cmake(cmake_opts, self._main_cmake_file())
-
-            # Current generator was successful
-            if ret1 == 0:
-                CMakeDependency.class_working_generator = i
-                break
-
-            mlog.debug('CMake failed for generator {} and package {} with error code {}'.format(i, name, ret1))
-            mlog.debug('OUT:\n{}\n\n\nERR:\n{}\n\n'.format(out1, err1))
-
-        # Check if any generator succeeded
-        if ret1 != 0:
-            return
-
-        try:
-            self.traceparser.parse(err1)
-        except CMakeException as e:
-            e = self._gen_exception(str(e))
-            if self.required:
-                raise
-            else:
-                self.compile_args = []
-                self.link_args = []
-                self.is_found = False
-                self.reason = e
-                return
-
-        # Whether the package is found or not is always stored in PACKAGE_FOUND
-        self.is_found = self.traceparser.var_to_bool('PACKAGE_FOUND')
-        if not self.is_found:
-            return
-
-        # Try to detect the version
-        vers_raw = self.traceparser.get_cmake_var('PACKAGE_VERSION')
-
-        if len(vers_raw) > 0:
-            self.version = vers_raw[0]
-            self.version.strip('"\' ')
-
-        # Post-process module list. Used in derived classes to modify the
-        # module list (append prepend a string, etc.).
-        modules = self._map_module_list(modules)
-        autodetected_module_list = False
-
-        # Try guessing a CMake target if none is provided
-        if len(modules) == 0:
-            for i in self.traceparser.targets:
-                tg = i.lower()
-                lname = name.lower()
-                if '{}::{}'.format(lname, lname) == tg or lname == tg.replace('::', ''):
-                    mlog.debug('Guessed CMake target \'{}\''.format(i))
-                    modules = [(i, True)]
-                    autodetected_module_list = True
-                    break
-
-        # Failed to guess a target --> try the old-style method
-        if len(modules) == 0:
-            incDirs = [x for x in self.traceparser.get_cmake_var('PACKAGE_INCLUDE_DIRS') if x]
-            defs = [x for x in self.traceparser.get_cmake_var('PACKAGE_DEFINITIONS') if x]
-            libs = [x for x in self.traceparser.get_cmake_var('PACKAGE_LIBRARIES') if x]
-
-            # Try to use old style variables if no module is specified
-            if len(libs) > 0:
-                self.compile_args = list(map(lambda x: '-I{}'.format(x), incDirs)) + defs
-                self.link_args = libs
-                mlog.debug('using old-style CMake variables for dependency {}'.format(name))
-                mlog.debug('Include Dirs:         {}'.format(incDirs))
-                mlog.debug('Compiler Definitions: {}'.format(defs))
-                mlog.debug('Libraries:            {}'.format(libs))
-                return
-
-            # Even the old-style approach failed. Nothing else we can do here
-            self.is_found = False
-            raise self._gen_exception('CMake: failed to guess a CMake target for {}.\n'
-                                      'Try to explicitly specify one or more targets with the "modules" property.\n'
-                                      'Valid targets are:\n{}'.format(name, list(self.traceparser.targets.keys())))
-
-        # Set dependencies with CMake targets
-        reg_is_lib = re.compile(r'^(-l[a-zA-Z0-9_]+|-pthread)$')
-        processed_targets = []
-        incDirs = []
-        compileDefinitions = []
-        compileOptions = []
-        libraries = []
-        for i, required in modules:
-            if i not in self.traceparser.targets:
-                if not required:
-                    mlog.warning('CMake: T.Optional module', mlog.bold(self._original_module_name(i)), 'for', mlog.bold(name), 'was not found')
-                    continue
-                raise self._gen_exception('CMake: invalid module {} for {}.\n'
-                                          'Try to explicitly specify one or more targets with the "modules" property.\n'
-                                          'Valid targets are:\n{}'.format(self._original_module_name(i), name, list(self.traceparser.targets.keys())))
-
-            targets = [i]
-            if not autodetected_module_list:
-                self.found_modules += [i]
-
-            while len(targets) > 0:
-                curr = targets.pop(0)
-
-                # Skip already processed targets
-                if curr in processed_targets:
-                    continue
-
-                tgt = self.traceparser.targets[curr]
-                cfgs = []
-                cfg = ''
-                otherDeps = []
-                mlog.debug(tgt)
-
-                if 'INTERFACE_INCLUDE_DIRECTORIES' in tgt.properties:
-                    incDirs += [x for x in tgt.properties['INTERFACE_INCLUDE_DIRECTORIES'] if x]
-
-                if 'INTERFACE_COMPILE_DEFINITIONS' in tgt.properties:
-                    compileDefinitions += ['-D' + re.sub('^-D', '', x) for x in tgt.properties['INTERFACE_COMPILE_DEFINITIONS'] if x]
-
-                if 'INTERFACE_COMPILE_OPTIONS' in tgt.properties:
-                    compileOptions += [x for x in tgt.properties['INTERFACE_COMPILE_OPTIONS'] if x]
-
-                if 'IMPORTED_CONFIGURATIONS' in tgt.properties:
-                    cfgs = [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x]
-                    cfg = cfgs[0]
-
-                if 'RELEASE' in cfgs:
-                    cfg = 'RELEASE'
-
-                if 'IMPORTED_IMPLIB_{}'.format(cfg) in tgt.properties:
-                    libraries += [x for x in tgt.properties['IMPORTED_IMPLIB_{}'.format(cfg)] if x]
-                elif 'IMPORTED_IMPLIB' in tgt.properties:
-                    libraries += [x for x in tgt.properties['IMPORTED_IMPLIB'] if x]
-                elif 'IMPORTED_LOCATION_{}'.format(cfg) in tgt.properties:
-                    libraries += [x for x in tgt.properties['IMPORTED_LOCATION_{}'.format(cfg)] if x]
-                elif 'IMPORTED_LOCATION' in tgt.properties:
-                    libraries += [x for x in tgt.properties['IMPORTED_LOCATION'] if x]
-
-                if 'INTERFACE_LINK_LIBRARIES' in tgt.properties:
-                    otherDeps += [x for x in tgt.properties['INTERFACE_LINK_LIBRARIES'] if x]
-
-                if 'IMPORTED_LINK_DEPENDENT_LIBRARIES_{}'.format(cfg) in tgt.properties:
-                    otherDeps += [x for x in tgt.properties['IMPORTED_LINK_DEPENDENT_LIBRARIES_{}'.format(cfg)] if x]
-                elif 'IMPORTED_LINK_DEPENDENT_LIBRARIES' in tgt.properties:
-                    otherDeps += [x for x in tgt.properties['IMPORTED_LINK_DEPENDENT_LIBRARIES'] if x]
-
-                for j in otherDeps:
-                    if j in self.traceparser.targets:
-                        targets += [j]
-                    elif reg_is_lib.match(j) or os.path.exists(j):
-                        libraries += [j]
-
-                processed_targets += [curr]
-
-        # Make sure all elements in the lists are unique and sorted
-        incDirs = sorted(set(incDirs))
-        compileDefinitions = sorted(set(compileDefinitions))
-        compileOptions = sorted(set(compileOptions))
-        libraries = sorted(set(libraries))
-
-        mlog.debug('Include Dirs:         {}'.format(incDirs))
-        mlog.debug('Compiler Definitions: {}'.format(compileDefinitions))
-        mlog.debug('Compiler Options:     {}'.format(compileOptions))
-        mlog.debug('Libraries:            {}'.format(libraries))
-
-        self.compile_args = compileOptions + compileDefinitions + ['-I{}'.format(x) for x in incDirs]
-        self.link_args = libraries
-
-    def _setup_cmake_dir(self, cmake_file: str) -> str:
-        # Setup the CMake build environment and return the "build" directory
-        build_dir = Path(self.cmake_root_dir) / 'cmake_{}'.format(self.name)
-        build_dir.mkdir(parents=True, exist_ok=True)
-
-        # Insert language parameters into the CMakeLists.txt and write new CMakeLists.txt
-        src_cmake = Path(__file__).parent / 'data' / cmake_file
-        cmake_txt = src_cmake.read_text()
-
-        # 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
-        # without C language is
-        #   find_package(Threads)
-        # To make this general to
-        # any other language that might need this, we use a list for all
-        # languages and expand in the cmake Project(... LANGUAGES ...) statement.
-        from ..cmake import language_map
-        cmake_language = [language_map[x] for x in self.language_list if x in language_map]
-        if not cmake_language:
-            cmake_language += ['NONE']
-
-        cmake_txt = """
-cmake_minimum_required(VERSION ${{CMAKE_VERSION}})
-project(MesonTemp LANGUAGES {})
-""".format(' '.join(cmake_language)) + cmake_txt
-
-        cm_file = build_dir / 'CMakeLists.txt'
-        cm_file.write_text(cmake_txt)
-        mlog.cmd_ci_include(cm_file.absolute().as_posix())
-
-        return str(build_dir)
-
-    def _call_cmake(self, args, cmake_file: str, env=None):
-        build_dir = self._setup_cmake_dir(cmake_file)
-        return self.cmakebin.call_with_fake_build(args, build_dir, env=env)
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.CMAKE]
-
-    def log_tried(self):
-        return self.type_name
-
-    def log_details(self) -> str:
-        modules = [self._original_module_name(x) for x in self.found_modules]
-        modules = sorted(set(modules))
-        if modules:
-            return 'modules: ' + ', '.join(modules)
-        return ''
-
-    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
-                     configtool: T.Optional[str] = None, default_value: T.Optional[str] = None,
-                     pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
-        if cmake:
-            try:
-                v = self.traceparser.vars[cmake]
-            except KeyError:
-                pass
-            else:
-                if len(v) == 1:
-                    return v[0]
-                elif v:
-                    return v
-        if default_value is not None:
-            return default_value
-        raise DependencyException('Could not get cmake variable and no default provided for {!r}'.format(self))
-
-class DubDependency(ExternalDependency):
-    class_dubbin = None
-
-    def __init__(self, name, environment, kwargs):
-        super().__init__('dub', environment, 'd', kwargs)
-        self.name = name
-        self.compiler = super().get_compiler()
-        self.module_path = None
-
-        if 'required' in kwargs:
-            self.required = kwargs.get('required')
-
-        if DubDependency.class_dubbin is None:
-            self.dubbin = self._check_dub()
-            DubDependency.class_dubbin = self.dubbin
-        else:
-            self.dubbin = DubDependency.class_dubbin
-
-        if not self.dubbin:
-            if self.required:
-                raise DependencyException('DUB not found.')
-            self.is_found = False
-            return
-
-        mlog.debug('Determining dependency {!r} with DUB executable '
-                   '{!r}'.format(name, self.dubbin.get_path()))
-
-        # we need to know the target architecture
-        arch = self.compiler.arch
-
-        # Ask dub for the package
-        ret, res = self._call_dubbin(['describe', name, '--arch=' + arch])
-
-        if ret != 0:
-            self.is_found = False
-            return
-
-        comp = self.compiler.get_id().replace('llvm', 'ldc').replace('gcc', 'gdc')
-        packages = []
-        description = json.loads(res)
-        for package in description['packages']:
-            packages.append(package['name'])
-            if package['name'] == name:
-                self.is_found = True
-
-                not_lib = True
-                if 'targetType' in package:
-                    if package['targetType'] in ['library', 'sourceLibrary', 'staticLibrary', 'dynamicLibrary']:
-                        not_lib = False
-
-                if not_lib:
-                    mlog.error(mlog.bold(name), "found but it isn't a library")
-                    self.is_found = False
-                    return
-
-                self.module_path = self._find_right_lib_path(package['path'], comp, description, True, package['targetFileName'])
-                if not os.path.exists(self.module_path):
-                    # check if the dependency was built for other archs
-                    archs = [['x86_64'], ['x86'], ['x86', 'x86_mscoff']]
-                    for a in archs:
-                        description_a = copy.deepcopy(description)
-                        description_a['architecture'] = a
-                        arch_module_path = self._find_right_lib_path(package['path'], comp, description_a, True, package['targetFileName'])
-                        if arch_module_path:
-                            mlog.error(mlog.bold(name), "found but it wasn't compiled for", mlog.bold(arch))
-                            self.is_found = False
-                            return
-
-                    mlog.error(mlog.bold(name), "found but it wasn't compiled with", mlog.bold(comp))
-                    self.is_found = False
-                    return
-
-                self.version = package['version']
-                self.pkg = package
-
-        if self.pkg['targetFileName'].endswith('.a'):
-            self.static = True
-
-        self.compile_args = []
-        for flag in self.pkg['dflags']:
-            self.link_args.append(flag)
-        for path in self.pkg['importPaths']:
-            self.compile_args.append('-I' + os.path.join(self.pkg['path'], path))
-
-        self.link_args = self.raw_link_args = []
-        for flag in self.pkg['lflags']:
-            self.link_args.append(flag)
-
-        self.link_args.append(os.path.join(self.module_path, self.pkg['targetFileName']))
-
-        # Handle dependencies
-        libs = []
-
-        def add_lib_args(field_name, target):
-            if field_name in target['buildSettings']:
-                for lib in target['buildSettings'][field_name]:
-                    if lib not in libs:
-                        libs.append(lib)
-                        if os.name != 'nt':
-                            pkgdep = PkgConfigDependency(lib, environment, {'required': 'true', 'silent': 'true'})
-                            for arg in pkgdep.get_compile_args():
-                                self.compile_args.append(arg)
-                            for arg in pkgdep.get_link_args():
-                                self.link_args.append(arg)
-                            for arg in pkgdep.get_link_args(raw=True):
-                                self.raw_link_args.append(arg)
-
-        for target in description['targets']:
-            if target['rootPackage'] in packages:
-                add_lib_args('libs', target)
-                add_lib_args('libs-{}'.format(platform.machine()), target)
-                for file in target['buildSettings']['linkerFiles']:
-                    lib_path = self._find_right_lib_path(file, comp, description)
-                    if lib_path:
-                        self.link_args.append(lib_path)
-                    else:
-                        self.is_found = False
-
-    def get_compiler(self):
-        return self.compiler
-
-    def _find_right_lib_path(self, default_path, comp, description, folder_only=False, file_name=''):
-        module_path = lib_file_name = ''
-        if folder_only:
-            module_path = default_path
-            lib_file_name = file_name
-        else:
-            module_path = os.path.dirname(default_path)
-            lib_file_name = os.path.basename(default_path)
-        module_build_path = os.path.join(module_path, '.dub', 'build')
-
-        # Get D version implemented in the compiler
-        # gdc doesn't support this
-        ret, res = self._call_dubbin(['--version'])
-
-        if ret != 0:
-            mlog.error('Failed to run {!r}', mlog.bold(comp))
-            return
-
-        d_ver = re.search('v[0-9].[0-9][0-9][0-9].[0-9]', res) # Ex.: v2.081.2
-        if d_ver is not None:
-            d_ver = d_ver.group().rsplit('.', 1)[0].replace('v', '').replace('.', '') # Fix structure. Ex.: 2081
-        else:
-            d_ver = '' # gdc
-
-        if not os.path.isdir(module_build_path):
-            return ''
-
-        # Ex.: library-debug-linux.posix-x86_64-ldc_2081-EF934983A3319F8F8FF2F0E107A363BA
-        build_name = '-{}-{}-{}-{}_{}'.format(description['buildType'], '.'.join(description['platform']), '.'.join(description['architecture']), comp, d_ver)
-        for entry in os.listdir(module_build_path):
-            if build_name in entry:
-                for file in os.listdir(os.path.join(module_build_path, entry)):
-                    if file == lib_file_name:
-                        if folder_only:
-                            return os.path.join(module_build_path, entry)
-                        else:
-                            return os.path.join(module_build_path, entry, lib_file_name)
-
-        return ''
-
-    def _call_dubbin(self, args, env=None):
-        p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2]
-        return p.returncode, out.strip()
-
-    def _call_copmbin(self, args, env=None):
-        p, out = Popen_safe(self.compiler.get_exelist() + args, env=env)[0:2]
-        return p.returncode, out.strip()
-
-    def _check_dub(self):
-        dubbin = ExternalProgram('dub', silent=True)
-        if dubbin.found():
-            try:
-                p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2]
-                if p.returncode != 0:
-                    mlog.warning('Found dub {!r} but couldn\'t run it'
-                                 ''.format(' '.join(dubbin.get_command())))
-                    # Set to False instead of None to signify that we've already
-                    # searched for it and not found it
-                    dubbin = False
-            except (FileNotFoundError, PermissionError):
-                dubbin = False
-        else:
-            dubbin = False
-        if dubbin:
-            mlog.log('Found DUB:', mlog.bold(dubbin.get_path()),
-                     '(%s)' % out.strip())
-        else:
-            mlog.log('Found DUB:', mlog.red('NO'))
-        return dubbin
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.DUB]
-
-class ExternalProgram:
-    windows_exts = ('exe', 'msc', 'com', 'bat', 'cmd')
-    # An 'ExternalProgram' always runs on the build machine
-    for_machine = MachineChoice.BUILD
-
-    def __init__(self, name: str, command: T.Optional[T.List[str]] = None,
-                 silent: bool = False, search_dir: T.Optional[str] = None,
-                 extra_search_dirs: T.Optional[T.List[str]] = None):
-        self.name = name
-        if command is not None:
-            self.command = listify(command)
-        else:
-            all_search_dirs = [search_dir]
-            if extra_search_dirs:
-                all_search_dirs += extra_search_dirs
-            for d in all_search_dirs:
-                self.command = self._search(name, d)
-                if self.found():
-                    break
-
-        # Set path to be the last item that is actually a file (in order to
-        # skip options in something like ['python', '-u', 'file.py']. If we
-        # can't find any components, default to the last component of the path.
-        self.path = self.command[-1]
-        for i in range(len(self.command) - 1, -1, -1):
-            arg = self.command[i]
-            if arg is not None and os.path.isfile(arg):
-                self.path = arg
-                break
-
-        if not silent:
-            # ignore the warning because derived classes never call this __init__
-            # method, and thus only the found() method of this class is ever executed
-            if self.found():  # lgtm [py/init-calls-subclass]
-                mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'),
-                         '(%s)' % ' '.join(self.command))
-            else:
-                mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO'))
-
-    def __repr__(self) -> str:
-        r = '<{} {!r} -> {!r}>'
-        return r.format(self.__class__.__name__, self.name, self.command)
-
-    def description(self) -> str:
-        '''Human friendly description of the command'''
-        return ' '.join(self.command)
-
-    @classmethod
-    def from_bin_list(cls, bt: BinaryTable, name):
-        command = bt.lookup_entry(name)
-        if command is None:
-            return NonExistingExternalProgram()
-        return cls.from_entry(name, command)
-
-    @staticmethod
-    @functools.lru_cache(maxsize=None)
-    def _windows_sanitize_path(path: str) -> str:
-        # Ensure that we use USERPROFILE even when inside MSYS, MSYS2, Cygwin, etc.
-        if 'USERPROFILE' not in os.environ:
-            return path
-        # Ignore executables in the WindowsApps directory which are
-        # zero-sized wrappers that magically open the Windows Store to
-        # install the application.
-        appstore_dir = Path(os.environ['USERPROFILE']) / 'AppData' / 'Local' / 'Microsoft' / 'WindowsApps'
-        paths = []
-        for each in path.split(os.pathsep):
-            if Path(each) != appstore_dir:
-                paths.append(each)
-        return os.pathsep.join(paths)
-
-    @staticmethod
-    def from_entry(name, command):
-        if isinstance(command, list):
-            if len(command) == 1:
-                command = command[0]
-        # We cannot do any searching if the command is a list, and we don't
-        # need to search if the path is an absolute path.
-        if isinstance(command, list) or os.path.isabs(command):
-            return ExternalProgram(name, command=command, silent=True)
-        assert isinstance(command, str)
-        # Search for the command using the specified string!
-        return ExternalProgram(command, silent=True)
-
-    @staticmethod
-    def _shebang_to_cmd(script):
-        """
-        Check if the file has a shebang and manually parse it to figure out
-        the interpreter to use. This is useful if the script is not executable
-        or if we're on Windows (which does not understand shebangs).
-        """
-        try:
-            with open(script) as f:
-                first_line = f.readline().strip()
-            if first_line.startswith('#!'):
-                # In a shebang, everything before the first space is assumed to
-                # be the command to run and everything after the first space is
-                # the single argument to pass to that command. So we must split
-                # exactly once.
-                commands = first_line[2:].split('#')[0].strip().split(maxsplit=1)
-                if mesonlib.is_windows():
-                    # Windows does not have UNIX paths so remove them,
-                    # but don't remove Windows paths
-                    if commands[0].startswith('/'):
-                        commands[0] = commands[0].split('/')[-1]
-                    if len(commands) > 0 and commands[0] == 'env':
-                        commands = commands[1:]
-                    # Windows does not ship python3.exe, but we know the path to it
-                    if len(commands) > 0 and commands[0] == 'python3':
-                        commands = mesonlib.python_command + commands[1:]
-                elif mesonlib.is_haiku():
-                    # Haiku does not have /usr, but a lot of scripts assume that
-                    # /usr/bin/env always exists. Detect that case and run the
-                    # script with the interpreter after it.
-                    if commands[0] == '/usr/bin/env':
-                        commands = commands[1:]
-                    # We know what python3 is, we're running on it
-                    if len(commands) > 0 and commands[0] == 'python3':
-                        commands = mesonlib.python_command + commands[1:]
-                else:
-                    # Replace python3 with the actual python3 that we are using
-                    if commands[0] == '/usr/bin/env' and commands[1] == 'python3':
-                        commands = mesonlib.python_command + commands[2:]
-                    elif commands[0].split('/')[-1] == 'python3':
-                        commands = mesonlib.python_command + commands[1:]
-                return commands + [script]
-        except Exception as e:
-            mlog.debug(e)
-        mlog.debug('Unusable script {!r}'.format(script))
-        return False
-
-    def _is_executable(self, path):
-        suffix = os.path.splitext(path)[-1].lower()[1:]
-        execmask = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
-        if mesonlib.is_windows():
-            if suffix in self.windows_exts:
-                return True
-        elif os.stat(path).st_mode & execmask:
-            return not os.path.isdir(path)
-        return False
-
-    def _search_dir(self, name, search_dir):
-        if search_dir is None:
-            return False
-        trial = os.path.join(search_dir, name)
-        if os.path.exists(trial):
-            if self._is_executable(trial):
-                return [trial]
-            # Now getting desperate. Maybe it is a script file that is
-            # a) not chmodded executable, or
-            # b) we are on windows so they can't be directly executed.
-            return self._shebang_to_cmd(trial)
-        else:
-            if mesonlib.is_windows():
-                for ext in self.windows_exts:
-                    trial_ext = '{}.{}'.format(trial, ext)
-                    if os.path.exists(trial_ext):
-                        return [trial_ext]
-        return False
-
-    def _search_windows_special_cases(self, name, command):
-        '''
-        Lots of weird Windows quirks:
-        1. PATH search for @name returns files with extensions from PATHEXT,
-           but only self.windows_exts are executable without an interpreter.
-        2. @name might be an absolute path to an executable, but without the
-           extension. This works inside MinGW so people use it a lot.
-        3. The script is specified without an extension, in which case we have
-           to manually search in PATH.
-        4. More special-casing for the shebang inside the script.
-        '''
-        if command:
-            # On Windows, even if the PATH search returned a full path, we can't be
-            # sure that it can be run directly if it's not a native executable.
-            # For instance, interpreted scripts sometimes need to be run explicitly
-            # with an interpreter if the file association is not done properly.
-            name_ext = os.path.splitext(command)[1]
-            if name_ext[1:].lower() in self.windows_exts:
-                # Good, it can be directly executed
-                return [command]
-            # Try to extract the interpreter from the shebang
-            commands = self._shebang_to_cmd(command)
-            if commands:
-                return commands
-            return [None]
-        # Maybe the name is an absolute path to a native Windows
-        # executable, but without the extension. This is technically wrong,
-        # but many people do it because it works in the MinGW shell.
-        if os.path.isabs(name):
-            for ext in self.windows_exts:
-                command = '{}.{}'.format(name, ext)
-                if os.path.exists(command):
-                    return [command]
-        # On Windows, interpreted scripts must have an extension otherwise they
-        # cannot be found by a standard PATH search. So we do a custom search
-        # where we manually search for a script with a shebang in PATH.
-        search_dirs = self._windows_sanitize_path(os.environ.get('PATH', '')).split(';')
-        for search_dir in search_dirs:
-            commands = self._search_dir(name, search_dir)
-            if commands:
-                return commands
-        return [None]
-
-    def _search(self, name, search_dir):
-        '''
-        Search in the specified dir for the specified executable by name
-        and if not found search in PATH
-        '''
-        commands = self._search_dir(name, search_dir)
-        if commands:
-            return commands
-        # Do a standard search in PATH
-        path = os.environ.get('PATH', None)
-        if mesonlib.is_windows() and path:
-            path = self._windows_sanitize_path(path)
-        command = shutil.which(name, path=path)
-        if mesonlib.is_windows():
-            return self._search_windows_special_cases(name, command)
-        # On UNIX-like platforms, shutil.which() is enough to find
-        # all executables whether in PATH or with an absolute path
-        return [command]
-
-    def found(self) -> bool:
-        return self.command[0] is not None
-
-    def get_command(self):
-        return self.command[:]
-
-    def get_path(self):
-        return self.path
-
-    def get_name(self):
-        return self.name
-
-
-class NonExistingExternalProgram(ExternalProgram):  # lgtm [py/missing-call-to-init]
-    "A program that will never exist"
-
-    def __init__(self, name='nonexistingprogram'):
-        self.name = name
-        self.command = [None]
-        self.path = None
-
-    def __repr__(self):
-        r = '<{} {!r} -> {!r}>'
-        return r.format(self.__class__.__name__, self.name, self.command)
-
-    def found(self):
-        return False
-
-
-class EmptyExternalProgram(ExternalProgram):  # lgtm [py/missing-call-to-init]
-    '''
-    A program object that returns an empty list of commands. Used for cases
-    such as a cross file exe_wrapper to represent that it's not required.
-    '''
-
-    def __init__(self):
-        self.name = None
-        self.command = []
-        self.path = None
-
-    def __repr__(self):
-        r = '<{} {!r} -> {!r}>'
-        return r.format(self.__class__.__name__, self.name, self.command)
-
-    def found(self):
-        return True
-
-
 class ExternalLibrary(ExternalDependency):
-    def __init__(self, name, link_args, environment, language, silent=False):
-        super().__init__('library', environment, language, {})
+    def __init__(self, name: str, link_args: T.List[str], environment: 'Environment',
+                 language: str, silent: bool = False) -> None:
+        super().__init__(DependencyTypeName('library'), environment, {}, language=language)
         self.name = name
         self.language = language
         self.is_found = False
@@ -2043,7 +422,7 @@
             else:
                 mlog.log('Library', mlog.bold(name), 'found:', mlog.red('NO'))
 
-    def get_link_args(self, language=None, **kwargs):
+    def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
         '''
         External libraries detected using a compiler must only be used with
         compatible code. For instance, Vala libraries (.vapi files) cannot be
@@ -2056,11 +435,11 @@
         if (self.language == 'vala' and language != 'vala') or \
            (language == 'vala' and self.language != 'vala'):
             return []
-        return super().get_link_args(**kwargs)
+        return super().get_link_args(language=language, raw=raw)
 
     def get_partial_dependency(self, *, compile_args: bool = False,
                                link_args: bool = False, links: bool = False,
-                               includes: bool = False, sources: bool = False):
+                               includes: bool = False, sources: bool = False) -> 'ExternalLibrary':
         # External library only has link_args, so ignore the rest of the
         # interface.
         new = copy.copy(self)
@@ -2069,279 +448,6 @@
         return new
 
 
-class ExtraFrameworkDependency(ExternalDependency):
-    system_framework_paths = None
-
-    def __init__(self, name, required, paths, env, lang, kwargs):
-        super().__init__('extraframeworks', env, lang, kwargs)
-        self.name = name
-        self.required = required
-        # Full path to framework directory
-        self.framework_path = None
-        if not self.clib_compiler:
-            raise DependencyException('No C-like compilers are available')
-        if self.system_framework_paths is None:
-            try:
-                self.system_framework_paths = self.clib_compiler.find_framework_paths(self.env)
-            except MesonException as e:
-                if 'non-clang' in str(e):
-                    # Apple frameworks can only be found (and used) with the
-                    # system compiler. It is not available so bail immediately.
-                    self.is_found = False
-                    return
-                raise
-        self.detect(name, paths)
-
-    def detect(self, name, paths):
-        if not paths:
-            paths = self.system_framework_paths
-        for p in paths:
-            mlog.debug('Looking for framework {} in {}'.format(name, p))
-            # We need to know the exact framework path because it's used by the
-            # Qt5 dependency class, and for setting the include path. We also
-            # want to avoid searching in an invalid framework path which wastes
-            # time and can cause a false positive.
-            framework_path = self._get_framework_path(p, name)
-            if framework_path is None:
-                continue
-            # We want to prefer the specified paths (in order) over the system
-            # paths since these are "extra" frameworks.
-            # For example, Python2's framework is in /System/Library/Frameworks and
-            # Python3's framework is in /Library/Frameworks, but both are called
-            # Python.framework. We need to know for sure that the framework was
-            # found in the path we expect.
-            allow_system = p in self.system_framework_paths
-            args = self.clib_compiler.find_framework(name, self.env, [p], allow_system)
-            if args is None:
-                continue
-            self.link_args = args
-            self.framework_path = framework_path.as_posix()
-            self.compile_args = ['-F' + self.framework_path]
-            # We need to also add -I includes to the framework because all
-            # cross-platform projects such as OpenGL, Python, Qt, GStreamer,
-            # etc do not use "framework includes":
-            # https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/IncludingFrameworks.html
-            incdir = self._get_framework_include_path(framework_path)
-            if incdir:
-                self.compile_args += ['-I' + incdir]
-            self.is_found = True
-            return
-
-    def _get_framework_path(self, path, name):
-        p = Path(path)
-        lname = name.lower()
-        for d in p.glob('*.framework/'):
-            if lname == d.name.rsplit('.', 1)[0].lower():
-                return d
-        return None
-
-    def _get_framework_latest_version(self, path):
-        versions = []
-        for each in path.glob('Versions/*'):
-            # macOS filesystems are usually case-insensitive
-            if each.name.lower() == 'current':
-                continue
-            versions.append(Version(each.name))
-        if len(versions) == 0:
-            # most system frameworks do not have a 'Versions' directory
-            return 'Headers'
-        return 'Versions/{}/Headers'.format(sorted(versions)[-1]._s)
-
-    def _get_framework_include_path(self, path):
-        # According to the spec, 'Headers' must always be a symlink to the
-        # Headers directory inside the currently-selected version of the
-        # framework, but sometimes frameworks are broken. Look in 'Versions'
-        # for the currently-selected version or pick the latest one.
-        trials = ('Headers', 'Versions/Current/Headers',
-                  self._get_framework_latest_version(path))
-        for each in trials:
-            trial = path / each
-            if trial.is_dir():
-                return trial.as_posix()
-        return None
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.EXTRAFRAMEWORK]
-
-    def log_info(self):
-        return self.framework_path
-
-    def log_tried(self):
-        return 'framework'
-
-
-def get_dep_identifier(name, kwargs) -> T.Tuple:
-    identifier = (name, )
-    for key, value in kwargs.items():
-        # 'version' is irrelevant for caching; the caller must check version matches
-        # 'native' is handled above with `for_machine`
-        # 'required' is irrelevant for caching; the caller handles it separately
-        # 'fallback' subprojects cannot be cached -- they must be initialized
-        # 'default_options' is only used in fallback case
-        if key in ('version', 'native', 'required', 'fallback', 'default_options'):
-            continue
-        # All keyword arguments are strings, ints, or lists (or lists of lists)
-        if isinstance(value, list):
-            value = frozenset(listify(value))
-        identifier += (key, value)
-    return identifier
-
-display_name_map = {
-    'boost': 'Boost',
-    'cuda': 'CUDA',
-    'dub': 'DUB',
-    'gmock': 'GMock',
-    'gtest': 'GTest',
-    'hdf5': 'HDF5',
-    'llvm': 'LLVM',
-    'mpi': 'MPI',
-    'netcdf': 'NetCDF',
-    'openmp': 'OpenMP',
-    'wxwidgets': 'WxWidgets',
-}
-
-def find_external_dependency(name, env, kwargs):
-    assert(name)
-    required = kwargs.get('required', True)
-    if not isinstance(required, bool):
-        raise DependencyException('Keyword "required" must be a boolean.')
-    if not isinstance(kwargs.get('method', ''), str):
-        raise DependencyException('Keyword "method" must be a string.')
-    lname = name.lower()
-    if lname not in _packages_accept_language and 'language' in kwargs:
-        raise DependencyException('%s dependency does not accept "language" keyword argument' % (name, ))
-    if not isinstance(kwargs.get('version', ''), (str, list)):
-        raise DependencyException('Keyword "Version" must be string or list.')
-
-    # display the dependency name with correct casing
-    display_name = display_name_map.get(lname, lname)
-
-    for_machine = MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST
-
-    type_text = PerMachine('Build-time', 'Run-time')[for_machine] + ' dependency'
-
-    # build a list of dependency methods to try
-    candidates = _build_external_dependency_list(name, env, kwargs)
-
-    pkg_exc = []
-    pkgdep = []
-    details = ''
-
-    for c in candidates:
-        # try this dependency method
-        try:
-            d = c()
-            d._check_version()
-            pkgdep.append(d)
-        except DependencyException as e:
-            pkg_exc.append(e)
-            mlog.debug(str(e))
-        else:
-            pkg_exc.append(None)
-            details = d.log_details()
-            if details:
-                details = '(' + details + ') '
-            if 'language' in kwargs:
-                details += 'for ' + d.language + ' '
-
-            # if the dependency was found
-            if d.found():
-
-                info = []
-                if d.version:
-                    info.append(mlog.normal_cyan(d.version))
-
-                log_info = d.log_info()
-                if log_info:
-                    info.append('(' + log_info + ')')
-
-                mlog.log(type_text, mlog.bold(display_name), details + 'found:', mlog.green('YES'), *info)
-
-                return d
-
-    # otherwise, the dependency could not be found
-    tried_methods = [d.log_tried() for d in pkgdep if d.log_tried()]
-    if tried_methods:
-        tried = '{}'.format(mlog.format_list(tried_methods))
-    else:
-        tried = ''
-
-    mlog.log(type_text, mlog.bold(display_name), details + 'found:', mlog.red('NO'),
-             '(tried {})'.format(tried) if tried else '')
-
-    if required:
-        # if an exception occurred with the first detection method, re-raise it
-        # (on the grounds that it came from the preferred dependency detection
-        # method)
-        if pkg_exc and pkg_exc[0]:
-            raise pkg_exc[0]
-
-        # we have a list of failed ExternalDependency objects, so we can report
-        # the methods we tried to find the dependency
-        raise DependencyException('Dependency "%s" not found' % (name) +
-                                  (', tried %s' % (tried) if tried else ''))
-
-    return NotFoundDependency(env)
-
-
-def _build_external_dependency_list(name, env: Environment, kwargs: T.Dict[str, T.Any]) -> list:
-    # First check if the method is valid
-    if 'method' in kwargs and kwargs['method'] not in [e.value for e in DependencyMethods]:
-        raise DependencyException('method {!r} is invalid'.format(kwargs['method']))
-
-    # Is there a specific dependency detector for this dependency?
-    lname = name.lower()
-    if lname in packages:
-        # Create the list of dependency object constructors using a factory
-        # class method, if one exists, otherwise the list just consists of the
-        # constructor
-        if getattr(packages[lname], '_factory', None):
-            dep = packages[lname]._factory(env, kwargs)
-        else:
-            dep = [functools.partial(packages[lname], env, kwargs)]
-        return dep
-
-    candidates = []
-
-    # If it's explicitly requested, use the dub detection method (only)
-    if 'dub' == kwargs.get('method', ''):
-        candidates.append(functools.partial(DubDependency, name, env, kwargs))
-        return candidates
-
-    # If it's explicitly requested, use the pkgconfig detection method (only)
-    if 'pkg-config' == kwargs.get('method', ''):
-        candidates.append(functools.partial(PkgConfigDependency, name, env, kwargs))
-        return candidates
-
-    # If it's explicitly requested, use the CMake detection method (only)
-    if 'cmake' == kwargs.get('method', ''):
-        candidates.append(functools.partial(CMakeDependency, name, env, kwargs))
-        return candidates
-
-    # If it's explicitly requested, use the Extraframework detection method (only)
-    if 'extraframework' == kwargs.get('method', ''):
-        # On OSX, also try framework dependency detector
-        if mesonlib.is_osx():
-            candidates.append(functools.partial(ExtraFrameworkDependency, name,
-                                                False, None, env, None, kwargs))
-        return candidates
-
-    # Otherwise, just use the pkgconfig and cmake dependency detector
-    if 'auto' == kwargs.get('method', 'auto'):
-        candidates.append(functools.partial(PkgConfigDependency, name, env, kwargs))
-
-        # On OSX, also try framework dependency detector
-        if mesonlib.is_osx():
-            candidates.append(functools.partial(ExtraFrameworkDependency, name,
-                                                False, None, env, None, kwargs))
-
-        # Only use CMake as a last resort, since it might not work 100% (see #6113)
-        candidates.append(functools.partial(CMakeDependency, name, env, kwargs))
-
-    return candidates
-
-
 def sort_libpaths(libpaths: T.List[str], refpaths: T.List[str]) -> T.List[str]:
     """Sort  according to 
 
@@ -2351,11 +457,11 @@
     if len(refpaths) == 0:
         return list(libpaths)
 
-    def key_func(libpath):
-        common_lengths = []
+    def key_func(libpath: str) -> T.Tuple[int, int]:
+        common_lengths: T.List[int] = []
         for refpath in refpaths:
             try:
-                common_path = os.path.commonpath([libpath, refpath])
+                common_path: str = os.path.commonpath([libpath, refpath])
             except ValueError:
                 common_path = ''
             common_lengths.append(len(common_path))
@@ -2365,13 +471,92 @@
         return (max_index, reversed_max_length)
     return sorted(libpaths, key=key_func)
 
-
-def strip_system_libdirs(environment, for_machine: MachineChoice, link_args):
+def strip_system_libdirs(environment: 'Environment', for_machine: MachineChoice, link_args: T.List[str]) -> T.List[str]:
     """Remove -L arguments.
 
     leaving these in will break builds where a user has a version of a library
     in the system path, and a different version not in the system path if they
     want to link against the non-system path version.
     """
-    exclude = {'-L{}'.format(p) for p in environment.get_compiler_system_dirs(for_machine)}
+    exclude = {f'-L{p}' for p in environment.get_compiler_system_dirs(for_machine)}
     return [l for l in link_args if l not in exclude]
+
+def process_method_kw(possible: T.Iterable[DependencyMethods], kwargs: T.Dict[str, T.Any]) -> T.List[DependencyMethods]:
+    method = kwargs.get('method', 'auto')  # type: T.Union[DependencyMethods, str]
+    if isinstance(method, DependencyMethods):
+        return [method]
+    # TODO: try/except?
+    if method not in [e.value for e in DependencyMethods]:
+        raise DependencyException(f'method {method!r} is invalid')
+    method = DependencyMethods(method)
+
+    # This sets per-tool config methods which are deprecated to to the new
+    # generic CONFIG_TOOL value.
+    if method in [DependencyMethods.SDLCONFIG, DependencyMethods.CUPSCONFIG,
+                  DependencyMethods.PCAPCONFIG, DependencyMethods.LIBWMFCONFIG]:
+        FeatureDeprecated.single_use(f'Configuration method {method.value}', '0.44', 'Use "config-tool" instead.')
+        method = DependencyMethods.CONFIG_TOOL
+    if method is DependencyMethods.QMAKE:
+        FeatureDeprecated.single_use('Configuration method "qmake"', '0.58', 'Use "config-tool" instead.')
+        method = DependencyMethods.CONFIG_TOOL
+
+    # Set the detection method. If the method is set to auto, use any available method.
+    # If method is set to a specific string, allow only that detection method.
+    if method == DependencyMethods.AUTO:
+        methods = list(possible)
+    elif method in possible:
+        methods = [method]
+    else:
+        raise DependencyException(
+            'Unsupported detection method: {}, allowed methods are {}'.format(
+                method.value,
+                mlog.format_list([x.value for x in [DependencyMethods.AUTO] + list(possible)])))
+
+    return methods
+
+def detect_compiler(name: str, env: 'Environment', for_machine: MachineChoice,
+                    language: T.Optional[str]) -> T.Optional['Compiler']:
+    """Given a language and environment find the compiler used."""
+    compilers = env.coredata.compilers[for_machine]
+
+    # Set the compiler for this dependency if a language is specified,
+    # else try to pick something that looks usable.
+    if language:
+        if language not in compilers:
+            m = name.capitalize() + ' requires a {0} compiler, but ' \
+                '{0} is not in the list of project languages'
+            raise DependencyException(m.format(language.capitalize()))
+        return compilers[language]
+    else:
+        for lang in clib_langs:
+            try:
+                return compilers[lang]
+            except KeyError:
+                continue
+    return None
+
+
+class SystemDependency(ExternalDependency):
+
+    """Dependency base for System type dependencies."""
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None) -> None:
+        super().__init__(DependencyTypeName('system'), env, kwargs, language=language)
+        self.name = name
+
+    def log_tried(self) -> str:
+        return 'system'
+
+
+class BuiltinDependency(ExternalDependency):
+
+    """Dependency base for Builtin type dependencies."""
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None) -> None:
+        super().__init__(DependencyTypeName('builtin'), env, kwargs, language=language)
+        self.name = name
+
+    def log_tried(self) -> str:
+        return 'builtin'
diff -Nru meson-0.53.2/mesonbuild/dependencies/boost.py meson-0.61.2/mesonbuild/dependencies/boost.py
--- meson-0.53.2/mesonbuild/dependencies/boost.py	2019-08-28 17:15:39.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/boost.py	2021-11-02 19:58:07.000000000 +0000
@@ -1,4 +1,4 @@
-# Copyright 2013-2017 The Meson development team
+# Copyright 2013-2020 The Meson development team
 
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -12,17 +12,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# This file contains the detection logic for miscellaneous external dependencies.
-
-import glob
-import os
+import re
+import functools
+import typing as T
+from pathlib import Path
 
 from .. import mlog
 from .. import mesonlib
-from ..environment import detect_cpu_family
+from ..environment import Environment
+
+from .base import DependencyException, SystemDependency
+from .pkgconfig import PkgConfigDependency
+from .misc import threads_factory
 
-from .base import (DependencyException, ExternalDependency)
-from .misc import ThreadDependency
+if T.TYPE_CHECKING:
+    from ..environment import Properties
 
 # On windows 3 directory layouts are supported:
 # * The default layout (versioned) installed:
@@ -39,16 +43,6 @@
 # mingw-w64 / Windows : libboost_-mt.a            (location = /mingw64/lib/)
 #                       libboost_-mt.dll.a
 #
-# Library names supported:
-#   - libboost_--mt-gd-x_x.lib (static)
-#   - boost_--mt-gd-x_x.lib|.dll (shared)
-#   - libboost_.lib (static)
-#   - boost_.lib|.dll (shared)
-#   where compiler is vc141 for example.
-#
-# NOTE: -gd means runtime and build time debugging is on
-#       -mt means threading=multi
-#
 # The `modules` argument accept library names. This is because every module that
 # has libraries to link against also has multiple options regarding how to
 # link. See for example:
@@ -78,614 +72,1007 @@
 # Furthermore, the boost documentation for unix above uses examples from windows like
 #   "libboost_regex-vc71-mt-d-x86-1_34.lib", so apparently the abi tags may be more aimed at windows.
 #
-# Probably we should use the linker search path to decide which libraries to use.  This will
-# make it possible to find the macports boost libraries without setting BOOST_ROOT, and will
-# also mean that it would be possible to use user-installed boost libraries when official
-# packages are installed.
-#
-# We thus follow the following strategy:
-# 1. Look for libraries using compiler.find_library( )
-#   1.1 On Linux, just look for boost_
-#   1.2 On other systems (e.g. Mac) look for boost_-mt if multithreading.
-#   1.3 Otherwise look for boost_
-# 2. Fall back to previous approach
-#   2.1. Search particular directories.
-#   2.2. Find boost libraries with unknown suffixes using file-name globbing.
-
-# TODO: Unix: Don't assume we know where the boost dir is, rely on -Idir and -Ldir being set.
-# TODO: Allow user to specify suffix in BOOST_SUFFIX, or add specific options like BOOST_DEBUG for 'd' for debug.
-
-class BoostDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('boost', environment, 'cpp', kwargs)
-        self.need_static_link = ['boost_exception', 'boost_test_exec_monitor']
-        self.is_debug = environment.coredata.get_builtin_option('buildtype').startswith('debug')
-        threading = kwargs.get("threading", "multi")
-        self.is_multithreading = threading == "multi"
-
-        self.requested_modules = self.get_requested(kwargs)
-        if 'thread' in self.requested_modules:
-            self._add_sub_dependency(ThreadDependency, environment, kwargs)
-
-        self.boost_root = None
-        self.boost_roots = []
-        self.incdir = None
-        self.libdir = None
-
-        if 'BOOST_ROOT' in os.environ:
-            self.boost_root = os.environ['BOOST_ROOT']
-            self.boost_roots = [self.boost_root]
-            if not os.path.isabs(self.boost_root):
-                raise DependencyException('BOOST_ROOT must be an absolute path.')
-        if 'BOOST_INCLUDEDIR' in os.environ:
-            self.incdir = os.environ['BOOST_INCLUDEDIR']
-        if 'BOOST_LIBRARYDIR' in os.environ:
-            self.libdir = os.environ['BOOST_LIBRARYDIR']
-
-        if self.boost_root is None:
-            if self.env.machines[self.for_machine].is_windows():
-                self.boost_roots = self.detect_win_roots()
-            else:
-                self.boost_roots = self.detect_nix_roots()
-
-        if self.incdir is None:
-            if self.env.machines[self.for_machine].is_windows():
-                self.incdir = self.detect_win_incdir()
-            else:
-                self.incdir = self.detect_nix_incdir()
-
-        mlog.debug('Boost library root dir is', mlog.bold(self.boost_root))
-        mlog.debug('Boost include directory is', mlog.bold(self.incdir))
-
-        # 1. check if we can find BOOST headers.
-        self.detect_headers_and_version()
-
-        if not self.is_found:
-            return # if we can not find 'boost/version.hpp'
-
-        # 2. check if we can find BOOST libraries.
-        self.detect_lib_modules()
-        mlog.debug('Boost library directory is', mlog.bold(self.libdir))
-
-        mlog.debug('Installed Boost libraries: ')
-        for key in sorted(self.lib_modules.keys()):
-            mlog.debug(key, self.lib_modules[key])
+# We follow the following strategy for finding modules:
+# A) Detect potential boost root directories (uses also BOOST_ROOT env var)
+# B) Foreach candidate
+#   1. Look for the boost headers (boost/version.pp)
+#   2. Find all boost libraries
+#     2.1 Add all libraries in lib*
+#     2.2 Filter out non boost libraries
+#     2.3 Filter the renaining libraries based on the meson requirements (static/shared, etc.)
+#     2.4 Ensure that all libraries have the same boost tag (and are thus compatible)
+#   3. Select the libraries matching the requested modules
+
+@functools.total_ordering
+class BoostIncludeDir():
+    def __init__(self, path: Path, version_int: int):
+        self.path = path
+        self.version_int = version_int
+        major = int(self.version_int / 100000)
+        minor = int((self.version_int / 100) % 1000)
+        patch = int(self.version_int % 100)
+        self.version = f'{major}.{minor}.{patch}'
+        self.version_lib = f'{major}_{minor}'
+
+    def __repr__(self) -> str:
+        return f''
+
+    def __lt__(self, other: object) -> bool:
+        if isinstance(other, BoostIncludeDir):
+            return (self.version_int, self.path) < (other.version_int, other.path)
+        return NotImplemented
+
+@functools.total_ordering
+class BoostLibraryFile():
+    # Python libraries are special because of the included
+    # minor version in the module name.
+    boost_python_libs = ['boost_python', 'boost_numpy']
+    reg_python_mod_split = re.compile(r'(boost_[a-zA-Z]+)([0-9]*)')
+
+    reg_abi_tag = re.compile(r'^s?g?y?d?p?n?$')
+    reg_ver_tag = re.compile(r'^[0-9_]+$')
+
+    def __init__(self, path: Path):
+        self.path = path
+        self.name = self.path.name
+
+        # Initialize default properties
+        self.static = False
+        self.toolset = ''
+        self.arch = ''
+        self.version_lib = ''
+        self.mt = True
+
+        self.runtime_static = False
+        self.runtime_debug = False
+        self.python_debug = False
+        self.debug = False
+        self.stlport = False
+        self.deprecated_iostreams = False
+
+        # Post process the library name
+        name_parts = self.name.split('.')
+        self.basename = name_parts[0]
+        self.suffixes = name_parts[1:]
+        self.vers_raw = [x for x in self.suffixes if x.isdigit()]
+        self.suffixes = [x for x in self.suffixes if not x.isdigit()]
+        self.nvsuffix = '.'.join(self.suffixes)  # Used for detecting the library type
+        self.nametags = self.basename.split('-')
+        self.mod_name = self.nametags[0]
+        if self.mod_name.startswith('lib'):
+            self.mod_name = self.mod_name[3:]
+
+        # Set library version if possible
+        if len(self.vers_raw) >= 2:
+            self.version_lib = '{}_{}'.format(self.vers_raw[0], self.vers_raw[1])
+
+        # Detecting library type
+        if self.nvsuffix in ['so', 'dll', 'dll.a', 'dll.lib', 'dylib']:
+            self.static = False
+        elif self.nvsuffix in ['a', 'lib']:
+            self.static = True
+        else:
+            raise DependencyException(f'Unable to process library extension "{self.nvsuffix}" ({self.path})')
 
-        # 3. check if requested modules are valid, that is, either found or in the list of known boost libraries
-        self.check_invalid_modules()
+        # boost_.lib is the dll import library
+        if self.basename.startswith('boost_') and self.nvsuffix == 'lib':
+            self.static = False
+
+        # Process tags
+        tags = self.nametags[1:]
+        # Filter out the python version tag and fix modname
+        if self.is_python_lib():
+            tags = self.fix_python_name(tags)
+        if not tags:
+            return
 
-        # 4. final check whether or not we find all requested and valid modules
-        self.check_find_requested_modules()
+        # Without any tags mt is assumed, however, an absence of mt in the name
+        # with tags present indicates that the lib was built without mt support
+        self.mt = False
+        for i in tags:
+            if i == 'mt':
+                self.mt = True
+            elif len(i) == 3 and i[1:] in ['32', '64']:
+                self.arch = i
+            elif BoostLibraryFile.reg_abi_tag.match(i):
+                self.runtime_static = 's' in i
+                self.runtime_debug = 'g' in i
+                self.python_debug = 'y' in i
+                self.debug = 'd' in i
+                self.stlport = 'p' in i
+                self.deprecated_iostreams = 'n' in i
+            elif BoostLibraryFile.reg_ver_tag.match(i):
+                self.version_lib = i
+            else:
+                self.toolset = i
 
-    def check_invalid_modules(self):
-        invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in self.lib_modules and 'boost_' + c not in BOOST_LIBS]
+    def __repr__(self) -> str:
+        return f''
 
-        # previous versions of meson allowed include dirs as modules
-        remove = []
-        for m in invalid_modules:
-            if m in BOOST_DIRS:
-                mlog.warning('Requested boost library', mlog.bold(m), 'that doesn\'t exist. '
-                             'This will be an error in the future')
-                remove.append(m)
+    def __lt__(self, other: object) -> bool:
+        if isinstance(other, BoostLibraryFile):
+            return (
+                self.mod_name, self.static, self.version_lib, self.arch,
+                not self.mt, not self.runtime_static,
+                not self.debug, self.runtime_debug, self.python_debug,
+                self.stlport, self.deprecated_iostreams,
+                self.name,
+            ) < (
+                other.mod_name, other.static, other.version_lib, other.arch,
+                not other.mt, not other.runtime_static,
+                not other.debug, other.runtime_debug, other.python_debug,
+                other.stlport, other.deprecated_iostreams,
+                other.name,
+            )
+        return NotImplemented
+
+    def __eq__(self, other: object) -> bool:
+        if isinstance(other, BoostLibraryFile):
+            return self.name == other.name
+        return NotImplemented
+
+    def __hash__(self) -> int:
+        return hash(self.name)
+
+    @property
+    def abitag(self) -> str:
+        abitag = ''
+        abitag += 'S' if self.static else '-'
+        abitag += 'M' if self.mt else '-'
+        abitag += ' '
+        abitag += 's' if self.runtime_static else '-'
+        abitag += 'g' if self.runtime_debug else '-'
+        abitag += 'y' if self.python_debug else '-'
+        abitag += 'd' if self.debug else '-'
+        abitag += 'p' if self.stlport else '-'
+        abitag += 'n' if self.deprecated_iostreams else '-'
+        abitag += ' ' + (self.arch or '???')
+        abitag += ' ' + (self.toolset or '?')
+        abitag += ' ' + (self.version_lib or 'x_xx')
+        return abitag
+
+    def is_boost(self) -> bool:
+        return any([self.name.startswith(x) for x in ['libboost_', 'boost_']])
+
+    def is_python_lib(self) -> bool:
+        return any([self.mod_name.startswith(x) for x in BoostLibraryFile.boost_python_libs])
+
+    def fix_python_name(self, tags: T.List[str]) -> T.List[str]:
+        # Handle the boost_python naming madeness.
+        # See https://github.com/mesonbuild/meson/issues/4788 for some distro
+        # specific naming variations.
+        other_tags = []  # type: T.List[str]
+
+        # Split the current modname into the base name and the version
+        m_cur = BoostLibraryFile.reg_python_mod_split.match(self.mod_name)
+        cur_name = m_cur.group(1)
+        cur_vers = m_cur.group(2)
+
+        # Update the current version string if the new version string is longer
+        def update_vers(new_vers: str) -> None:
+            nonlocal cur_vers
+            new_vers = new_vers.replace('_', '')
+            new_vers = new_vers.replace('.', '')
+            if not new_vers.isdigit():
+                return
+            if len(new_vers) > len(cur_vers):
+                cur_vers = new_vers
+
+        for i in tags:
+            if i.startswith('py'):
+                update_vers(i[2:])
+            elif i.isdigit():
+                update_vers(i)
+            elif len(i) >= 3 and i[0].isdigit and i[2].isdigit() and i[1] == '.':
+                update_vers(i)
+            else:
+                other_tags += [i]
 
-        self.requested_modules = [x for x in self.requested_modules if x not in remove]
-        invalid_modules = [x for x in invalid_modules if x not in remove]
+        self.mod_name = cur_name + cur_vers
+        return other_tags
 
-        if invalid_modules:
-            mlog.error('Invalid Boost modules: ' + ', '.join(invalid_modules))
+    def mod_name_matches(self, mod_name: str) -> bool:
+        if self.mod_name == mod_name:
             return True
-        else:
+        if not self.is_python_lib():
             return False
 
-    def log_details(self):
-        module_str = ', '.join(self.requested_modules)
-        return module_str
+        m_cur = BoostLibraryFile.reg_python_mod_split.match(self.mod_name)
+        m_arg = BoostLibraryFile.reg_python_mod_split.match(mod_name)
 
-    def log_info(self):
-        if self.boost_root:
-            return self.boost_root
-        return ''
+        if not m_cur or not m_arg:
+            return False
 
-    def detect_nix_roots(self):
-        return [os.path.abspath(os.path.join(x, '..'))
-                for x in self.clib_compiler.get_default_include_dirs()]
-
-    def detect_win_roots(self):
-        res = []
-        # Where boost documentation says it should be
-        globtext = 'C:\\Program Files\\boost\\boost_*'
-        files = glob.glob(globtext)
-        res.extend(files)
-
-        # Where boost built from source actually installs it
-        if os.path.isdir('C:\\Boost'):
-            res.append('C:\\Boost')
-
-        # Where boost prebuilt binaries are
-        globtext = 'C:\\local\\boost_*'
-        files = glob.glob(globtext)
-        res.extend(files)
-        return res
+        if m_cur.group(1) != m_arg.group(1):
+            return False
 
-    def detect_nix_incdir(self):
-        if self.boost_root:
-            return os.path.join(self.boost_root, 'include')
-        return None
+        cur_vers = m_cur.group(2)
+        arg_vers = m_arg.group(2)
+
+        # Always assume python 2 if nothing is specified
+        if not arg_vers:
+            arg_vers = '2'
+
+        return cur_vers.startswith(arg_vers)
+
+    def version_matches(self, version_lib: str) -> bool:
+        # If no version tag is present, assume that it fits
+        if not self.version_lib or not version_lib:
+            return True
+        return self.version_lib == version_lib
 
-    # FIXME: Should pick a version that matches the requested version
-    # Returns the folder that contains the boost folder.
-    def detect_win_incdir(self):
-        for root in self.boost_roots:
-            globtext = os.path.join(root, 'include', 'boost-*')
-            incdirs = glob.glob(globtext)
-            if incdirs:
-                return incdirs[0]
-            incboostdir = os.path.join(root, 'include', 'boost')
-            if os.path.isdir(incboostdir):
-                return os.path.join(root, 'include')
-            incboostdir = os.path.join(root, 'boost')
-            if os.path.isdir(incboostdir):
-                return root
-        return None
-
-    def get_compile_args(self):
-        args = []
-        include_dir = self.incdir
-
-        # Use "-isystem" when including boost headers instead of "-I"
-        # to avoid compiler warnings/failures when "-Werror" is used
-
-        # Careful not to use "-isystem" on default include dirs as it
-        # breaks some of the headers for certain gcc versions
-
-        # For example, doing g++ -isystem /usr/include on a simple
-        # "int main()" source results in the error:
-        # "/usr/include/c++/6.3.1/cstdlib:75:25: fatal error: stdlib.h: No such file or directory"
-
-        # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129
-        # and http://stackoverflow.com/questions/37218953/isystem-on-a-system-include-directory-causes-errors
-        # for more details
+    def arch_matches(self, arch: str) -> bool:
+        # If no version tag is present, assume that it fits
+        if not self.arch or not arch:
+            return True
+        return self.arch == arch
 
-        if include_dir and include_dir not in self.clib_compiler.get_default_include_dirs():
-            args.append("".join(self.clib_compiler.get_include_args(include_dir, True)))
+    def vscrt_matches(self, vscrt: str) -> bool:
+        # If no vscrt tag present, assume that it fits  ['/MD', '/MDd', '/MT', '/MTd']
+        if not vscrt:
+            return True
+        if vscrt in ['/MD', '-MD']:
+            return not self.runtime_static and not self.runtime_debug
+        elif vscrt in ['/MDd', '-MDd']:
+            return not self.runtime_static and self.runtime_debug
+        elif vscrt in ['/MT', '-MT']:
+            return (self.runtime_static or not self.static) and not self.runtime_debug
+        elif vscrt in ['/MTd', '-MTd']:
+            return (self.runtime_static or not self.static) and self.runtime_debug
+
+        mlog.warning(f'Boost: unknown vscrt tag {vscrt}. This may cause the compilation to fail. Please consider reporting this as a bug.', once=True)
+        return True
+
+    def get_compiler_args(self) -> T.List[str]:
+        args = []  # type: T.List[str]
+        if self.mod_name in boost_libraries:
+            libdef = boost_libraries[self.mod_name]  # type: BoostLibrary
+            if self.static:
+                args += libdef.static
+            else:
+                args += libdef.shared
+            if self.mt:
+                args += libdef.multi
+            else:
+                args += libdef.single
         return args
 
-    def get_requested(self, kwargs):
-        candidates = mesonlib.extract_as_list(kwargs, 'modules')
-        for c in candidates:
-            if not isinstance(c, str):
+    def get_link_args(self) -> T.List[str]:
+        return [self.path.as_posix()]
+
+class BoostDependency(SystemDependency):
+    def __init__(self, environment: Environment, kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__('boost', environment, kwargs, language='cpp')
+        buildtype = environment.coredata.get_option(mesonlib.OptionKey('buildtype'))
+        assert isinstance(buildtype, str)
+        self.debug = buildtype.startswith('debug')
+        self.multithreading = kwargs.get('threading', 'multi') == 'multi'
+
+        self.boost_root = None  # type: T.Optional[Path]
+        self.explicit_static = 'static' in kwargs
+
+        # Extract and validate modules
+        self.modules = mesonlib.extract_as_list(kwargs, 'modules')  # type: T.List[str]
+        for i in self.modules:
+            if not isinstance(i, str):
                 raise DependencyException('Boost module argument is not a string.')
-        return candidates
+            if i.startswith('boost_'):
+                raise DependencyException('Boost modules must be passed without the boost_ prefix')
 
-    def detect_headers_and_version(self):
-        try:
-            version = self.clib_compiler.get_define('BOOST_LIB_VERSION', '#include ', self.env, self.get_compile_args(), [], disable_cache=True)[0]
-        except mesonlib.EnvironmentException:
-            return
-        except TypeError:
-            return
-        # Remove quotes
-        version = version[1:-1]
-        # Fix version string
-        self.version = version.replace('_', '.')
-        self.is_found = True
-
-    def detect_lib_modules(self):
-        self.lib_modules = {}
-        # 1. Try to find modules using compiler.find_library( )
-        if self.find_libraries_with_abi_tags(self.abi_tags()):
-            pass
-        # 2. Fall back to the old method
-        else:
-            if self.env.machines[self.for_machine].is_windows():
-                self.detect_lib_modules_win()
-            else:
-                self.detect_lib_modules_nix()
+        self.modules_found = []    # type: T.List[str]
+        self.modules_missing = []  # type: T.List[str]
 
-    def check_find_requested_modules(self):
-        # 3. Check if we can find the modules
-        for m in self.requested_modules:
-            if 'boost_' + m not in self.lib_modules:
-                mlog.debug('Requested Boost library {!r} not found'.format(m))
+        # Do we need threads?
+        if 'thread' in self.modules:
+            if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})):
                 self.is_found = False
+                return
 
-    def modname_from_filename(self, filename):
-        modname = os.path.basename(filename)
-        modname = modname.split('.', 1)[0]
-        modname = modname.split('-', 1)[0]
-        if modname.startswith('libboost'):
-            modname = modname[3:]
-        return modname
-
-    def compiler_tag(self):
-        tag = None
-        compiler = self.env.detect_cpp_compiler(self.for_machine)
-        if self.env.machines[self.for_machine].is_windows():
-            if compiler.get_id() in ['msvc', 'clang-cl']:
-                comp_ts_version = compiler.get_toolset_version()
-                compiler_ts = comp_ts_version.split('.')
-                # FIXME - what about other compilers?
-                tag = '-vc{}{}'.format(compiler_ts[0], compiler_ts[1])
-            else:
-                tag = ''
-        return tag
+        # Try figuring out the architecture tag
+        self.arch = environment.machines[self.for_machine].cpu_family
+        self.arch = boost_arch_map.get(self.arch, None)
+
+        # First, look for paths specified in a machine file
+        props = self.env.properties[self.for_machine]
+        if any(x in self.env.properties[self.for_machine] for x in
+               ['boost_includedir', 'boost_librarydir', 'boost_root']):
+            self.detect_boost_machine_file(props)
+            return
 
-    def threading_tag(self):
-        if not self.is_multithreading:
-            return ''
-
-        if self.env.machines[self.for_machine].is_darwin():
-            # - Mac:      requires -mt for multithreading, so should not fall back to non-mt libraries.
-            return '-mt'
-        elif self.env.machines[self.for_machine].is_windows():
-            # - Windows:  requires -mt for multithreading, so should not fall back to non-mt libraries.
-            return '-mt'
-        else:
-            # - Linux:    leaves off -mt but libraries are multithreading-aware.
-            # - Cygwin:   leaves off -mt but libraries are multithreading-aware.
-            return ''
-
-    def version_tag(self):
-        return '-' + self.version.replace('.', '_')
-
-    def debug_tag(self):
-        return '-gd' if self.is_debug else ''
-
-    def arch_tag(self):
-        # currently only applies to windows msvc installed binaries
-        if self.env.detect_cpp_compiler(self.for_machine).get_id() not in ['msvc', 'clang-cl']:
-            return ''
-        # pre-compiled binaries only added arch tag for versions > 1.64
-        if float(self.version) < 1.65:
-            return ''
-        arch = detect_cpu_family(self.env.coredata.compilers.host)
-        if arch == 'x86':
-            return '-x32'
-        elif arch == 'x86_64':
-            return '-x64'
-        return ''
+        # Finally, look for paths from .pc files and from searching the filesystem
+        self.detect_roots()
 
-    def versioned_abi_tag(self):
-        return self.compiler_tag() + self.threading_tag() + self.debug_tag() + self.arch_tag() + self.version_tag()
+    def check_and_set_roots(self, roots: T.List[Path], use_system: bool) -> None:
+        roots = list(mesonlib.OrderedSet(roots))
+        for j in roots:
+            #   1. Look for the boost headers (boost/version.hpp)
+            mlog.debug(f'Checking potential boost root {j.as_posix()}')
+            inc_dirs = self.detect_inc_dirs(j)
+            inc_dirs = sorted(inc_dirs, reverse=True)  # Prefer the newer versions
+
+            # Early abort when boost is not found
+            if not inc_dirs:
+                continue
+
+            lib_dirs = self.detect_lib_dirs(j, use_system)
+            self.is_found = self.run_check(inc_dirs, lib_dirs)
+            if self.is_found:
+                self.boost_root = j
+                break
+
+    def detect_boost_machine_file(self, props: 'Properties') -> None:
+        """Detect boost with values in the machine file or environment.
+
+        The machine file values are defaulted to the environment values.
+        """
+        # XXX: if we had a TypedDict we wouldn't need this
+        incdir = props.get('boost_includedir')
+        assert incdir is None or isinstance(incdir, str)
+        libdir = props.get('boost_librarydir')
+        assert libdir is None or isinstance(libdir, str)
+
+        if incdir and libdir:
+            inc_dir = Path(incdir)
+            lib_dir = Path(libdir)
+
+            if not inc_dir.is_absolute() or not lib_dir.is_absolute():
+                raise DependencyException('Paths given for boost_includedir and boost_librarydir in machine file must be absolute')
+
+            mlog.debug('Trying to find boost with:')
+            mlog.debug(f'  - boost_includedir = {inc_dir}')
+            mlog.debug(f'  - boost_librarydir = {lib_dir}')
+
+            return self.detect_split_root(inc_dir, lib_dir)
+
+        elif incdir or libdir:
+            raise DependencyException('Both boost_includedir *and* boost_librarydir have to be set in your machine file (one is not enough)')
+
+        rootdir = props.get('boost_root')
+        # It shouldn't be possible to get here without something in boost_root
+        assert rootdir
+
+        raw_paths = mesonlib.stringlistify(rootdir)
+        paths = [Path(x) for x in raw_paths]
+        if paths and any([not x.is_absolute() for x in paths]):
+            raise DependencyException('boost_root path given in machine file must be absolute')
+
+        self.check_and_set_roots(paths, use_system=False)
+
+    def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) -> bool:
+        mlog.debug('  - potential library dirs: {}'.format([x.as_posix() for x in lib_dirs]))
+        mlog.debug('  - potential include dirs: {}'.format([x.path.as_posix() for x in inc_dirs]))
+
+        #   2. Find all boost libraries
+        libs = []  # type: T.List[BoostLibraryFile]
+        for i in lib_dirs:
+            libs = self.detect_libraries(i)
+            if libs:
+                mlog.debug(f'  - found boost library dir: {i}')
+                # mlog.debug('  - raw library list:')
+                # for j in libs:
+                #     mlog.debug('    - {}'.format(j))
+                break
+        libs = sorted(set(libs))
+
+        modules = ['boost_' + x for x in self.modules]
+        for inc in inc_dirs:
+            mlog.debug(f'  - found boost {inc.version} include dir: {inc.path}')
+            f_libs = self.filter_libraries(libs, inc.version_lib)
+
+            mlog.debug('  - filtered library list:')
+            for j in f_libs:
+                mlog.debug(f'    - {j}')
+
+            #   3. Select the libraries matching the requested modules
+            not_found = []  # type: T.List[str]
+            selected_modules = []  # type: T.List[BoostLibraryFile]
+            for mod in modules:
+                found = False
+                for l in f_libs:
+                    if l.mod_name_matches(mod):
+                        selected_modules += [l]
+                        found = True
+                        break
+                if not found:
+                    not_found += [mod]
 
-    # FIXME - how to handle different distributions, e.g. for Mac? Currently we handle homebrew and macports, but not fink.
-    def abi_tags(self):
-        if self.env.machines[self.for_machine].is_windows():
-            return [self.versioned_abi_tag(), self.threading_tag()]
-        else:
-            return [self.threading_tag()]
+            # log the result
+            mlog.debug('  - found:')
+            comp_args = []  # type: T.List[str]
+            link_args = []  # type: T.List[str]
+            for j in selected_modules:
+                c_args = j.get_compiler_args()
+                l_args = j.get_link_args()
+                mlog.debug('    - {:<24} link={} comp={}'.format(j.mod_name, str(l_args), str(c_args)))
+                comp_args += c_args
+                link_args += l_args
+
+            comp_args = list(set(comp_args))
+            link_args = list(set(link_args))
+
+            self.modules_found = [x.mod_name for x in selected_modules]
+            self.modules_found = [x[6:] for x in self.modules_found]
+            self.modules_found = sorted(set(self.modules_found))
+            self.modules_missing = not_found
+            self.modules_missing = [x[6:] for x in self.modules_missing]
+            self.modules_missing = sorted(set(self.modules_missing))
+
+            # if we found all modules we are done
+            if not not_found:
+                self.version = inc.version
+                self.compile_args = ['-I' + inc.path.as_posix()]
+                self.compile_args += comp_args
+                self.compile_args += self._extra_compile_args()
+                self.compile_args = list(mesonlib.OrderedSet(self.compile_args))
+                self.link_args = link_args
+                mlog.debug(f'  - final compile args: {self.compile_args}')
+                mlog.debug(f'  - final link args:    {self.link_args}')
+                return True
 
-    def sourceforge_dir(self):
-        if self.env.detect_cpp_compiler(self.for_machine).get_id() != 'msvc':
-            return None
-        comp_ts_version = self.env.detect_cpp_compiler(self.for_machine).get_toolset_version()
-        arch = detect_cpu_family(self.env.coredata.compilers.host)
-        if arch == 'x86':
-            return 'lib32-msvc-{}'.format(comp_ts_version)
-        elif arch == 'x86_64':
-            return 'lib64-msvc-{}'.format(comp_ts_version)
-        else:
-            # Does anyone do Boost cross-compiling to other archs on Windows?
-            return None
+            # in case we missed something log it and try again
+            mlog.debug('  - NOT found:')
+            for mod in not_found:
+                mlog.debug(f'    - {mod}')
 
-    def find_libraries_with_abi_tag(self, tag):
+        return False
 
-        # All modules should have the same tag
-        self.lib_modules = {}
+    def detect_inc_dirs(self, root: Path) -> T.List[BoostIncludeDir]:
+        candidates = []  # type: T.List[Path]
+        inc_root = root / 'include'
+
+        candidates += [root / 'boost']
+        candidates += [inc_root / 'boost']
+        if inc_root.is_dir():
+            for i in inc_root.iterdir():
+                if not i.is_dir() or not i.name.startswith('boost-'):
+                    continue
+                candidates += [i / 'boost']
+        candidates = [x for x in candidates if x.is_dir()]
+        candidates = [x / 'version.hpp' for x in candidates]
+        candidates = [x for x in candidates if x.exists()]
+        return [self._include_dir_from_version_header(x) for x in candidates]
+
+    def detect_lib_dirs(self, root: Path, use_system: bool) -> T.List[Path]:
+        # First check the system include paths. Only consider those within the
+        # given root path
+
+        if use_system:
+            system_dirs_t = self.clib_compiler.get_library_dirs(self.env)
+            system_dirs = [Path(x) for x in system_dirs_t]
+            system_dirs = [x.resolve() for x in system_dirs if x.exists()]
+            system_dirs = [x for x in system_dirs if mesonlib.path_is_in_root(x, root)]
+            system_dirs = list(mesonlib.OrderedSet(system_dirs))
+
+            if system_dirs:
+                return system_dirs
+
+        # No system include paths were found --> fall back to manually looking
+        # for library dirs in root
+        dirs = []     # type: T.List[Path]
+        subdirs = []  # type: T.List[Path]
+        for i in root.iterdir():
+            if i.is_dir() and i.name.startswith('lib'):
+                dirs += [i]
+
+        # Some distros put libraries not directly inside /usr/lib but in /usr/lib/x86_64-linux-gnu
+        for i in dirs:
+            for j in i.iterdir():
+                if j.is_dir() and j.name.endswith('-linux-gnu'):
+                    subdirs += [j]
+
+        # Filter out paths that don't match the target arch to avoid finding
+        # the wrong libraries. See https://github.com/mesonbuild/meson/issues/7110
+        if not self.arch:
+            return dirs + subdirs
+
+        arch_list_32 = ['32', 'i386']
+        arch_list_64 = ['64']
+
+        raw_list = dirs + subdirs
+        no_arch = [x for x in raw_list if not any([y in x.name for y in arch_list_32 + arch_list_64])]
+
+        matching_arch = []  # type: T.List[Path]
+        if '32' in self.arch:
+            matching_arch = [x for x in raw_list if any([y in x.name for y in arch_list_32])]
+        elif '64' in self.arch:
+            matching_arch = [x for x in raw_list if any([y in x.name for y in arch_list_64])]
+
+        return sorted(matching_arch) + sorted(no_arch)
+
+    def filter_libraries(self, libs: T.List[BoostLibraryFile], lib_vers: str) -> T.List[BoostLibraryFile]:
+        # MSVC is very picky with the library tags
+        vscrt = ''
+        try:
+            crt_val = self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value
+            buildtype = self.env.coredata.options[mesonlib.OptionKey('buildtype')].value
+            vscrt = self.clib_compiler.get_crt_compile_args(crt_val, buildtype)[0]
+        except (KeyError, IndexError, AttributeError):
+            pass
 
-        all_found = True
+        # mlog.debug('    - static: {}'.format(self.static))
+        # mlog.debug('    - not explicit static: {}'.format(not self.explicit_static))
+        # mlog.debug('    - mt: {}'.format(self.multithreading))
+        # mlog.debug('    - version: {}'.format(lib_vers))
+        # mlog.debug('    - arch: {}'.format(self.arch))
+        # mlog.debug('    - vscrt: {}'.format(vscrt))
+        libs = [x for x in libs if x.static == self.static or not self.explicit_static]
+        libs = [x for x in libs if x.mt == self.multithreading]
+        libs = [x for x in libs if x.version_matches(lib_vers)]
+        libs = [x for x in libs if x.arch_matches(self.arch)]
+        libs = [x for x in libs if x.vscrt_matches(vscrt)]
+        libs = [x for x in libs if x.nvsuffix != 'dll']  # Only link to import libraries
+
+        # Only filter by debug when we are building in release mode. Debug
+        # libraries are automatically preferred through sorting otherwise.
+        if not self.debug:
+            libs = [x for x in libs if not x.debug]
+
+        # Take the abitag from the first library and filter by it. This
+        # ensures that we have a set of libraries that are always compatible.
+        if not libs:
+            return []
+        abitag = libs[0].abitag
+        libs = [x for x in libs if x.abitag == abitag]
+
+        return libs
+
+    def detect_libraries(self, libdir: Path) -> T.List[BoostLibraryFile]:
+        libs = set()  # type: T.Set[BoostLibraryFile]
+        for i in libdir.iterdir():
+            if not i.is_file():
+                continue
+            if not any([i.name.startswith(x) for x in ['libboost_', 'boost_']]):
+                continue
+
+            libs.add(BoostLibraryFile(i.resolve()))
+
+        return [x for x in libs if x.is_boost()]  # Filter out no boost libraries
+
+    def detect_split_root(self, inc_dir: Path, lib_dir: Path) -> None:
+        boost_inc_dir = None
+        for j in [inc_dir / 'version.hpp', inc_dir / 'boost' / 'version.hpp']:
+            if j.is_file():
+                boost_inc_dir = self._include_dir_from_version_header(j)
+                break
+        if not boost_inc_dir:
+            self.is_found = False
+            return
 
-        for module in self.requested_modules:
-            libname = 'boost_' + module + tag
+        self.is_found = self.run_check([boost_inc_dir], [lib_dir])
 
-            args = self.clib_compiler.find_library(libname, self.env, self.extra_lib_dirs())
-            if args is None:
-                mlog.debug("Couldn\'t find library '{}' for boost module '{}'  (ABI tag = '{}')".format(libname, module, tag))
-                all_found = False
-            else:
-                mlog.debug('Link args for boost module "{}" are {}'.format(module, args))
-                self.lib_modules['boost_' + module] = args
+    def detect_roots(self) -> None:
+        roots = []  # type: T.List[Path]
 
-        return all_found
+        # Try getting the BOOST_ROOT from a boost.pc if it exists. This primarily
+        # allows BoostDependency to find boost from Conan. See #5438
+        try:
+            boost_pc = PkgConfigDependency('boost', self.env, {'required': False})
+            if boost_pc.found():
+                boost_root = boost_pc.get_pkgconfig_variable('prefix', {'default': None})
+                if boost_root:
+                    roots += [Path(boost_root)]
+        except DependencyException:
+            pass
 
-    def find_libraries_with_abi_tags(self, tags):
-        for tag in tags:
-            if self.find_libraries_with_abi_tag(tag):
-                return True
-        return False
+        # Add roots from system paths
+        inc_paths = [Path(x) for x in self.clib_compiler.get_default_include_dirs()]
+        inc_paths = [x.parent for x in inc_paths if x.exists()]
+        inc_paths = [x.resolve() for x in inc_paths]
+        roots += inc_paths
 
-    def detect_lib_modules_win(self):
-        if not self.libdir:
-            # The libdirs in the distributed binaries (from sf)
-            lib_sf = self.sourceforge_dir()
+        # Add system paths
+        if self.env.machines[self.for_machine].is_windows():
+            # Where boost built from source actually installs it
+            c_root = Path('C:/Boost')
+            if c_root.is_dir():
+                roots += [c_root]
+
+            # Where boost documentation says it should be
+            prog_files = Path('C:/Program Files/boost')
+            # Where boost prebuilt binaries are
+            local_boost = Path('C:/local')
+
+            candidates = []  # type: T.List[Path]
+            if prog_files.is_dir():
+                candidates += [*prog_files.iterdir()]
+            if local_boost.is_dir():
+                candidates += [*local_boost.iterdir()]
 
-            if self.boost_root:
-                roots = [self.boost_root]
-            else:
-                roots = self.boost_roots
-            for root in roots:
-                # The default libdir when building
-                libdir = os.path.join(root, 'lib')
-                if os.path.isdir(libdir):
-                    self.libdir = libdir
-                    break
-                if lib_sf:
-                    full_path = os.path.join(root, lib_sf)
-                    if os.path.isdir(full_path):
-                        self.libdir = full_path
-                        break
+            roots += [x for x in candidates if x.name.lower().startswith('boost') and x.is_dir()]
+        else:
+            tmp = []  # type: T.List[Path]
 
-        if not self.libdir:
-            return
+            # Add some default system paths
+            tmp += [Path('/opt/local')]
+            tmp += [Path('/usr/local/opt/boost')]
+            tmp += [Path('/usr/local')]
+            tmp += [Path('/usr')]
+
+            # Cleanup paths
+            tmp = [x for x in tmp if x.is_dir()]
+            tmp = [x.resolve() for x in tmp]
+            roots += tmp
+
+        self.check_and_set_roots(roots, use_system=True)
+
+    def log_details(self) -> str:
+        res = ''
+        if self.modules_found:
+            res += 'found: ' + ', '.join(self.modules_found)
+        if self.modules_missing:
+            if res:
+                res += ' | '
+            res += 'missing: ' + ', '.join(self.modules_missing)
+        return res
 
-        for name in self.need_static_link:
-            # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a
-            libname = 'lib' + name + self.versioned_abi_tag() + '.lib'
-            if os.path.isfile(os.path.join(self.libdir, libname)):
-                self.lib_modules[self.modname_from_filename(libname)] = [libname]
-            else:
-                libname = "lib{}.lib".format(name)
-                if os.path.isfile(os.path.join(self.libdir, libname)):
-                    self.lib_modules[name[3:]] = [libname]
-
-        # globber1 applies to a layout=system installation
-        # globber2 applies to a layout=versioned installation
-        globber1 = 'libboost_*' if self.static else 'boost_*'
-        globber2 = globber1 + self.versioned_abi_tag()
-        # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a
-        globber2_matches = glob.glob(os.path.join(self.libdir, globber2 + '.lib'))
-        for entry in globber2_matches:
-            fname = os.path.basename(entry)
-            self.lib_modules[self.modname_from_filename(fname)] = [fname]
-        if not globber2_matches:
-            # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a
-            for entry in glob.glob(os.path.join(self.libdir, globber1 + '.lib')):
-                if self.static:
-                    fname = os.path.basename(entry)
-                    self.lib_modules[self.modname_from_filename(fname)] = [fname]
-
-    def detect_lib_modules_nix(self):
-        if self.static:
-            libsuffix = 'a'
-        elif self.env.machines[self.for_machine].is_darwin():
-            libsuffix = 'dylib'
-        else:
-            libsuffix = 'so'
+    def log_info(self) -> str:
+        if self.boost_root:
+            return self.boost_root.as_posix()
+        return ''
 
-        globber = 'libboost_*.{}'.format(libsuffix)
-        if self.libdir:
-            libdirs = [self.libdir]
-        elif self.boost_root is None:
-            libdirs = mesonlib.get_library_dirs()
-        else:
-            libdirs = [os.path.join(self.boost_root, 'lib')]
-        for libdir in libdirs:
-            for name in self.need_static_link:
-                libname = 'lib{}.a'.format(name)
-                if os.path.isfile(os.path.join(libdir, libname)):
-                    self.lib_modules[name] = [libname]
-            for entry in glob.glob(os.path.join(libdir, globber)):
-                # I'm not 100% sure what to do here. Some distros
-                # have modules such as thread only as -mt versions.
-                # On debian all packages are built threading=multi
-                # but not suffixed with -mt.
-                # FIXME: implement detect_lib_modules_{debian, redhat, ...}
-                # FIXME: this wouldn't work with -mt-gd either. -BDR
-                if self.is_multithreading and mesonlib.is_debianlike():
-                    pass
-                elif self.is_multithreading and entry.endswith('-mt.{}'.format(libsuffix)):
-                    pass
-                elif not entry.endswith('-mt.{}'.format(libsuffix)):
-                    pass
-                else:
-                    continue
-                modname = self.modname_from_filename(entry)
-                if modname not in self.lib_modules:
-                    self.lib_modules[modname] = [entry]
-
-    def extra_lib_dirs(self):
-        if self.libdir:
-            return [self.libdir]
-        elif self.boost_root:
-            return [os.path.join(self.boost_root, 'lib')]
-        return []
-
-    def get_link_args(self, **kwargs):
-        args = []
-        for d in self.extra_lib_dirs():
-            args += self.clib_compiler.get_linker_search_args(d)
-        for lib in self.requested_modules:
-            args += self.lib_modules['boost_' + lib]
-        return args
+    def _include_dir_from_version_header(self, hfile: Path) -> BoostIncludeDir:
+        # Extract the version with a regex. Using clib_compiler.get_define would
+        # also work, however, this is slower (since it the compiler has to be
+        # invoked) and overkill since the layout of the header is always the same.
+        assert hfile.exists()
+        raw = hfile.read_text(encoding='utf-8')
+        m = re.search(r'#define\s+BOOST_VERSION\s+([0-9]+)', raw)
+        if not m:
+            mlog.debug(f'Failed to extract version information from {hfile}')
+            return BoostIncludeDir(hfile.parents[1], 0)
+        return BoostIncludeDir(hfile.parents[1], int(m.group(1)))
+
+    def _extra_compile_args(self) -> T.List[str]:
+        # BOOST_ALL_DYN_LINK should not be required with the known defines below
+        return ['-DBOOST_ALL_NO_LIB']  # Disable automatic linking
+
+
+# See https://www.boost.org/doc/libs/1_72_0/more/getting_started/unix-variants.html#library-naming
+# See https://mesonbuild.com/Reference-tables.html#cpu-families
+boost_arch_map = {
+    'aarch64': 'a64',
+    'arc': 'a32',
+    'arm': 'a32',
+    'ia64': 'i64',
+    'mips': 'm32',
+    'mips64': 'm64',
+    'ppc': 'p32',
+    'ppc64': 'p64',
+    'sparc': 's32',
+    'sparc64': 's64',
+    'x86': 'x32',
+    'x86_64': 'x64',
+}
+
+
+####      ---- BEGIN GENERATED ----      ####
+#                                           #
+# Generated with tools/boost_names.py:
+#  - boost version:   1.73.0
+#  - modules found:   159
+#  - libraries found: 43
+#
 
-    def get_sources(self):
-        return []
+class BoostLibrary():
+    def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]):
+        self.name = name
+        self.shared = shared
+        self.static = static
+        self.single = single
+        self.multi = multi
+
+class BoostModule():
+    def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
+        self.name = name
+        self.key = key
+        self.desc = desc
+        self.libs = libs
+
+
+# dict of all know libraries with additional compile options
+boost_libraries = {
+    'boost_atomic': BoostLibrary(
+        name='boost_atomic',
+        shared=['-DBOOST_ATOMIC_DYN_LINK=1'],
+        static=['-DBOOST_ATOMIC_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_chrono': BoostLibrary(
+        name='boost_chrono',
+        shared=['-DBOOST_CHRONO_DYN_LINK=1'],
+        static=['-DBOOST_CHRONO_STATIC_LINK=1'],
+        single=['-DBOOST_CHRONO_THREAD_DISABLED'],
+        multi=[],
+    ),
+    'boost_container': BoostLibrary(
+        name='boost_container',
+        shared=['-DBOOST_CONTAINER_DYN_LINK=1'],
+        static=['-DBOOST_CONTAINER_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_context': BoostLibrary(
+        name='boost_context',
+        shared=['-DBOOST_CONTEXT_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_contract': BoostLibrary(
+        name='boost_contract',
+        shared=['-DBOOST_CONTRACT_DYN_LINK'],
+        static=['-DBOOST_CONTRACT_STATIC_LINK'],
+        single=['-DBOOST_CONTRACT_DISABLE_THREADS'],
+        multi=[],
+    ),
+    'boost_coroutine': BoostLibrary(
+        name='boost_coroutine',
+        shared=['-DBOOST_COROUTINES_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_date_time': BoostLibrary(
+        name='boost_date_time',
+        shared=['-DBOOST_DATE_TIME_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_exception': BoostLibrary(
+        name='boost_exception',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_fiber': BoostLibrary(
+        name='boost_fiber',
+        shared=['-DBOOST_FIBERS_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_fiber_numa': BoostLibrary(
+        name='boost_fiber_numa',
+        shared=['-DBOOST_FIBERS_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_filesystem': BoostLibrary(
+        name='boost_filesystem',
+        shared=['-DBOOST_FILESYSTEM_DYN_LINK=1'],
+        static=['-DBOOST_FILESYSTEM_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_graph': BoostLibrary(
+        name='boost_graph',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_iostreams': BoostLibrary(
+        name='boost_iostreams',
+        shared=['-DBOOST_IOSTREAMS_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_locale': BoostLibrary(
+        name='boost_locale',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_log': BoostLibrary(
+        name='boost_log',
+        shared=['-DBOOST_LOG_DYN_LINK=1'],
+        static=[],
+        single=['-DBOOST_LOG_NO_THREADS'],
+        multi=[],
+    ),
+    'boost_log_setup': BoostLibrary(
+        name='boost_log_setup',
+        shared=['-DBOOST_LOG_SETUP_DYN_LINK=1'],
+        static=[],
+        single=['-DBOOST_LOG_NO_THREADS'],
+        multi=[],
+    ),
+    'boost_math_c99': BoostLibrary(
+        name='boost_math_c99',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_c99f': BoostLibrary(
+        name='boost_math_c99f',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_c99l': BoostLibrary(
+        name='boost_math_c99l',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_tr1': BoostLibrary(
+        name='boost_math_tr1',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_tr1f': BoostLibrary(
+        name='boost_math_tr1f',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_tr1l': BoostLibrary(
+        name='boost_math_tr1l',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_mpi': BoostLibrary(
+        name='boost_mpi',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_nowide': BoostLibrary(
+        name='boost_nowide',
+        shared=['-DBOOST_NOWIDE_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_prg_exec_monitor': BoostLibrary(
+        name='boost_prg_exec_monitor',
+        shared=['-DBOOST_TEST_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_program_options': BoostLibrary(
+        name='boost_program_options',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_random': BoostLibrary(
+        name='boost_random',
+        shared=['-DBOOST_RANDOM_DYN_LINK'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_regex': BoostLibrary(
+        name='boost_regex',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_serialization': BoostLibrary(
+        name='boost_serialization',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_addr2line': BoostLibrary(
+        name='boost_stacktrace_addr2line',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_backtrace': BoostLibrary(
+        name='boost_stacktrace_backtrace',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_basic': BoostLibrary(
+        name='boost_stacktrace_basic',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_noop': BoostLibrary(
+        name='boost_stacktrace_noop',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_windbg': BoostLibrary(
+        name='boost_stacktrace_windbg',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_windbg_cached': BoostLibrary(
+        name='boost_stacktrace_windbg_cached',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_system': BoostLibrary(
+        name='boost_system',
+        shared=['-DBOOST_SYSTEM_DYN_LINK=1'],
+        static=['-DBOOST_SYSTEM_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_test_exec_monitor': BoostLibrary(
+        name='boost_test_exec_monitor',
+        shared=['-DBOOST_TEST_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_thread': BoostLibrary(
+        name='boost_thread',
+        shared=['-DBOOST_THREAD_BUILD_DLL=1', '-DBOOST_THREAD_USE_DLL=1'],
+        static=['-DBOOST_THREAD_BUILD_LIB=1', '-DBOOST_THREAD_USE_LIB=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_timer': BoostLibrary(
+        name='boost_timer',
+        shared=['-DBOOST_TIMER_DYN_LINK=1'],
+        static=['-DBOOST_TIMER_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_type_erasure': BoostLibrary(
+        name='boost_type_erasure',
+        shared=['-DBOOST_TYPE_ERASURE_DYN_LINK'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_unit_test_framework': BoostLibrary(
+        name='boost_unit_test_framework',
+        shared=['-DBOOST_TEST_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_wave': BoostLibrary(
+        name='boost_wave',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_wserialization': BoostLibrary(
+        name='boost_wserialization',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+}
 
-# Generated with boost_names.py
-BOOST_LIBS = [
-    'boost_atomic',
-    'boost_chrono',
-    'boost_chrono',
-    'boost_container',
-    'boost_context',
-    'boost_coroutine',
-    'boost_date_time',
-    'boost_exception',
-    'boost_fiber',
-    'boost_filesystem',
-    'boost_graph',
-    'boost_iostreams',
-    'boost_locale',
-    'boost_log',
-    'boost_log_setup',
-    'boost_math_tr1',
-    'boost_math_tr1f',
-    'boost_math_tr1l',
-    'boost_math_c99',
-    'boost_math_c99f',
-    'boost_math_c99l',
-    'boost_math_tr1',
-    'boost_math_tr1f',
-    'boost_math_tr1l',
-    'boost_math_c99',
-    'boost_math_c99f',
-    'boost_math_c99l',
-    'boost_math_tr1',
-    'boost_math_tr1f',
-    'boost_math_tr1l',
-    'boost_math_c99',
-    'boost_math_c99f',
-    'boost_math_c99l',
-    'boost_math_tr1',
-    'boost_math_tr1f',
-    'boost_math_tr1l',
-    'boost_math_c99',
-    'boost_math_c99f',
-    'boost_math_c99l',
-    'boost_math_tr1',
-    'boost_math_tr1f',
-    'boost_math_tr1l',
-    'boost_math_c99',
-    'boost_math_c99f',
-    'boost_math_c99l',
-    'boost_math_tr1',
-    'boost_math_tr1f',
-    'boost_math_tr1l',
-    'boost_math_c99',
-    'boost_math_c99f',
-    'boost_math_c99l',
-    'boost_mpi',
-    'boost_program_options',
-    'boost_random',
-    'boost_regex',
-    'boost_serialization',
-    'boost_wserialization',
-    'boost_signals',
-    'boost_stacktrace_noop',
-    'boost_stacktrace_backtrace',
-    'boost_stacktrace_addr2line',
-    'boost_stacktrace_basic',
-    'boost_stacktrace_windbg',
-    'boost_stacktrace_windbg_cached',
-    'boost_system',
-    'boost_prg_exec_monitor',
-    'boost_test_exec_monitor',
-    'boost_unit_test_framework',
-    'boost_thread',
-    'boost_timer',
-    'boost_type_erasure',
-    'boost_wave'
-]
-
-BOOST_DIRS = [
-    'lambda',
-    'optional',
-    'convert',
-    'system',
-    'uuid',
-    'archive',
-    'align',
-    'timer',
-    'chrono',
-    'gil',
-    'logic',
-    'signals',
-    'predef',
-    'tr1',
-    'multi_index',
-    'property_map',
-    'multi_array',
-    'context',
-    'random',
-    'endian',
-    'circular_buffer',
-    'proto',
-    'assign',
-    'format',
-    'math',
-    'phoenix',
-    'graph',
-    'locale',
-    'mpl',
-    'pool',
-    'unordered',
-    'core',
-    'exception',
-    'ptr_container',
-    'flyweight',
-    'range',
-    'typeof',
-    'thread',
-    'move',
-    'spirit',
-    'dll',
-    'compute',
-    'serialization',
-    'ratio',
-    'msm',
-    'config',
-    'metaparse',
-    'coroutine2',
-    'qvm',
-    'program_options',
-    'concept',
-    'detail',
-    'hana',
-    'concept_check',
-    'compatibility',
-    'variant',
-    'type_erasure',
-    'mpi',
-    'test',
-    'fusion',
-    'log',
-    'sort',
-    'local_function',
-    'units',
-    'functional',
-    'preprocessor',
-    'integer',
-    'container',
-    'polygon',
-    'interprocess',
-    'numeric',
-    'iterator',
-    'wave',
-    'lexical_cast',
-    'multiprecision',
-    'utility',
-    'tti',
-    'asio',
-    'dynamic_bitset',
-    'algorithm',
-    'xpressive',
-    'bimap',
-    'signals2',
-    'type_traits',
-    'regex',
-    'statechart',
-    'parameter',
-    'icl',
-    'python',
-    'lockfree',
-    'intrusive',
-    'io',
-    'pending',
-    'geometry',
-    'tuple',
-    'iostreams',
-    'heap',
-    'atomic',
-    'filesystem',
-    'smart_ptr',
-    'function',
-    'fiber',
-    'type_index',
-    'accumulators',
-    'function_types',
-    'coroutine',
-    'vmd',
-    'date_time',
-    'property_tree',
-    'bind'
-]
+#                                           #
+####       ---- END GENERATED ----       ####
diff -Nru meson-0.53.2/mesonbuild/dependencies/cmake.py meson-0.61.2/mesonbuild/dependencies/cmake.py
--- meson-0.53.2/mesonbuild/dependencies/cmake.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/cmake.py	2022-01-17 10:50:45.000000000 +0000
@@ -0,0 +1,644 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .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
+from pathlib import Path
+import functools
+import re
+import os
+import shutil
+import textwrap
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+    from ..envconfig import MachineInfo
+
+class CMakeInfo(T.NamedTuple):
+    module_paths: T.List[str]
+    cmake_root: str
+    archs: T.List[str]
+    common_paths: T.List[str]
+
+class CMakeDependency(ExternalDependency):
+    # The class's copy of the CMake path. Avoids having to search for it
+    # multiple times in the same Meson invocation.
+    class_cmakeinfo: PerMachine[T.Optional[CMakeInfo]] = PerMachine(None, None)
+    # Version string for the minimum CMake version
+    class_cmake_version = '>=3.4'
+    # CMake generators to try (empty for no generator)
+    class_cmake_generators = ['', 'Ninja', 'Unix Makefiles', 'Visual Studio 10 2010']
+    class_working_generator: T.Optional[str] = None
+
+    def _gen_exception(self, msg: str) -> DependencyException:
+        return DependencyException(f'Dependency {self.name} not found: {msg}')
+
+    def _main_cmake_file(self) -> str:
+        return 'CMakeLists.txt'
+
+    def _extra_cmake_opts(self) -> T.List[str]:
+        return []
+
+    def _map_module_list(self, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
+        # Map the input module list to something else
+        # This function will only be executed AFTER the initial CMake
+        # interpreter pass has completed. Thus variables defined in the
+        # CMakeLists.txt can be accessed here.
+        #
+        # Both the modules and components inputs contain the original lists.
+        return modules
+
+    def _map_component_list(self, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
+        # Map the input components list to something else. This
+        # function will be executed BEFORE the initial CMake interpreter
+        # pass. Thus variables from the CMakeLists.txt can NOT be accessed.
+        #
+        # Both the modules and components inputs contain the original lists.
+        return components
+
+    def _original_module_name(self, module: str) -> str:
+        # Reverse the module mapping done by _map_module_list for
+        # one module
+        return module
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        # Gather a list of all languages to support
+        self.language_list = []  # type: T.List[str]
+        if language is None:
+            compilers = None
+            if kwargs.get('native', False):
+                compilers = environment.coredata.compilers.build
+            else:
+                compilers = environment.coredata.compilers.host
+
+            candidates = ['c', 'cpp', 'fortran', 'objc', 'objcxx']
+            self.language_list += [x for x in candidates if x in compilers]
+        else:
+            self.language_list += [language]
+
+        # Add additional languages if required
+        if 'fortran' in self.language_list:
+            self.language_list += ['c']
+
+        # Ensure that the list is unique
+        self.language_list = list(set(self.language_list))
+
+        super().__init__(DependencyTypeName('cmake'), environment, kwargs, language=language)
+        self.name = name
+        self.is_libtool = False
+        # Store a copy of the CMake path on the object itself so it is
+        # stored in the pickled coredata and recovered.
+        self.cmakebin:  T.Optional[CMakeExecutor] = None
+        self.cmakeinfo: T.Optional[CMakeInfo]     = None
+
+        # Where all CMake "build dirs" are located
+        self.cmake_root_dir = environment.scratch_dir
+
+        # T.List of successfully found modules
+        self.found_modules: T.List[str] = []
+
+        # Initialize with None before the first return to avoid
+        # AttributeError exceptions in derived classes
+        self.traceparser: T.Optional[CMakeTraceParser] = None
+
+        # TODO further evaluate always using MachineChoice.BUILD
+        self.cmakebin = CMakeExecutor(environment, CMakeDependency.class_cmake_version, self.for_machine, silent=self.silent)
+        if not self.cmakebin.found():
+            self.cmakebin = None
+            msg = f'CMake binary for machine {self.for_machine} not found. Giving up.'
+            if self.required:
+                raise DependencyException(msg)
+            mlog.debug(msg)
+            return
+
+        # Setup the trace parser
+        self.traceparser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir())
+
+        cm_args = stringlistify(extract_as_list(kwargs, 'cmake_args'))
+        cm_args = check_cmake_args(cm_args)
+        if CMakeDependency.class_cmakeinfo[self.for_machine] is None:
+            CMakeDependency.class_cmakeinfo[self.for_machine] = self._get_cmake_info(cm_args)
+        self.cmakeinfo = CMakeDependency.class_cmakeinfo[self.for_machine]
+        if self.cmakeinfo is None:
+            raise self._gen_exception('Unable to obtain CMake system information')
+
+        package_version = kwargs.get('cmake_package_version', '')
+        if not isinstance(package_version, str):
+            raise DependencyException('Keyword "cmake_package_version" must be a string.')
+        components = [(x, True) for x in stringlistify(extract_as_list(kwargs, 'components'))]
+        modules = [(x, True) for x in stringlistify(extract_as_list(kwargs, 'modules'))]
+        modules += [(x, False) for x in stringlistify(extract_as_list(kwargs, 'optional_modules'))]
+        cm_path = stringlistify(extract_as_list(kwargs, 'cmake_module_path'))
+        cm_path = [x if os.path.isabs(x) else os.path.join(environment.get_source_dir(), x) for x in cm_path]
+        if cm_path:
+            cm_args.append('-DCMAKE_MODULE_PATH=' + ';'.join(cm_path))
+        if not self._preliminary_find_check(name, cm_path, self.cmakebin.get_cmake_prefix_paths(), environment.machines[self.for_machine]):
+            mlog.debug('Preliminary CMake check failed. Aborting.')
+            return
+        self._detect_dep(name, package_version, modules, components, cm_args)
+
+    def __repr__(self) -> str:
+        return f'<{self.__class__.__name__} {self.name}: {self.is_found} {self.version_reqs}>'
+
+    def _get_cmake_info(self, cm_args: T.List[str]) -> T.Optional[CMakeInfo]:
+        mlog.debug("Extracting basic cmake information")
+
+        # Try different CMake generators since specifying no generator may fail
+        # in cygwin for some reason
+        gen_list = []
+        # First try the last working generator
+        if CMakeDependency.class_working_generator is not None:
+            gen_list += [CMakeDependency.class_working_generator]
+        gen_list += CMakeDependency.class_cmake_generators
+
+        temp_parser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir())
+        toolchain = CMakeToolchain(self.cmakebin, self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
+        toolchain.write()
+
+        for i in gen_list:
+            mlog.debug('Try CMake generator: {}'.format(i if len(i) > 0 else 'auto'))
+
+            # Prepare options
+            cmake_opts = temp_parser.trace_args() + toolchain.get_cmake_args() + ['.']
+            cmake_opts += cm_args
+            if len(i) > 0:
+                cmake_opts = ['-G', i] + cmake_opts
+
+            # Run CMake
+            ret1, out1, err1 = self._call_cmake(cmake_opts, 'CMakePathInfo.txt')
+
+            # Current generator was successful
+            if ret1 == 0:
+                CMakeDependency.class_working_generator = i
+                break
+
+            mlog.debug(f'CMake failed to gather system information for generator {i} with error code {ret1}')
+            mlog.debug(f'OUT:\n{out1}\n\n\nERR:\n{err1}\n\n')
+
+        # Check if any generator succeeded
+        if ret1 != 0:
+            return None
+
+        try:
+            temp_parser.parse(err1)
+        except MesonException:
+            return None
+
+        def process_paths(l: T.List[str]) -> T.Set[str]:
+            if is_windows():
+                # Cannot split on ':' on Windows because its in the drive letter
+                tmp = [x.split(os.pathsep) for x in l]
+            else:
+                # https://github.com/mesonbuild/meson/issues/7294
+                tmp = [re.split(r':|;', x) for x in l]
+            flattened = [x for sublist in tmp for x in sublist]
+            return set(flattened)
+
+        # Extract the variables and sanity check them
+        root_paths_set = process_paths(temp_parser.get_cmake_var('MESON_FIND_ROOT_PATH'))
+        root_paths_set.update(process_paths(temp_parser.get_cmake_var('MESON_CMAKE_SYSROOT')))
+        root_paths = sorted(root_paths_set)
+        root_paths = [x for x in root_paths if os.path.isdir(x)]
+        module_paths_set = process_paths(temp_parser.get_cmake_var('MESON_PATHS_LIST'))
+        rooted_paths: T.List[str] = []
+        for j in [Path(x) for x in root_paths]:
+            for p in [Path(x) for x in module_paths_set]:
+                rooted_paths.append(str(j / p.relative_to(p.anchor)))
+        module_paths = sorted(module_paths_set.union(rooted_paths))
+        module_paths = [x for x in module_paths if os.path.isdir(x)]
+        archs = temp_parser.get_cmake_var('MESON_ARCH_LIST')
+
+        common_paths = ['lib', 'lib32', 'lib64', 'libx32', 'share']
+        for i in archs:
+            common_paths += [os.path.join('lib', i)]
+
+        res = CMakeInfo(
+            module_paths=module_paths,
+            cmake_root=temp_parser.get_cmake_var('MESON_CMAKE_ROOT')[0],
+            archs=archs,
+            common_paths=common_paths,
+        )
+
+        mlog.debug(f'  -- Module search paths:    {res.module_paths}')
+        mlog.debug(f'  -- CMake root:             {res.cmake_root}')
+        mlog.debug(f'  -- CMake architectures:    {res.archs}')
+        mlog.debug(f'  -- CMake lib search paths: {res.common_paths}')
+
+        return res
+
+    @staticmethod
+    @functools.lru_cache(maxsize=None)
+    def _cached_listdir(path: str) -> T.Tuple[T.Tuple[str, str], ...]:
+        try:
+            return tuple((x, str(x).lower()) for x in os.listdir(path))
+        except OSError:
+            return tuple()
+
+    @staticmethod
+    @functools.lru_cache(maxsize=None)
+    def _cached_isdir(path: str) -> bool:
+        try:
+            return os.path.isdir(path)
+        except OSError:
+            return False
+
+    def _preliminary_find_check(self, name: str, module_path: T.List[str], prefix_path: T.List[str], machine: 'MachineInfo') -> bool:
+        lname = str(name).lower()
+
+        # Checks , /cmake, /CMake
+        def find_module(path: str) -> bool:
+            for i in [path, os.path.join(path, 'cmake'), os.path.join(path, 'CMake')]:
+                if not self._cached_isdir(i):
+                    continue
+
+                # Check the directory case insensitive
+                content = self._cached_listdir(i)
+                candidates = ['Find{}.cmake', '{}Config.cmake', '{}-config.cmake']
+                candidates = [x.format(name).lower() for x in candidates]
+                if any([x[1] in candidates for x in content]):
+                    return True
+            return False
+
+        # Search in /(lib/|lib*|share) for cmake files
+        def search_lib_dirs(path: str) -> bool:
+            for i in [os.path.join(path, x) for x in self.cmakeinfo.common_paths]:
+                if not self._cached_isdir(i):
+                    continue
+
+                # Check /(lib/|lib*|share)/cmake/*/
+                cm_dir = os.path.join(i, 'cmake')
+                if self._cached_isdir(cm_dir):
+                    content = self._cached_listdir(cm_dir)
+                    content = tuple(x for x in content if x[1].startswith(lname))
+                    for k in content:
+                        if find_module(os.path.join(cm_dir, k[0])):
+                            return True
+
+                # /(lib/|lib*|share)/*/
+                # /(lib/|lib*|share)/*/(cmake|CMake)/
+                content = self._cached_listdir(i)
+                content = tuple(x for x in content if x[1].startswith(lname))
+                for k in content:
+                    if find_module(os.path.join(i, k[0])):
+                        return True
+
+            return False
+
+        # Check the user provided and system module paths
+        for i in module_path + [os.path.join(self.cmakeinfo.cmake_root, 'Modules')]:
+            if find_module(i):
+                return True
+
+        # Check the user provided prefix paths
+        for i in prefix_path:
+            if search_lib_dirs(i):
+                return True
+
+        # Check PATH
+        system_env = []  # type: T.List[str]
+        for i in os.environ.get('PATH', '').split(os.pathsep):
+            if i.endswith('/bin') or i.endswith('\\bin'):
+                i = i[:-4]
+            if i.endswith('/sbin') or i.endswith('\\sbin'):
+                i = i[:-5]
+            system_env += [i]
+
+        # Check the system paths
+        for i in self.cmakeinfo.module_paths + system_env:
+            if find_module(i):
+                return True
+
+            if search_lib_dirs(i):
+                return True
+
+            content = self._cached_listdir(i)
+            content = tuple(x for x in content if x[1].startswith(lname))
+            for k in content:
+                if search_lib_dirs(os.path.join(i, k[0])):
+                    return True
+
+            # Mac framework support
+            if machine.is_darwin():
+                for j in [f'{lname}.framework', f'{lname}.app']:
+                    for k in content:
+                        if k[1] != j:
+                            continue
+                        if find_module(os.path.join(i, k[0], 'Resources')) or find_module(os.path.join(i, k[0], 'Version')):
+                            return True
+
+        # Check the environment path
+        env_path = os.environ.get(f'{name}_DIR')
+        if env_path and find_module(env_path):
+            return True
+
+        # Check the Linux CMake registry
+        linux_reg = Path.home() / '.cmake' / 'packages'
+        for p in [linux_reg / name, linux_reg / lname]:
+            if p.exists():
+                return True
+
+        return False
+
+    def _detect_dep(self, name: str, package_version: str, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]], args: T.List[str]) -> None:
+        # Detect a dependency with CMake using the '--find-package' mode
+        # and the trace output (stderr)
+        #
+        # When the trace output is enabled CMake prints all functions with
+        # parameters to stderr as they are executed. Since CMake 3.4.0
+        # variables ("${VAR}") are also replaced in the trace output.
+        mlog.debug('\nDetermining dependency {!r} with CMake executable '
+                   '{!r}'.format(name, self.cmakebin.executable_path()))
+
+        # Try different CMake generators since specifying no generator may fail
+        # in cygwin for some reason
+        gen_list = []
+        # First try the last working generator
+        if CMakeDependency.class_working_generator is not None:
+            gen_list += [CMakeDependency.class_working_generator]
+        gen_list += CMakeDependency.class_cmake_generators
+
+        # Map the components
+        comp_mapped = self._map_component_list(modules, components)
+        toolchain = CMakeToolchain(self.cmakebin, self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
+        toolchain.write()
+
+        for i in gen_list:
+            mlog.debug('Try CMake generator: {}'.format(i if len(i) > 0 else 'auto'))
+
+            # Prepare options
+            cmake_opts = []
+            cmake_opts += [f'-DNAME={name}']
+            cmake_opts += ['-DARCHS={}'.format(';'.join(self.cmakeinfo.archs))]
+            cmake_opts += [f'-DVERSION={package_version}']
+            cmake_opts += ['-DCOMPS={}'.format(';'.join([x[0] for x in comp_mapped]))]
+            cmake_opts += args
+            cmake_opts += self.traceparser.trace_args()
+            cmake_opts += toolchain.get_cmake_args()
+            cmake_opts += self._extra_cmake_opts()
+            cmake_opts += ['.']
+            if len(i) > 0:
+                cmake_opts = ['-G', i] + cmake_opts
+
+            # Run CMake
+            ret1, out1, err1 = self._call_cmake(cmake_opts, self._main_cmake_file())
+
+            # Current generator was successful
+            if ret1 == 0:
+                CMakeDependency.class_working_generator = i
+                break
+
+            mlog.debug(f'CMake failed for generator {i} and package {name} with error code {ret1}')
+            mlog.debug(f'OUT:\n{out1}\n\n\nERR:\n{err1}\n\n')
+
+        # Check if any generator succeeded
+        if ret1 != 0:
+            return
+
+        try:
+            self.traceparser.parse(err1)
+        except CMakeException as e:
+            e2 = self._gen_exception(str(e))
+            if self.required:
+                raise
+            else:
+                self.compile_args = []
+                self.link_args = []
+                self.is_found = False
+                self.reason = e2
+                return
+
+        # Whether the package is found or not is always stored in PACKAGE_FOUND
+        self.is_found = self.traceparser.var_to_bool('PACKAGE_FOUND')
+        if not self.is_found:
+            return
+
+        # Try to detect the version
+        vers_raw = self.traceparser.get_cmake_var('PACKAGE_VERSION')
+
+        if len(vers_raw) > 0:
+            self.version = vers_raw[0]
+            self.version.strip('"\' ')
+
+        # Post-process module list. Used in derived classes to modify the
+        # module list (append prepend a string, etc.).
+        modules = self._map_module_list(modules, components)
+        autodetected_module_list = False
+
+        # Try guessing a CMake target if none is provided
+        if len(modules) == 0:
+            for i in self.traceparser.targets:
+                tg = i.lower()
+                lname = name.lower()
+                if f'{lname}::{lname}' == tg or lname == tg.replace('::', ''):
+                    mlog.debug(f'Guessed CMake target \'{i}\'')
+                    modules = [(i, True)]
+                    autodetected_module_list = True
+                    break
+
+        # Failed to guess a target --> try the old-style method
+        if len(modules) == 0:
+            # Warn when there might be matching imported targets but no automatic match was used
+            partial_modules: T.List[CMakeTarget] = []
+            for k, v in self.traceparser.targets.items():
+                tg = k.lower()
+                lname = name.lower()
+                if tg.startswith(f'{lname}::'):
+                    partial_modules += [v]
+            if partial_modules:
+                mlog.warning(textwrap.dedent(f'''\
+                    Could not find and exact match for the CMake dependency {name}.
+
+                    However, Meson found the following partial matches:
+
+                        {[x.name for x in partial_modules]}
+
+                    Using imported is recommended, since this approach is less error prone
+                    and better supported by Meson. Consider explicitly specifying one of
+                    these in the dependency call with:
+
+                        dependency('{name}', modules: ['{name}::', ...])
+
+                    Meson will now continue to use the old-style {name}_LIBRARIES CMake
+                    variables to extract the dependency information since no explicit
+                    target is currently specified.
+
+                '''))
+                mlog.debug('More info for the partial match targets:')
+                for tgt in partial_modules:
+                    mlog.debug(tgt)
+
+
+            incDirs = [x for x in self.traceparser.get_cmake_var('PACKAGE_INCLUDE_DIRS') if x]
+            defs = [x for x in self.traceparser.get_cmake_var('PACKAGE_DEFINITIONS') if x]
+            libs_raw = [x for x in self.traceparser.get_cmake_var('PACKAGE_LIBRARIES') if x]
+
+            # CMake has a "fun" API, where certain keywords describing
+            # configurations can be in the *_LIBRARIES vraiables. See:
+            # - https://github.com/mesonbuild/meson/issues/9197
+            # - https://gitlab.freedesktop.org/libnice/libnice/-/issues/140
+            # - https://cmake.org/cmake/help/latest/command/target_link_libraries.html#overview  (the last point in the section)
+            libs: T.List[str] = []
+            cfg_matches = True
+            is_debug = cmake_is_debug(self.env)
+            cm_tag_map = {'debug': is_debug, 'optimized': not is_debug, 'general': True}
+            for i in libs_raw:
+                if i.lower() in cm_tag_map:
+                    cfg_matches = cm_tag_map[i.lower()]
+                    continue
+                if cfg_matches:
+                    libs += [i]
+                # According to the CMake docs, a keyword only works for the
+                # directly the following item and all items without a keyword
+                # are implizitly `general`
+                cfg_matches = True
+
+            # Try to use old style variables if no module is specified
+            if len(libs) > 0:
+                self.compile_args = list(map(lambda x: f'-I{x}', incDirs)) + defs
+                self.link_args = []
+                for j in libs:
+                    rtgt = resolve_cmake_trace_targets(j, self.traceparser, self.env, clib_compiler=self.clib_compiler)
+                    self.link_args += rtgt.libraries
+                    self.compile_args += [f'-I{x}' for x in rtgt.include_directories]
+                    self.compile_args += rtgt.public_compile_opts
+                mlog.debug(f'using old-style CMake variables for dependency {name}')
+                mlog.debug(f'Include Dirs:         {incDirs}')
+                mlog.debug(f'Compiler Definitions: {defs}')
+                mlog.debug(f'Libraries:            {libs}')
+                return
+
+            # Even the old-style approach failed. Nothing else we can do here
+            self.is_found = False
+            raise self._gen_exception('CMake: failed to guess a CMake target for {}.\n'
+                                      'Try to explicitly specify one or more targets with the "modules" property.\n'
+                                      'Valid targets are:\n{}'.format(name, list(self.traceparser.targets.keys())))
+
+        # Set dependencies with CMake targets
+        # recognise arguments we should pass directly to the linker
+        incDirs = []
+        compileOptions = []
+        libraries = []
+
+        for i, required in modules:
+            if i not in self.traceparser.targets:
+                if not required:
+                    mlog.warning('CMake: T.Optional module', mlog.bold(self._original_module_name(i)), 'for', mlog.bold(name), 'was not found')
+                    continue
+                raise self._gen_exception('CMake: invalid module {} for {}.\n'
+                                          'Try to explicitly specify one or more targets with the "modules" property.\n'
+                                          'Valid targets are:\n{}'.format(self._original_module_name(i), name, list(self.traceparser.targets.keys())))
+
+            if not autodetected_module_list:
+                self.found_modules += [i]
+
+            rtgt = resolve_cmake_trace_targets(i ,self.traceparser, self.env,
+                clib_compiler=self.clib_compiler,
+                not_found_warning=lambda x: mlog.warning('CMake: Dependency', mlog.bold(x), 'for', mlog.bold(name), 'was not found')
+            )
+            incDirs        += rtgt.include_directories
+            compileOptions += rtgt.public_compile_opts
+            libraries      += rtgt.libraries + rtgt.link_flags
+
+        # Make sure all elements in the lists are unique and sorted
+        incDirs = sorted(set(incDirs))
+        compileOptions = sorted(set(compileOptions))
+        libraries = sorted(set(libraries))
+
+        mlog.debug(f'Include Dirs:         {incDirs}')
+        mlog.debug(f'Compiler Options:     {compileOptions}')
+        mlog.debug(f'Libraries:            {libraries}')
+
+        self.compile_args = compileOptions + [f'-I{x}' for x in incDirs]
+        self.link_args = libraries
+
+    def _get_build_dir(self) -> Path:
+        build_dir = Path(self.cmake_root_dir) / f'cmake_{self.name}'
+        build_dir.mkdir(parents=True, exist_ok=True)
+        return build_dir
+
+    def _setup_cmake_dir(self, cmake_file: str) -> Path:
+        # Setup the CMake build environment and return the "build" directory
+        build_dir = self._get_build_dir()
+
+        # Remove old CMake cache so we can try out multiple generators
+        cmake_cache = build_dir / 'CMakeCache.txt'
+        cmake_files = build_dir / 'CMakeFiles'
+        if cmake_cache.exists():
+            cmake_cache.unlink()
+        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
+
+        # 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
+        # without C language is
+        #   find_package(Threads)
+        # To make this general to
+        # any other language that might need this, we use a list for all
+        # languages and expand in the cmake Project(... LANGUAGES ...) statement.
+        from ..cmake import language_map
+        cmake_language = [language_map[x] for x in self.language_list if x in language_map]
+        if not cmake_language:
+            cmake_language += ['NONE']
+
+        cmake_txt = textwrap.dedent("""
+            cmake_minimum_required(VERSION ${{CMAKE_VERSION}})
+            project(MesonTemp LANGUAGES {})
+        """).format(' '.join(cmake_language)) + cmake_txt
+
+        cm_file = build_dir / 'CMakeLists.txt'
+        cm_file.write_text(cmake_txt, encoding='utf-8')
+        mlog.cmd_ci_include(cm_file.absolute().as_posix())
+
+        return build_dir
+
+    def _call_cmake(self,
+                    args: T.List[str],
+                    cmake_file: str,
+                    env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, T.Optional[str], T.Optional[str]]:
+        build_dir = self._setup_cmake_dir(cmake_file)
+        return self.cmakebin.call(args, build_dir, env=env)
+
+    def log_tried(self) -> str:
+        return self.type_name
+
+    def log_details(self) -> str:
+        modules = [self._original_module_name(x) for x in self.found_modules]
+        modules = sorted(set(modules))
+        if modules:
+            return 'modules: ' + ', '.join(modules)
+        return ''
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
+                     pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
+        if cmake and self.traceparser is not None:
+            try:
+                v = self.traceparser.vars[cmake]
+            except KeyError:
+                pass
+            else:
+                if len(v) == 1:
+                    return v[0]
+                elif v:
+                    return v
+        if default_value is not None:
+            return default_value
+        raise DependencyException(f'Could not get cmake variable and no default provided for {self!r}')
diff -Nru meson-0.53.2/mesonbuild/dependencies/coarrays.py meson-0.61.2/mesonbuild/dependencies/coarrays.py
--- meson-0.53.2/mesonbuild/dependencies/coarrays.py	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/coarrays.py	2021-11-02 19:58:07.000000000 +0000
@@ -12,11 +12,47 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from ..mesonlib import listify
-from .base import CMakeDependency, DependencyMethods, ExternalDependency, PkgConfigDependency
+import functools
+import typing as T
 
+from .base import DependencyMethods, detect_compiler, SystemDependency
+from .cmake import CMakeDependency
+from .pkgconfig import PkgConfigDependency
+from .factory import factory_methods
+
+if T.TYPE_CHECKING:
+    from . factory import DependencyGenerator
+    from ..environment import Environment, MachineChoice
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE, DependencyMethods.SYSTEM})
+def coarray_factory(env: 'Environment',
+                    for_machine: 'MachineChoice',
+                    kwargs: T.Dict[str, T.Any],
+                    methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    fcid = detect_compiler('coarray', env, for_machine, 'fortran').get_id()
+    candidates: T.List['DependencyGenerator'] = []
+
+    if fcid == 'gcc':
+        # OpenCoarrays is the most commonly used method for Fortran Coarray with GCC
+        if DependencyMethods.PKGCONFIG in methods:
+            for pkg in ['caf-openmpi', 'caf']:
+                candidates.append(functools.partial(
+                    PkgConfigDependency, pkg, env, kwargs, language='fortran'))
+
+        if DependencyMethods.CMAKE in methods:
+            if 'modules' not in kwargs:
+                kwargs['modules'] = 'OpenCoarrays::caf_mpi'
+            candidates.append(functools.partial(
+                CMakeDependency, 'OpenCoarrays', env, kwargs, language='fortran'))
 
-class CoarrayDependency(ExternalDependency):
+    if DependencyMethods.SYSTEM in methods:
+        candidates.append(functools.partial(CoarrayDependency, env, kwargs))
+
+    return candidates
+
+
+class CoarrayDependency(SystemDependency):
     """
     Coarrays are a Fortran 2008 feature.
 
@@ -25,59 +61,26 @@
     Coarrays may be thought of as a high-level language abstraction of
     low-level MPI calls.
     """
-    def __init__(self, environment, kwargs: dict):
-        super().__init__('coarray', environment, 'fortran', kwargs)
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__('coarray', environment, kwargs, language='fortran')
         kwargs['required'] = False
         kwargs['silent'] = True
-        self.is_found = False
-        methods = listify(self.methods)
 
         cid = self.get_compiler().get_id()
         if cid == 'gcc':
-            """ OpenCoarrays is the most commonly used method for Fortran Coarray with GCC """
-
-            if set([DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]).intersection(methods):
-                for pkg in ['caf-openmpi', 'caf']:
-                    pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language)
-                    if pkgdep.found():
-                        self.compile_args = pkgdep.get_compile_args()
-                        self.link_args = pkgdep.get_link_args()
-                        self.version = pkgdep.get_version()
-                        self.is_found = True
-                        self.pcdep = pkgdep
-                        return
-
-            if set([DependencyMethods.AUTO, DependencyMethods.CMAKE]).intersection(methods):
-                if not kwargs.get('modules'):
-                    kwargs['modules'] = 'OpenCoarrays::caf_mpi'
-                cmakedep = CMakeDependency('OpenCoarrays', environment, kwargs, language=self.language)
-                if cmakedep.found():
-                    self.compile_args = cmakedep.get_compile_args()
-                    self.link_args = cmakedep.get_link_args()
-                    self.version = cmakedep.get_version()
-                    self.is_found = True
-                    return
-
-            if DependencyMethods.AUTO in methods:
-                # fallback to single image
-                self.compile_args = ['-fcoarray=single']
-                self.version = 'single image (fallback)'
-                self.is_found = True
-                return
-
+            # Fallback to single image
+            self.compile_args = ['-fcoarray=single']
+            self.version = 'single image (fallback)'
+            self.is_found = True
         elif cid == 'intel':
-            """ Coarrays are built into Intel compilers, no external library needed """
+            # Coarrays are built into Intel compilers, no external library needed
             self.is_found = True
             self.link_args = ['-coarray=shared']
             self.compile_args = self.link_args
         elif cid == 'intel-cl':
-            """ Coarrays are built into Intel compilers, no external library needed """
+            # Coarrays are built into Intel compilers, no external library needed
             self.is_found = True
             self.compile_args = ['/Qcoarray:shared']
         elif cid == 'nagfor':
-            """ NAG doesn't require any special arguments for Coarray """
+            # NAG doesn't require any special arguments for Coarray
             self.is_found = True
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.AUTO, DependencyMethods.CMAKE, DependencyMethods.PKGCONFIG]
diff -Nru meson-0.53.2/mesonbuild/dependencies/configtool.py meson-0.61.2/mesonbuild/dependencies/configtool.py
--- meson-0.53.2/mesonbuild/dependencies/configtool.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/configtool.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,174 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .base import ExternalDependency, DependencyException, DependencyTypeName
+from ..mesonlib import listify, Popen_safe, split_args, version_compare, version_compare_many
+from ..programs import find_external_program
+from .. import mlog
+import re
+import typing as T
+
+from mesonbuild import mesonlib
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+class ConfigToolDependency(ExternalDependency):
+
+    """Class representing dependencies found using a config tool.
+
+    Takes the following extra keys in kwargs that it uses internally:
+    :tools List[str]: A list of tool names to use
+    :version_arg str: The argument to pass to the tool to get it's version
+    :returncode_value int: The value of the correct returncode
+        Because some tools are stupid and don't return 0
+    """
+
+    tools: T.Optional[T.List[str]] = None
+    tool_name: T.Optional[str] = None
+    version_arg = '--version'
+    __strip_version = re.compile(r'^[0-9][0-9.]+')
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
+        super().__init__(DependencyTypeName('config-tool'), environment, kwargs, language=language)
+        self.name = name
+        # You may want to overwrite the class version in some cases
+        self.tools = listify(kwargs.get('tools', self.tools))
+        if not self.tool_name:
+            self.tool_name = self.tools[0]
+        if 'version_arg' in kwargs:
+            self.version_arg = kwargs['version_arg']
+
+        req_version_raw = kwargs.get('version', None)
+        if req_version_raw is not None:
+            req_version = mesonlib.stringlistify(req_version_raw)
+        else:
+            req_version = []
+        tool, version = self.find_config(req_version, kwargs.get('returncode_value', 0))
+        self.config = tool
+        self.is_found = self.report_config(version, req_version)
+        if not self.is_found:
+            self.config = None
+            return
+        self.version = version
+
+    def _sanitize_version(self, version: str) -> str:
+        """Remove any non-numeric, non-point version suffixes."""
+        m = self.__strip_version.match(version)
+        if m:
+            # Ensure that there isn't a trailing '.', such as an input like
+            # `1.2.3.git-1234`
+            return m.group(0).rstrip('.')
+        return version
+
+    def find_config(self, versions: T.List[str], returncode: int = 0) \
+            -> T.Tuple[T.Optional[T.List[str]], T.Optional[str]]:
+        """Helper method that searches for config tool binaries in PATH and
+        returns the one that best matches the given version requirements.
+        """
+        best_match: T.Tuple[T.Optional[T.List[str]], T.Optional[str]] = (None, None)
+        for potential_bin in find_external_program(
+                self.env, self.for_machine, self.tool_name,
+                self.tool_name, self.tools, allow_default_for_cross=False):
+            if not potential_bin.found():
+                continue
+            tool = potential_bin.get_command()
+            try:
+                p, out = Popen_safe(tool + [self.version_arg])[:2]
+            except (FileNotFoundError, PermissionError):
+                continue
+            if p.returncode != returncode:
+                continue
+
+            out = self._sanitize_version(out.strip())
+            # Some tools, like pcap-config don't supply a version, but also
+            # don't fail with --version, in that case just assume that there is
+            # only one version and return it.
+            if not out:
+                return (tool, None)
+            if versions:
+                is_found = version_compare_many(out, versions)[0]
+                # This allows returning a found version without a config tool,
+                # which is useful to inform the user that you found version x,
+                # but y was required.
+                if not is_found:
+                    tool = None
+            if best_match[1]:
+                if version_compare(out, '> {}'.format(best_match[1])):
+                    best_match = (tool, out)
+            else:
+                best_match = (tool, out)
+
+        return best_match
+
+    def report_config(self, version: T.Optional[str], req_version: T.List[str]) -> bool:
+        """Helper method to print messages about the tool."""
+
+        found_msg: T.List[T.Union[str, mlog.AnsiDecorator]] = [mlog.bold(self.tool_name), 'found:']
+
+        if self.config is None:
+            found_msg.append(mlog.red('NO'))
+            if version is not None and req_version:
+                found_msg.append(f'found {version!r} but need {req_version!r}')
+            elif req_version:
+                found_msg.append(f'need {req_version!r}')
+        else:
+            found_msg += [mlog.green('YES'), '({})'.format(' '.join(self.config)), version]
+
+        mlog.log(*found_msg)
+
+        return self.config is not None
+
+    def get_config_value(self, args: T.List[str], stage: str) -> T.List[str]:
+        p, out, err = Popen_safe(self.config + args)
+        if p.returncode != 0:
+            if self.required:
+                raise DependencyException(f'Could not generate {stage} for {self.name}.\n{err}')
+            return []
+        return split_args(out)
+
+    def get_configtool_variable(self, variable_name: str) -> str:
+        p, out, _ = Popen_safe(self.config + [f'--{variable_name}'])
+        if p.returncode != 0:
+            if self.required:
+                raise DependencyException(
+                    'Could not get variable "{}" for dependency {}'.format(
+                        variable_name, self.name))
+        variable = out.strip()
+        mlog.debug(f'Got config-tool variable {variable_name} : {variable}')
+        return variable
+
+    def log_tried(self) -> str:
+        return self.type_name
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
+                     pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
+        if configtool:
+            # In the not required case '' (empty string) will be returned if the
+            # variable is not found. Since '' is a valid value to return we
+            # set required to True here to force and error, and use the
+            # finally clause to ensure it's restored.
+            restore = self.required
+            self.required = True
+            try:
+                return self.get_configtool_variable(configtool)
+            except DependencyException:
+                pass
+            finally:
+                self.required = restore
+        if default_value is not None:
+            return default_value
+        raise DependencyException(f'Could not get config-tool variable and no default provided for {self!r}')
diff -Nru meson-0.53.2/mesonbuild/dependencies/cuda.py meson-0.61.2/mesonbuild/dependencies/cuda.py
--- meson-0.53.2/mesonbuild/dependencies/cuda.py	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/cuda.py	2021-11-02 19:58:07.000000000 +0000
@@ -15,25 +15,33 @@
 import glob
 import re
 import os
+import typing as T
+from pathlib import Path
 
-from .. import mlog
 from .. import mesonlib
+from .. import mlog
 from ..environment import detect_cpu_family
+from .base import DependencyException, SystemDependency
+
 
-from .base import (DependencyException, ExternalDependency)
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+    from ..compilers import Compiler
 
+TV_ResultTuple = T.Tuple[T.Optional[str], T.Optional[str], bool]
 
-class CudaDependency(ExternalDependency):
+class CudaDependency(SystemDependency):
 
     supported_languages = ['cuda', 'cpp', 'c'] # see also _default_language
 
-    def __init__(self, environment, kwargs):
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
         compilers = environment.coredata.compilers[self.get_for_machine_from_kwargs(kwargs)]
         language = self._detect_language(compilers)
         if language not in self.supported_languages:
-            raise DependencyException('Language \'{}\' is not supported by the CUDA Toolkit. Supported languages are {}.'.format(language, self.supported_languages))
+            raise DependencyException(f'Language \'{language}\' is not supported by the CUDA Toolkit. Supported languages are {self.supported_languages}.')
 
-        super().__init__('cuda', environment, language, kwargs)
+        super().__init__('cuda', environment, kwargs, language=language)
+        self.lib_modules: T.Dict[str, T.List[str]] = {}
         self.requested_modules = self.get_requested(kwargs)
         if 'cudart' not in self.requested_modules:
             self.requested_modules = ['cudart'] + self.requested_modules
@@ -43,13 +51,13 @@
             return
 
         if not os.path.isabs(self.cuda_path):
-            raise DependencyException('CUDA Toolkit path must be absolute, got \'{}\'.'.format(self.cuda_path))
+            raise DependencyException(f'CUDA Toolkit path must be absolute, got \'{self.cuda_path}\'.')
 
         # nvcc already knows where to find the CUDA Toolkit, but if we're compiling
         # a mixed C/C++/CUDA project, we still need to make the include dir searchable
         if self.language != 'cuda' or len(compilers) > 1:
             self.incdir = os.path.join(self.cuda_path, 'include')
-            self.compile_args += ['-I{}'.format(self.incdir)]
+            self.compile_args += [f'-I{self.incdir}']
 
         if self.language != 'cuda':
             arch_libdir = self._detect_arch_libdir()
@@ -61,13 +69,13 @@
         self.is_found = self._find_requested_libraries()
 
     @classmethod
-    def _detect_language(cls, compilers):
+    def _detect_language(cls, compilers: T.Dict[str, 'Compiler']) -> str:
         for lang in cls.supported_languages:
             if lang in compilers:
                 return lang
         return list(compilers.keys())[0]
 
-    def _detect_cuda_path_and_version(self):
+    def _detect_cuda_path_and_version(self) -> TV_ResultTuple:
         self.env_var = self._default_path_env_var()
         mlog.debug('Default path env var:', mlog.bold(self.env_var))
 
@@ -79,11 +87,11 @@
                 # make sure nvcc version satisfies specified version requirements
                 (found_some, not_found, found) = mesonlib.version_compare_many(nvcc_version, version_reqs)
                 if not_found:
-                    msg = 'The current nvcc version {} does not satisfy the specified CUDA Toolkit version requirements {}.'.format(nvcc_version, version_reqs)
+                    msg = f'The current nvcc version {nvcc_version} does not satisfy the specified CUDA Toolkit version requirements {version_reqs}.'
                     return self._report_dependency_error(msg, (None, None, False))
 
             # use nvcc version to find a matching CUDA Toolkit
-            version_reqs = ['={}'.format(nvcc_version)]
+            version_reqs = [f'={nvcc_version}']
         else:
             nvcc_version = None
 
@@ -97,19 +105,20 @@
 
         platform_msg = 'set the CUDA_PATH environment variable' if self._is_windows() \
             else 'set the CUDA_PATH environment variable/create the \'/usr/local/cuda\' symbolic link'
-        msg = 'Please specify the desired CUDA Toolkit version (e.g. dependency(\'cuda\', version : \'>=10.1\')) or {} to point to the location of your desired version.'.format(platform_msg)
+        msg = f'Please specify the desired CUDA Toolkit version (e.g. dependency(\'cuda\', version : \'>=10.1\')) or {platform_msg} to point to the location of your desired version.'
         return self._report_dependency_error(msg, (None, None, False))
 
-    def _find_matching_toolkit(self, paths, version_reqs, nvcc_version):
+    def _find_matching_toolkit(self, paths: T.List[TV_ResultTuple], version_reqs: T.List[str], nvcc_version: T.Optional[str]) -> TV_ResultTuple:
         # keep the default paths order intact, sort the rest in the descending order
         # according to the toolkit version
-        defaults, rest = mesonlib.partition(lambda t: not t[2], paths)
-        defaults = list(defaults)
-        paths = defaults + sorted(rest, key=lambda t: mesonlib.Version(t[1]), reverse=True)
-        mlog.debug('Search paths: {}'.format(paths))
+        part_func: T.Callable[[TV_ResultTuple], bool] = lambda t: not t[2]
+        defaults_it, rest_it = mesonlib.partition(part_func, paths)
+        defaults = list(defaults_it)
+        paths = defaults + sorted(rest_it, key=lambda t: mesonlib.Version(t[1]), reverse=True)
+        mlog.debug(f'Search paths: {paths}')
 
         if nvcc_version and defaults:
-            default_src = "the {} environment variable".format(self.env_var) if self.env_var else "the \'/usr/local/cuda\' symbolic link"
+            default_src = f"the {self.env_var} environment variable" if self.env_var else "the \'/usr/local/cuda\' symbolic link"
             nvcc_warning = 'The default CUDA Toolkit as designated by {} ({}) doesn\'t match the current nvcc version {} and will be ignored.'.format(default_src, os.path.realpath(defaults[0][0]), nvcc_version)
         else:
             nvcc_warning = None
@@ -125,23 +134,23 @@
             mlog.warning(nvcc_warning)
         return (None, None, False)
 
-    def _default_path_env_var(self):
+    def _default_path_env_var(self) -> T.Optional[str]:
         env_vars = ['CUDA_PATH'] if self._is_windows() else ['CUDA_PATH', 'CUDA_HOME', 'CUDA_ROOT']
         env_vars = [var for var in env_vars if var in os.environ]
-        user_defaults = set([os.environ[var] for var in env_vars])
+        user_defaults = {os.environ[var] for var in env_vars}
         if len(user_defaults) > 1:
             mlog.warning('Environment variables {} point to conflicting toolkit locations ({}). Toolkit selection might produce unexpected results.'.format(', '.join(env_vars), ', '.join(user_defaults)))
         return env_vars[0] if env_vars else None
 
-    def _cuda_paths(self):
+    def _cuda_paths(self) -> T.List[T.Tuple[str, bool]]:
         return ([(os.environ[self.env_var], True)] if self.env_var else []) \
             + (self._cuda_paths_win() if self._is_windows() else self._cuda_paths_nix())
 
-    def _cuda_paths_win(self):
+    def _cuda_paths_win(self) -> T.List[T.Tuple[str, bool]]:
         env_vars = os.environ.keys()
         return [(os.environ[var], False) for var in env_vars if var.startswith('CUDA_PATH_')]
 
-    def _cuda_paths_nix(self):
+    def _cuda_paths_nix(self) -> T.List[T.Tuple[str, bool]]:
         # include /usr/local/cuda default only if no env_var was found
         pattern = '/usr/local/cuda-*' if self.env_var else '/usr/local/cuda*'
         return [(path, os.path.basename(path) == 'cuda') for path in glob.iglob(pattern)]
@@ -149,40 +158,65 @@
     toolkit_version_regex = re.compile(r'^CUDA Version\s+(.*)$')
     path_version_win_regex = re.compile(r'^v(.*)$')
     path_version_nix_regex = re.compile(r'^cuda-(.*)$')
+    cudart_version_regex = re.compile(r'#define\s+CUDART_VERSION\s+([0-9]+)')
 
-    def _cuda_toolkit_version(self, path):
+    def _cuda_toolkit_version(self, path: str) -> str:
         version = self._read_toolkit_version_txt(path)
         if version:
             return version
+        version = self._read_cuda_runtime_api_version(path)
+        if version:
+            return version
 
         mlog.debug('Falling back to extracting version from path')
         path_version_regex = self.path_version_win_regex if self._is_windows() else self.path_version_nix_regex
-        m = path_version_regex.match(os.path.basename(path))
-        if m:
-            return m[1]
+        try:
+            m = path_version_regex.match(os.path.basename(path))
+            if m:
+                return m.group(1)
+            else:
+                mlog.warning(f'Could not detect CUDA Toolkit version for {path}')
+        except Exception as e:
+            mlog.warning(f'Could not detect CUDA Toolkit version for {path}: {e!s}')
 
-        mlog.warning('Could not detect CUDA Toolkit version for {}'.format(path))
         return '0.0'
 
-    def _read_toolkit_version_txt(self, path):
-        # Read 'version.txt' at the root of the CUDA Toolkit directory to determine the tookit version
+    def _read_cuda_runtime_api_version(self, path_str: str) -> T.Optional[str]:
+        path = Path(path_str)
+        for i in path.rglob('cuda_runtime_api.h'):
+            raw = i.read_text(encoding='utf-8')
+            m = self.cudart_version_regex.search(raw)
+            if not m:
+                continue
+            try:
+                vers_int = int(m.group(1))
+            except ValueError:
+                continue
+            # use // for floor instead of / which produces a float
+            major = vers_int // 1000                  # type: int
+            minor = (vers_int - major * 1000) // 10   # type: int
+            return f'{major}.{minor}'
+        return None
+
+    def _read_toolkit_version_txt(self, path: str) -> T.Optional[str]:
+        # Read 'version.txt' at the root of the CUDA Toolkit directory to determine the toolkit version
         version_file_path = os.path.join(path, 'version.txt')
         try:
-            with open(version_file_path) as version_file:
+            with open(version_file_path, encoding='utf-8') as version_file:
                 version_str = version_file.readline() # e.g. 'CUDA Version 10.1.168'
                 m = self.toolkit_version_regex.match(version_str)
                 if m:
-                    return self._strip_patch_version(m[1])
+                    return self._strip_patch_version(m.group(1))
         except Exception as e:
-            mlog.debug('Could not read CUDA Toolkit\'s version file {}: {}'.format(version_file_path, str(e)))
+            mlog.debug(f'Could not read CUDA Toolkit\'s version file {version_file_path}: {e!s}')
 
         return None
 
     @classmethod
-    def _strip_patch_version(cls, version):
+    def _strip_patch_version(cls, version: str) -> str:
         return '.'.join(version.split('.')[:2])
 
-    def _detect_arch_libdir(self):
+    def _detect_arch_libdir(self) -> str:
         arch = detect_cpu_family(self.env.coredata.compilers.host)
         machine = self.env.machines[self.for_machine]
         msg = '{} architecture is not supported in {} version of the CUDA Toolkit.'
@@ -192,11 +226,11 @@
                 raise DependencyException(msg.format(arch, 'Windows'))
             return os.path.join('lib', libdirs[arch])
         elif machine.is_linux():
-            libdirs = {'x86_64': 'lib64', 'ppc64': 'lib'}
+            libdirs = {'x86_64': 'lib64', 'ppc64': 'lib', 'aarch64': 'lib64', 'loongarch64': 'lib64'}
             if arch not in libdirs:
                 raise DependencyException(msg.format(arch, 'Linux'))
             return libdirs[arch]
-        elif machine.is_osx():
+        elif machine.is_darwin():
             libdirs = {'x86_64': 'lib64'}
             if arch not in libdirs:
                 raise DependencyException(msg.format(arch, 'macOS'))
@@ -204,46 +238,51 @@
         else:
             raise DependencyException('CUDA Toolkit: unsupported platform.')
 
-    def _find_requested_libraries(self):
-        self.lib_modules = {}
+    def _find_requested_libraries(self) -> bool:
         all_found = True
 
         for module in self.requested_modules:
             args = self.clib_compiler.find_library(module, self.env, [self.libdir] if self.libdir else [])
             if args is None:
-                self._report_dependency_error('Couldn\'t find requested CUDA module \'{}\''.format(module))
+                self._report_dependency_error(f'Couldn\'t find requested CUDA module \'{module}\'')
                 all_found = False
             else:
-                mlog.debug('Link args for CUDA module \'{}\' are {}'.format(module, args))
+                mlog.debug(f'Link args for CUDA module \'{module}\' are {args}')
                 self.lib_modules[module] = args
 
         return all_found
 
-    def _is_windows(self):
+    def _is_windows(self) -> bool:
         return self.env.machines[self.for_machine].is_windows()
 
-    def _report_dependency_error(self, msg, ret_val=None):
+    @T.overload
+    def _report_dependency_error(self, msg: str) -> None: ...
+
+    @T.overload
+    def _report_dependency_error(self, msg: str, ret_val: TV_ResultTuple) -> TV_ResultTuple: ... # noqa: F811
+
+    def _report_dependency_error(self, msg: str, ret_val: T.Optional[TV_ResultTuple] = None) -> T.Optional[TV_ResultTuple]: # noqa: F811
         if self.required:
             raise DependencyException(msg)
 
         mlog.debug(msg)
         return ret_val
 
-    def log_details(self):
+    def log_details(self) -> str:
         module_str = ', '.join(self.requested_modules)
         return 'modules: ' + module_str
 
-    def log_info(self):
+    def log_info(self) -> str:
         return self.cuda_path if self.cuda_path else ''
 
-    def get_requested(self, kwargs):
+    def get_requested(self, kwargs: T.Dict[str, T.Any]) -> T.List[str]:
         candidates = mesonlib.extract_as_list(kwargs, 'modules')
         for c in candidates:
             if not isinstance(c, str):
                 raise DependencyException('CUDA module argument is not a string.')
         return candidates
 
-    def get_link_args(self, **kwargs):
+    def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
         args = []
         if self.libdir:
             args += self.clib_compiler.get_linker_search_args(self.libdir)
diff -Nru meson-0.53.2/mesonbuild/dependencies/data/CMakeLists.txt meson-0.61.2/mesonbuild/dependencies/data/CMakeLists.txt
--- meson-0.53.2/mesonbuild/dependencies/data/CMakeLists.txt	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/data/CMakeLists.txt	2021-04-01 21:13:00.000000000 +0000
@@ -9,7 +9,11 @@
 string(TOUPPER "${_packageName}" PACKAGE_NAME)
 
 while(TRUE)
-  find_package("${NAME}" QUIET)
+  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 "")
diff -Nru meson-0.53.2/mesonbuild/dependencies/detect.py meson-0.61.2/mesonbuild/dependencies/detect.py
--- meson-0.53.2/mesonbuild/dependencies/detect.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/detect.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,226 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .base import ExternalDependency, DependencyException, DependencyMethods, NotFoundDependency
+from .cmake import CMakeDependency
+from .dub import DubDependency
+from .framework import ExtraFrameworkDependency
+from .pkgconfig import PkgConfigDependency
+
+from ..mesonlib import listify, MachineChoice, PerMachine
+from .. import mlog
+import functools
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+    from .factory import DependencyFactory, WrappedFactoryFunc, DependencyGenerator
+
+# These must be defined in this file to avoid cyclical references.
+packages: T.Dict[
+    str,
+    T.Union[T.Type[ExternalDependency], 'DependencyFactory', 'WrappedFactoryFunc']
+] = {}
+_packages_accept_language: T.Set[str] = set()
+
+if T.TYPE_CHECKING:
+    TV_DepIDEntry = T.Union[str, bool, int, T.Tuple[str, ...]]
+    TV_DepID = T.Tuple[T.Tuple[str, TV_DepIDEntry], ...]
+
+
+def get_dep_identifier(name: str, kwargs: T.Dict[str, T.Any]) -> 'TV_DepID':
+    identifier: 'TV_DepID' = (('name', name), )
+    from ..interpreter import permitted_dependency_kwargs
+    assert len(permitted_dependency_kwargs) == 19, \
+           'Extra kwargs have been added to dependency(), please review if it makes sense to handle it here'
+    for key, value in kwargs.items():
+        # 'version' is irrelevant for caching; the caller must check version matches
+        # 'native' is handled above with `for_machine`
+        # 'required' is irrelevant for caching; the caller handles it separately
+        # 'fallback' and 'allow_fallback' is not part of the cache because,
+        #     once a dependency has been found through a fallback, it should
+        #     be used for the rest of the Meson run.
+        # 'default_options' is only used in fallback case
+        # 'not_found_message' has no impact on the dependency lookup
+        # 'include_type' is handled after the dependency lookup
+        if key in ('version', 'native', 'required', 'fallback', 'allow_fallback', 'default_options',
+                   'not_found_message', 'include_type'):
+            continue
+        # All keyword arguments are strings, ints, or lists (or lists of lists)
+        if isinstance(value, list):
+            for i in value:
+                assert isinstance(i, str)
+            value = tuple(frozenset(listify(value)))
+        else:
+            assert isinstance(value, (str, bool, int))
+        identifier = (*identifier, (key, value),)
+    return identifier
+
+display_name_map = {
+    'boost': 'Boost',
+    'cuda': 'CUDA',
+    'dub': 'DUB',
+    'gmock': 'GMock',
+    'gtest': 'GTest',
+    'hdf5': 'HDF5',
+    'llvm': 'LLVM',
+    'mpi': 'MPI',
+    'netcdf': 'NetCDF',
+    'openmp': 'OpenMP',
+    'wxwidgets': 'WxWidgets',
+}
+
+def find_external_dependency(name: str, env: 'Environment', kwargs: T.Dict[str, object]) -> T.Union['ExternalDependency', NotFoundDependency]:
+    assert name
+    required = kwargs.get('required', True)
+    if not isinstance(required, bool):
+        raise DependencyException('Keyword "required" must be a boolean.')
+    if not isinstance(kwargs.get('method', ''), str):
+        raise DependencyException('Keyword "method" must be a string.')
+    lname = name.lower()
+    if lname not in _packages_accept_language and 'language' in kwargs:
+        raise DependencyException(f'{name} dependency does not accept "language" keyword argument')
+    if not isinstance(kwargs.get('version', ''), (str, list)):
+        raise DependencyException('Keyword "Version" must be string or list.')
+
+    # display the dependency name with correct casing
+    display_name = display_name_map.get(lname, lname)
+
+    for_machine = MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST
+
+    type_text = PerMachine('Build-time', 'Run-time')[for_machine] + ' dependency'
+
+    # build a list of dependency methods to try
+    candidates = _build_external_dependency_list(name, env, for_machine, kwargs)
+
+    pkg_exc: T.List[DependencyException] = []
+    pkgdep:  T.List[ExternalDependency]  = []
+    details = ''
+
+    for c in candidates:
+        # try this dependency method
+        try:
+            d = c()
+            d._check_version()
+            pkgdep.append(d)
+        except DependencyException as e:
+            pkg_exc.append(e)
+            mlog.debug(str(e))
+        else:
+            pkg_exc.append(None)
+            details = d.log_details()
+            if details:
+                details = '(' + details + ') '
+            if 'language' in kwargs:
+                details += 'for ' + d.language + ' '
+
+            # if the dependency was found
+            if d.found():
+
+                info: mlog.TV_LoggableList = []
+                if d.version:
+                    info.append(mlog.normal_cyan(d.version))
+
+                log_info = d.log_info()
+                if log_info:
+                    info.append('(' + log_info + ')')
+
+                mlog.log(type_text, mlog.bold(display_name), details + 'found:', mlog.green('YES'), *info)
+
+                return d
+
+    # otherwise, the dependency could not be found
+    tried_methods = [d.log_tried() for d in pkgdep if d.log_tried()]
+    if tried_methods:
+        tried = mlog.format_list(tried_methods)
+    else:
+        tried = ''
+
+    mlog.log(type_text, mlog.bold(display_name), details + 'found:', mlog.red('NO'),
+             f'(tried {tried})' if tried else '')
+
+    if required:
+        # if an exception occurred with the first detection method, re-raise it
+        # (on the grounds that it came from the preferred dependency detection
+        # method)
+        if pkg_exc and pkg_exc[0]:
+            raise pkg_exc[0]
+
+        # we have a list of failed ExternalDependency objects, so we can report
+        # the methods we tried to find the dependency
+        raise DependencyException(f'Dependency "{name}" not found' +
+                                  (f', tried {tried}' if tried else ''))
+
+    return NotFoundDependency(name, env)
+
+
+def _build_external_dependency_list(name: str, env: 'Environment', for_machine: MachineChoice,
+                                    kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']:
+    # First check if the method is valid
+    if 'method' in kwargs and kwargs['method'] not in [e.value for e in DependencyMethods]:
+        raise DependencyException('method {!r} is invalid'.format(kwargs['method']))
+
+    # Is there a specific dependency detector for this dependency?
+    lname = name.lower()
+    if lname in packages:
+        # Create the list of dependency object constructors using a factory
+        # class method, if one exists, otherwise the list just consists of the
+        # constructor
+        if isinstance(packages[lname], type):
+            entry1 = T.cast(T.Type[ExternalDependency], packages[lname])  # mypy doesn't understand isinstance(..., type)
+            if issubclass(entry1, ExternalDependency):
+                # TODO: somehow make mypy understand that entry1(env, kwargs) is OK...
+                func: T.Callable[[], 'ExternalDependency'] = lambda: entry1(env, kwargs)  # type: ignore
+                dep = [func]
+        else:
+            entry2 = T.cast(T.Union['DependencyFactory', 'WrappedFactoryFunc'], packages[lname])
+            dep = entry2(env, for_machine, kwargs)
+        return dep
+
+    candidates: T.List['DependencyGenerator'] = []
+
+    # If it's explicitly requested, use the dub detection method (only)
+    if 'dub' == kwargs.get('method', ''):
+        candidates.append(functools.partial(DubDependency, name, env, kwargs))
+        return candidates
+
+    # If it's explicitly requested, use the pkgconfig detection method (only)
+    if 'pkg-config' == kwargs.get('method', ''):
+        candidates.append(functools.partial(PkgConfigDependency, name, env, kwargs))
+        return candidates
+
+    # If it's explicitly requested, use the CMake detection method (only)
+    if 'cmake' == kwargs.get('method', ''):
+        candidates.append(functools.partial(CMakeDependency, name, env, kwargs))
+        return candidates
+
+    # If it's explicitly requested, use the Extraframework detection method (only)
+    if 'extraframework' == kwargs.get('method', ''):
+        # On OSX, also try framework dependency detector
+        if env.machines[for_machine].is_darwin():
+            candidates.append(functools.partial(ExtraFrameworkDependency, name, env, kwargs))
+        return candidates
+
+    # Otherwise, just use the pkgconfig and cmake dependency detector
+    if 'auto' == kwargs.get('method', 'auto'):
+        candidates.append(functools.partial(PkgConfigDependency, name, env, kwargs))
+
+        # On OSX, also try framework dependency detector
+        if env.machines[for_machine].is_darwin():
+            candidates.append(functools.partial(ExtraFrameworkDependency, name, env, kwargs))
+
+        # Only use CMake as a last resort, since it might not work 100% (see #6113)
+        candidates.append(functools.partial(CMakeDependency, name, env, kwargs))
+
+    return candidates
diff -Nru meson-0.53.2/mesonbuild/dependencies/dev.py meson-0.61.2/mesonbuild/dependencies/dev.py
--- meson-0.53.2/mesonbuild/dependencies/dev.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/dev.py	2021-11-25 22:00:46.000000000 +0000
@@ -15,24 +15,30 @@
 # This file contains the detection logic for external dependencies useful for
 # development purposes, such as testing, debugging, etc..
 
-import functools
 import glob
 import os
 import re
+import pathlib
+import shutil
+import typing as T
 
 from .. import mesonlib, mlog
-from ..mesonlib import version_compare, stringlistify, extract_as_list, MachineChoice
+from ..compilers import AppleClangCCompiler, AppleClangCPPCompiler, detect_compiler_for
 from ..environment import get_llvm_tool_names
-from .base import (
-    DependencyException, DependencyMethods, ExternalDependency, PkgConfigDependency,
-    strip_system_libdirs, ConfigToolDependency, CMakeDependency
-)
-from .misc import ThreadDependency
-
-import typing as T
+from ..mesonlib import version_compare, stringlistify, extract_as_list, MachineChoice
+from .base import DependencyException, DependencyMethods, strip_system_libdirs, SystemDependency
+from .cmake import CMakeDependency
+from .configtool import ConfigToolDependency
+from .factory import DependencyFactory
+from .misc import threads_factory
+from .pkgconfig import PkgConfigDependency
+
+if T.TYPE_CHECKING:
+    from ..envconfig import MachineInfo
+    from .. environment import Environment
 
 
-def get_shared_library_suffix(environment, for_machine: MachineChoice):
+def get_shared_library_suffix(environment: 'Environment', for_machine: MachineChoice) -> str:
     """This is only guaranteed to work for languages that compile to machine
     code, not for languages like C# that use a bytecode and always end in .dll
     """
@@ -44,15 +50,17 @@
     return '.so'
 
 
-class GTestDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('gtest', environment, 'cpp', kwargs)
+class GTestDependencySystem(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs, language='cpp')
         self.main = kwargs.get('main', False)
         self.src_dirs = ['/usr/src/gtest/src', '/usr/src/googletest/googletest/src']
+        if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})):
+            self.is_found = False
+            return
         self.detect()
-        self._add_sub_dependency(ThreadDependency, environment, kwargs)
 
-    def detect(self):
+    def detect(self) -> None:
         gtest_detect = self.clib_compiler.find_library("gtest", self.env, [])
         gtest_main_detect = self.clib_compiler.find_library("gtest_main", self.env, [])
         if gtest_detect and (not self.main or gtest_main_detect):
@@ -75,7 +83,7 @@
         else:
             self.is_found = False
 
-    def detect_srcdir(self):
+    def detect_srcdir(self) -> bool:
         for s in self.src_dirs:
             if os.path.exists(s):
                 self.src_dir = s
@@ -89,39 +97,32 @@
                 return True
         return False
 
-    def log_info(self):
+    def log_info(self) -> str:
         if self.prebuilt:
             return 'prebuilt'
         else:
             return 'building self'
 
-    def log_tried(self):
+    def log_tried(self) -> str:
         return 'system'
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.PKGCONFIG in methods:
-            pcname = 'gtest_main' if kwargs.get('main', False) else 'gtest'
-            candidates.append(functools.partial(PkgConfigDependency, pcname, environment, kwargs))
-
-        if DependencyMethods.SYSTEM in methods:
-            candidates.append(functools.partial(GTestDependency, environment, kwargs))
 
-        return candidates
+class GTestDependencyPC(PkgConfigDependency):
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        assert name == 'gtest'
+        if kwargs.get('main'):
+            name = 'gtest_main'
+        super().__init__(name, environment, kwargs)
 
 
-class GMockDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('gmock', environment, 'cpp', kwargs)
+class GMockDependencySystem(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs, language='cpp')
         self.main = kwargs.get('main', False)
-        self._add_sub_dependency(ThreadDependency, environment, kwargs)
+        if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})):
+            self.is_found = False
+            return
 
         # If we are getting main() from GMock, we definitely
         # want to avoid linking in main() from GTest
@@ -132,11 +133,10 @@
         # GMock without GTest is pretty much useless
         # this also mimics the structure given in WrapDB,
         # where GMock always pulls in GTest
-        gtest_dep = GTestDependency(environment, gtest_kwargs)
-        if not gtest_dep.is_found:
+        found = self._add_sub_dependency(gtest_factory(environment, self.for_machine, gtest_kwargs))
+        if not found:
             self.is_found = False
             return
-        self.ext_deps.append(gtest_dep)
 
         # GMock may be a library or just source.
         # Work with both.
@@ -168,32 +168,23 @@
 
         self.is_found = False
 
-    def log_info(self):
+    def log_info(self) -> str:
         if self.prebuilt:
             return 'prebuilt'
         else:
             return 'building self'
 
-    def log_tried(self):
+    def log_tried(self) -> str:
         return 'system'
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.PKGCONFIG in methods:
-            pcname = 'gmock_main' if kwargs.get('main', False) else 'gmock'
-            candidates.append(functools.partial(PkgConfigDependency, pcname, environment, kwargs))
 
-        if DependencyMethods.SYSTEM in methods:
-            candidates.append(functools.partial(GMockDependency, environment, kwargs))
+class GMockDependencyPC(PkgConfigDependency):
 
-        return candidates
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        assert name == 'gmock'
+        if kwargs.get('main'):
+            name = 'gmock_main'
+        super().__init__(name, environment, kwargs)
 
 
 class LLVMDependencyConfigTool(ConfigToolDependency):
@@ -204,7 +195,7 @@
     tool_name = 'llvm-config'
     __cpp_blacklist = {'-DNDEBUG'}
 
-    def __init__(self, environment, kwargs):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
         self.tools = get_llvm_tool_names('llvm-config')
 
         # Fedora starting with Fedora 30 adds a suffix of the number
@@ -218,13 +209,12 @@
 
         # It's necessary for LLVM <= 3.8 to use the C++ linker. For 3.9 and 4.0
         # the C linker works fine if only using the C API.
-        super().__init__('LLVM', environment, 'cpp', kwargs)
-        self.provided_modules = []
-        self.required_modules = set()
-        self.module_details = []
+        super().__init__(name, environment, kwargs, language='cpp')
+        self.provided_modules: T.List[str] = []
+        self.required_modules: mesonlib.OrderedSet[str] = mesonlib.OrderedSet()
+        self.module_details:   T.List[str] = []
         if not self.is_found:
             return
-        self.static = kwargs.get('static', False)
 
         self.provided_modules = self.get_config_value(['--components'], 'modules')
         modules = stringlistify(extract_as_list(kwargs, 'modules'))
@@ -232,7 +222,7 @@
         opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules'))
         self.check_components(opt_modules, required=False)
 
-        cargs = set(self.get_config_value(['--cppflags'], 'compile_args'))
+        cargs = mesonlib.OrderedSet(self.get_config_value(['--cppflags'], 'compile_args'))
         self.compile_args = list(cargs.difference(self.__cpp_blacklist))
 
         if version_compare(self.version, '>= 3.9'):
@@ -241,9 +231,11 @@
             self._set_old_link_args()
         self.link_args = strip_system_libdirs(environment, self.for_machine, self.link_args)
         self.link_args = self.__fix_bogus_link_args(self.link_args)
-        self._add_sub_dependency(ThreadDependency, environment, kwargs)
+        if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})):
+            self.is_found = False
+            return
 
-    def __fix_bogus_link_args(self, args):
+    def __fix_bogus_link_args(self, args: T.List[str]) -> T.List[str]:
         """This function attempts to fix bogus link arguments that llvm-config
         generates.
 
@@ -254,19 +246,19 @@
               "-L IBPATH:...", if we're using an msvc like compilers convert
               that to "/LIBPATH", otherwise to "-L ..."
         """
-        cpp = self.env.coredata.compilers[self.for_machine]['cpp']
 
         new_args = []
         for arg in args:
             if arg.startswith('-l') and arg.endswith('.so'):
                 new_args.append(arg.lstrip('-l'))
             elif arg.startswith('-LIBPATH:'):
+                cpp = self.env.coredata.compilers[self.for_machine]['cpp']
                 new_args.extend(cpp.get_linker_search_args(arg.lstrip('-LIBPATH:')))
             else:
                 new_args.append(arg)
         return new_args
 
-    def __check_libfiles(self, shared):
+    def __check_libfiles(self, shared: bool) -> None:
         """Use llvm-config's --libfiles to check if libraries exist."""
         mode = '--link-shared' if shared else '--link-static'
 
@@ -282,9 +274,15 @@
         finally:
             self.required = restore
 
-    def _set_new_link_args(self, environment):
+    def _set_new_link_args(self, environment: 'Environment') -> None:
         """How to set linker args for LLVM versions >= 3.9"""
-        mode = self.get_config_value(['--shared-mode'], 'link_args')[0]
+        try:
+            mode = self.get_config_value(['--shared-mode'], 'link_args')[0]
+        except IndexError:
+            mlog.debug('llvm-config --shared-mode returned an error')
+            self.is_found = False
+            return
+
         if not self.static and mode == 'static':
             # If llvm is configured with LLVM_BUILD_LLVM_DYLIB but not with
             # LLVM_LINK_LLVM_DYLIB and not LLVM_BUILD_SHARED_LIBS (which
@@ -302,7 +300,7 @@
                 lib_ext = get_shared_library_suffix(environment, self.for_machine)
                 libdir = self.get_config_value(['--libdir'], 'link_args')[0]
                 # Sort for reproducibility
-                matches = sorted(glob.iglob(os.path.join(libdir, 'libLLVM*{}'.format(lib_ext))))
+                matches = sorted(glob.iglob(os.path.join(libdir, f'libLLVM*{lib_ext}')))
                 if not matches:
                     if self.required:
                         raise
@@ -311,7 +309,7 @@
 
                 self.link_args = self.get_config_value(['--ldflags'], 'link_args')
                 libname = os.path.basename(matches[0]).rstrip(lib_ext).lstrip('lib')
-                self.link_args.append('-l{}'.format(libname))
+                self.link_args.append(f'-l{libname}')
                 return
         elif self.static and mode == 'shared':
             # If, however LLVM_BUILD_SHARED_LIBS is true # (*cough* gentoo *cough*)
@@ -331,7 +329,7 @@
             ['--libs', '--ldflags'] + link_args + list(self.required_modules),
             'link_args')
 
-    def _set_old_link_args(self):
+    def _set_old_link_args(self) -> None:
         """Setting linker args for older versions of llvm.
 
         Old versions of LLVM bring an extra level of insanity with them.
@@ -350,19 +348,19 @@
             # called libLLVM-.(so|dylib|dll)
             libdir = self.get_config_value(['--libdir'], 'link_args')[0]
 
-            expected_name = 'libLLVM-{}'.format(self.version)
-            re_name = re.compile(r'{}.(so|dll|dylib)$'.format(expected_name))
+            expected_name = f'libLLVM-{self.version}'
+            re_name = re.compile(fr'{expected_name}.(so|dll|dylib)$')
 
             for file_ in os.listdir(libdir):
                 if re_name.match(file_):
-                    self.link_args = ['-L{}'.format(libdir),
+                    self.link_args = [f'-L{libdir}',
                                       '-l{}'.format(os.path.splitext(file_.lstrip('lib'))[0])]
                     break
             else:
                 raise DependencyException(
                     'Could not find a dynamically linkable library for LLVM.')
 
-    def check_components(self, modules, required=True):
+    def check_components(self, modules: T.List[str], required: bool = True) -> None:
         """Check for llvm components (modules in meson terms).
 
         The required option is whether the module is required, not whether LLVM
@@ -376,7 +374,7 @@
                     self.is_found = False
                     if self.required:
                         raise DependencyException(
-                            'Could not find required LLVM Component: {}'.format(mod))
+                            f'Could not find required LLVM Component: {mod}')
                     status = '(missing)'
                 else:
                     status = '(missing but optional)'
@@ -385,23 +383,38 @@
 
             self.module_details.append(mod + status)
 
-    def log_details(self):
+    def log_details(self) -> str:
         if self.module_details:
             return 'modules: ' + ', '.join(self.module_details)
         return ''
 
 class LLVMDependencyCMake(CMakeDependency):
-    def __init__(self, env, kwargs):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
         self.llvm_modules = stringlistify(extract_as_list(kwargs, 'modules'))
         self.llvm_opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules'))
-        super().__init__(name='LLVM', environment=env, language='cpp', kwargs=kwargs)
+        super().__init__(name, env, kwargs, language='cpp')
+
+        # Cmake will always create a statically linked binary, so don't use
+        # cmake if dynamic is required
+        if not self.static:
+            self.is_found = False
+            mlog.warning('Ignoring LLVM CMake dependency because dynamic was requested')
+            return
+
+        if self.traceparser is None:
+            return
 
         # Extract extra include directories and definitions
         inc_dirs = self.traceparser.get_cmake_var('PACKAGE_INCLUDE_DIRS')
         defs = self.traceparser.get_cmake_var('PACKAGE_DEFINITIONS')
+        # LLVM explicitly uses space-separated variables rather than semicolon lists
+        if len(defs) == 1:
+            defs = defs[0].split(' ')
         temp = ['-I' + x for x in inc_dirs] + defs
         self.compile_args += [x for x in temp if x not in self.compile_args]
-        self._add_sub_dependency(ThreadDependency, env, kwargs)
+        if not self._add_sub_dependency(threads_factory(env, self.for_machine, {})):
+            self.is_found = False
+            return
 
     def _main_cmake_file(self) -> str:
         # Use a custom CMakeLists.txt for LLVM
@@ -410,13 +423,13 @@
     def _extra_cmake_opts(self) -> T.List[str]:
         return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules + self.llvm_opt_modules))]
 
-    def _map_module_list(self, modules: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
+    def _map_module_list(self, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
         res = []
         for mod, required in modules:
-            cm_targets = self.traceparser.get_cmake_var('MESON_LLVM_TARGETS_{}'.format(mod))
+            cm_targets = self.traceparser.get_cmake_var(f'MESON_LLVM_TARGETS_{mod}')
             if not cm_targets:
                 if required:
-                    raise self._gen_exception('LLVM module {} was not found'.format(mod))
+                    raise self._gen_exception(f'LLVM module {mod} was not found')
                 else:
                     mlog.warning('Optional LLVM module', mlog.bold(mod), 'was not found')
                     continue
@@ -425,39 +438,140 @@
         return res
 
     def _original_module_name(self, module: str) -> str:
-        orig_name = self.traceparser.get_cmake_var('MESON_TARGET_TO_LLVM_{}'.format(module))
+        orig_name = self.traceparser.get_cmake_var(f'MESON_TARGET_TO_LLVM_{module}')
         if orig_name:
             return orig_name[0]
         return module
 
-class LLVMDependency(ExternalDependency):
-    def __init__(self, env, kwargs):
-        super().__init__('LLVM', env, 'cpp', kwargs)
-
-    @classmethod
-    def _factory(cls, env, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.CONFIG_TOOL in methods:
-            candidates.append(functools.partial(LLVMDependencyConfigTool, env, kwargs))
-
-        if DependencyMethods.CMAKE in methods:
-            candidates.append(functools.partial(LLVMDependencyCMake, env, kwargs))
-
-        return candidates
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.CMAKE, DependencyMethods.CONFIG_TOOL]
 
 class ValgrindDependency(PkgConfigDependency):
     '''
     Consumers of Valgrind usually only need the compile args and do not want to
     link to its (static) libraries.
     '''
-    def __init__(self, env, kwargs):
+    def __init__(self, env: 'Environment', kwargs: T.Dict[str, T.Any]):
         super().__init__('valgrind', env, kwargs)
 
-    def get_link_args(self, **kwargs):
+    def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
         return []
+
+
+class ZlibSystemDependency(SystemDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+
+        m = self.env.machines[self.for_machine]
+
+        # I'm not sure this is entirely correct. What if we're cross compiling
+        # from something to macOS?
+        if ((m.is_darwin() and isinstance(self.clib_compiler, (AppleClangCCompiler, AppleClangCPPCompiler))) or
+                m.is_freebsd() or m.is_dragonflybsd() or m.is_android()):
+            # No need to set includes,
+            # on macos xcode/clang will do that for us.
+            # on freebsd zlib.h is in /usr/include
+
+            self.is_found = True
+            self.link_args = ['-lz']
+        else:
+            # Without a clib_compiler we can't find zlib, so just give up.
+            if self.clib_compiler is None:
+                self.is_found = False
+                return
+
+            if self.clib_compiler.get_argument_syntax() == 'msvc':
+                libs = ['zlib1' 'zlib']
+            else:
+                libs = ['z']
+            for lib in libs:
+                l = self.clib_compiler.find_library(lib, environment, [])
+                h = self.clib_compiler.has_header('zlib.h', '', environment, dependencies=[self])
+                if l and h[0]:
+                    self.is_found = True
+                    self.link_args = l
+                    break
+            else:
+                return
+
+        v, _ = self.clib_compiler.get_define('ZLIB_VERSION', '#include ', self.env, [], [self])
+        self.version = v.strip('"')
+
+
+class JDKSystemDependency(SystemDependency):
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__('jdk', environment, kwargs)
+
+        m = self.env.machines[self.for_machine]
+
+        if 'java' not in environment.coredata.compilers[self.for_machine]:
+            detect_compiler_for(environment, 'java', self.for_machine)
+        self.javac = environment.coredata.compilers[self.for_machine]['java']
+        self.version = self.javac.version
+
+        if 'version' in kwargs and not version_compare(self.version, kwargs['version']):
+            mlog.error(f'Incorrect JDK version found ({self.version}), wanted {kwargs["version"]}')
+            self.is_found = False
+            return
+
+        self.java_home = environment.properties[self.for_machine].get_java_home()
+        if not self.java_home:
+            self.java_home = pathlib.Path(shutil.which(self.javac.exelist[0])).resolve().parents[1]
+
+        platform_include_dir = self.__machine_info_to_platform_include_dir(m)
+        if platform_include_dir is None:
+            mlog.error("Could not find a JDK platform include directory for your OS, please open an issue or provide a pull request.")
+            self.is_found = False
+            return
+
+        java_home_include = self.java_home / 'include'
+        self.compile_args.append(f'-I{java_home_include}')
+        self.compile_args.append(f'-I{java_home_include / platform_include_dir}')
+        self.is_found = True
+
+    @staticmethod
+    def __machine_info_to_platform_include_dir(m: 'MachineInfo') -> T.Optional[str]:
+        """Translates the machine information to the platform-dependent include directory
+
+        When inspecting a JDK release tarball or $JAVA_HOME, inside the `include/` directory is a
+        platform dependent folder that must be on the target's include path in addition to the
+        parent `include/` directory.
+        """
+        if m.is_linux():
+            return 'linux'
+        elif m.is_windows():
+            return 'win32'
+        elif m.is_darwin():
+            return 'darwin'
+        elif m.is_sunos():
+            return 'solaris'
+
+        return None
+
+
+llvm_factory = DependencyFactory(
+    'LLVM',
+    [DependencyMethods.CMAKE, DependencyMethods.CONFIG_TOOL],
+    cmake_class=LLVMDependencyCMake,
+    configtool_class=LLVMDependencyConfigTool,
+)
+
+gtest_factory = DependencyFactory(
+    'gtest',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    pkgconfig_class=GTestDependencyPC,
+    system_class=GTestDependencySystem,
+)
+
+gmock_factory = DependencyFactory(
+    'gmock',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    pkgconfig_class=GMockDependencyPC,
+    system_class=GMockDependencySystem,
+)
+
+zlib_factory = DependencyFactory(
+    'zlib',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE, DependencyMethods.SYSTEM],
+    cmake_name='ZLIB',
+    system_class=ZlibSystemDependency,
+)
diff -Nru meson-0.53.2/mesonbuild/dependencies/dub.py meson-0.61.2/mesonbuild/dependencies/dub.py
--- meson-0.53.2/mesonbuild/dependencies/dub.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/dub.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,236 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .base import ExternalDependency, DependencyException, DependencyTypeName
+from .pkgconfig import PkgConfigDependency
+from ..mesonlib import Popen_safe
+from ..programs import ExternalProgram
+from ..compilers import DCompiler
+from .. import mlog
+import re
+import os
+import copy
+import json
+import platform
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+class DubDependency(ExternalDependency):
+    class_dubbin = None
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(DependencyTypeName('dub'), environment, kwargs, language='d')
+        self.name = name
+        self.module_path: T.Optional[str] = None
+
+        _temp_comp = super().get_compiler()
+        assert isinstance(_temp_comp, DCompiler)
+        self.compiler = _temp_comp
+
+        if 'required' in kwargs:
+            self.required = kwargs.get('required')
+
+        if DubDependency.class_dubbin is None:
+            self.dubbin = self._check_dub()
+            DubDependency.class_dubbin = self.dubbin
+        else:
+            self.dubbin = DubDependency.class_dubbin
+
+        if not self.dubbin:
+            if self.required:
+                raise DependencyException('DUB not found.')
+            self.is_found = False
+            return
+
+        assert isinstance(self.dubbin, ExternalProgram)
+        mlog.debug('Determining dependency {!r} with DUB executable '
+                   '{!r}'.format(name, self.dubbin.get_path()))
+
+        # we need to know the target architecture
+        arch = self.compiler.arch
+
+        # Ask dub for the package
+        ret, res = self._call_dubbin(['describe', name, '--arch=' + arch])
+
+        if ret != 0:
+            self.is_found = False
+            return
+
+        comp = self.compiler.get_id().replace('llvm', 'ldc').replace('gcc', 'gdc')
+        packages = []
+        description = json.loads(res)
+        for package in description['packages']:
+            packages.append(package['name'])
+            if package['name'] == name:
+                self.is_found = True
+
+                not_lib = True
+                if 'targetType' in package:
+                    if package['targetType'] in ['library', 'sourceLibrary', 'staticLibrary', 'dynamicLibrary']:
+                        not_lib = False
+
+                if not_lib:
+                    mlog.error(mlog.bold(name), "found but it isn't a library")
+                    self.is_found = False
+                    return
+
+                self.module_path = self._find_right_lib_path(package['path'], comp, description, True, package['targetFileName'])
+                if not os.path.exists(self.module_path):
+                    # check if the dependency was built for other archs
+                    archs = [['x86_64'], ['x86'], ['x86', 'x86_mscoff']]
+                    for a in archs:
+                        description_a = copy.deepcopy(description)
+                        description_a['architecture'] = a
+                        arch_module_path = self._find_right_lib_path(package['path'], comp, description_a, True, package['targetFileName'])
+                        if arch_module_path:
+                            mlog.error(mlog.bold(name), "found but it wasn't compiled for", mlog.bold(arch))
+                            self.is_found = False
+                            return
+
+                    mlog.error(mlog.bold(name), "found but it wasn't compiled with", mlog.bold(comp))
+                    self.is_found = False
+                    return
+
+                self.version = package['version']
+                self.pkg = package
+
+        if self.pkg['targetFileName'].endswith('.a'):
+            self.static = True
+
+        self.compile_args = []
+        for flag in self.pkg['dflags']:
+            self.link_args.append(flag)
+        for path in self.pkg['importPaths']:
+            self.compile_args.append('-I' + os.path.join(self.pkg['path'], path))
+
+        self.link_args = self.raw_link_args = []
+        for flag in self.pkg['lflags']:
+            self.link_args.append(flag)
+
+        self.link_args.append(os.path.join(self.module_path, self.pkg['targetFileName']))
+
+        # Handle dependencies
+        libs = []
+
+        def add_lib_args(field_name: str, target: T.Dict[str, T.Dict[str, str]]) -> None:
+            if field_name in target['buildSettings']:
+                for lib in target['buildSettings'][field_name]:
+                    if lib not in libs:
+                        libs.append(lib)
+                        if os.name != 'nt':
+                            pkgdep = PkgConfigDependency(lib, environment, {'required': 'true', 'silent': 'true'})
+                            for arg in pkgdep.get_compile_args():
+                                self.compile_args.append(arg)
+                            for arg in pkgdep.get_link_args():
+                                self.link_args.append(arg)
+                            for arg in pkgdep.get_link_args(raw=True):
+                                self.raw_link_args.append(arg)
+
+        for target in description['targets']:
+            if target['rootPackage'] in packages:
+                add_lib_args('libs', target)
+                add_lib_args(f'libs-{platform.machine()}', target)
+                for file in target['buildSettings']['linkerFiles']:
+                    lib_path = self._find_right_lib_path(file, comp, description)
+                    if lib_path:
+                        self.link_args.append(lib_path)
+                    else:
+                        self.is_found = False
+
+    def _find_right_lib_path(self,
+                             default_path: str,
+                             comp: str,
+                             description: T.Dict[str, str],
+                             folder_only: bool = False,
+                             file_name: str = '') -> T.Optional[str]:
+        module_path = lib_file_name = ''
+        if folder_only:
+            module_path = default_path
+            lib_file_name = file_name
+        else:
+            module_path = os.path.dirname(default_path)
+            lib_file_name = os.path.basename(default_path)
+        module_build_path = os.path.join(module_path, '.dub', 'build')
+
+        # If default_path is a path to lib file and
+        # directory of lib don't have subdir '.dub/build'
+        if not os.path.isdir(module_build_path) and os.path.isfile(default_path):
+            if folder_only:
+                return module_path
+            else:
+                return default_path
+
+        # Get D version implemented in the compiler
+        # gdc doesn't support this
+        ret, res = self._call_dubbin(['--version'])
+
+        if ret != 0:
+            mlog.error('Failed to run {!r}', mlog.bold(comp))
+            return None
+
+        d_ver_reg = re.search('v[0-9].[0-9][0-9][0-9].[0-9]', res) # Ex.: v2.081.2
+        if d_ver_reg is not None:
+            d_ver = d_ver_reg.group().rsplit('.', 1)[0].replace('v', '').replace('.', '') # Fix structure. Ex.: 2081
+        else:
+            d_ver = '' # gdc
+
+        if not os.path.isdir(module_build_path):
+            return ''
+
+        # Ex.: library-debug-linux.posix-x86_64-ldc_2081-EF934983A3319F8F8FF2F0E107A363BA
+        build_name = '-{}-{}-{}-{}_{}'.format(description['buildType'], '.'.join(description['platform']), '.'.join(description['architecture']), comp, d_ver)
+        for entry in os.listdir(module_build_path):
+            if build_name in entry:
+                for file in os.listdir(os.path.join(module_build_path, entry)):
+                    if file == lib_file_name:
+                        if folder_only:
+                            return os.path.join(module_build_path, entry)
+                        else:
+                            return os.path.join(module_build_path, entry, lib_file_name)
+
+        return ''
+
+    def _call_dubbin(self, args: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str]:
+        assert isinstance(self.dubbin, ExternalProgram)
+        p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2]
+        return p.returncode, out.strip()
+
+    def _call_copmbin(self, args: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str]:
+        p, out = Popen_safe(self.compiler.get_exelist() + args, env=env)[0:2]
+        return p.returncode, out.strip()
+
+    def _check_dub(self) -> T.Union[bool, ExternalProgram]:
+        dubbin: T.Union[bool, ExternalProgram] = ExternalProgram('dub', silent=True)
+        assert isinstance(dubbin, ExternalProgram)
+        if dubbin.found():
+            try:
+                p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2]
+                if p.returncode != 0:
+                    mlog.warning('Found dub {!r} but couldn\'t run it'
+                                 ''.format(' '.join(dubbin.get_command())))
+                    # Set to False instead of None to signify that we've already
+                    # searched for it and not found it
+                    dubbin = False
+            except (FileNotFoundError, PermissionError):
+                dubbin = False
+        else:
+            dubbin = False
+        if isinstance(dubbin, ExternalProgram):
+            mlog.log('Found DUB:', mlog.bold(dubbin.get_path()),
+                     '(%s)' % out.strip())
+        else:
+            mlog.log('Found DUB:', mlog.red('NO'))
+        return dubbin
diff -Nru meson-0.53.2/mesonbuild/dependencies/factory.py meson-0.61.2/mesonbuild/dependencies/factory.py
--- meson-0.53.2/mesonbuild/dependencies/factory.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/factory.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,151 @@
+# Copyright 2013-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+# 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 functools
+import typing as T
+
+from ..mesonlib import MachineChoice
+from .base import DependencyException, DependencyMethods
+from .base import ExternalDependency
+from .base import process_method_kw
+from .base import BuiltinDependency, SystemDependency
+from .cmake import CMakeDependency
+from .framework import ExtraFrameworkDependency
+from .pkgconfig import PkgConfigDependency
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+    from .configtool import ConfigToolDependency
+
+    DependencyGenerator = T.Callable[[], ExternalDependency]
+    FactoryFunc = T.Callable[
+        [
+            'Environment',
+            MachineChoice,
+            T.Dict[str, T.Any],
+            T.List[DependencyMethods]
+        ],
+        T.List[DependencyGenerator]
+    ]
+
+    WrappedFactoryFunc = T.Callable[
+        [
+            'Environment',
+            MachineChoice,
+            T.Dict[str, T.Any]
+        ],
+        T.List[DependencyGenerator]
+    ]
+
+class DependencyFactory:
+
+    """Factory to get dependencies from multiple sources.
+
+    This class provides an initializer that takes a set of names and classes
+    for various kinds of dependencies. When the initialized object is called
+    it returns a list of callables return Dependency objects to try in order.
+
+    :name: The name of the dependency. This will be passed as the name
+        parameter of the each dependency unless it is overridden on a per
+        type basis.
+    :methods: An ordered list of DependencyMethods. This is the order
+        dependencies will be returned in unless they are removed by the
+        _process_method function
+    :*_name: This will overwrite the name passed to the corresponding class.
+        For example, if the name is 'zlib', but cmake calls the dependency
+        'Z', then using `cmake_name='Z'` will pass the name as 'Z' to cmake.
+    :*_class: A *type* or callable that creates a class, and has the
+        signature of an ExternalDependency
+    :system_class: If you pass DependencyMethods.SYSTEM in methods, you must
+        set this argument.
+    """
+
+    def __init__(self, name: str, methods: T.List[DependencyMethods], *,
+                 extra_kwargs: T.Optional[T.Dict[str, T.Any]] = None,
+                 pkgconfig_name: T.Optional[str] = None,
+                 pkgconfig_class: 'T.Type[PkgConfigDependency]' = PkgConfigDependency,
+                 cmake_name: T.Optional[str] = None,
+                 cmake_class: 'T.Type[CMakeDependency]' = CMakeDependency,
+                 configtool_class: 'T.Optional[T.Type[ConfigToolDependency]]' = None,
+                 framework_name: T.Optional[str] = None,
+                 framework_class: 'T.Type[ExtraFrameworkDependency]' = ExtraFrameworkDependency,
+                 builtin_class: 'T.Type[BuiltinDependency]' = BuiltinDependency,
+                 system_class: 'T.Type[SystemDependency]' = SystemDependency):
+
+        if DependencyMethods.CONFIG_TOOL in methods and not configtool_class:
+            raise DependencyException('A configtool must have a custom class')
+
+        self.extra_kwargs = extra_kwargs or {}
+        self.methods = methods
+        self.classes: T.Dict[
+            DependencyMethods,
+            T.Callable[['Environment', T.Dict[str, T.Any]], ExternalDependency]
+        ] = {
+            # Just attach the correct name right now, either the generic name
+            # or the method specific name.
+            DependencyMethods.EXTRAFRAMEWORK: lambda env, kwargs: framework_class(framework_name or name, env, kwargs),
+            DependencyMethods.PKGCONFIG:      lambda env, kwargs: pkgconfig_class(pkgconfig_name or name, env, kwargs),
+            DependencyMethods.CMAKE:          lambda env, kwargs: cmake_class(cmake_name or name, env, kwargs),
+            DependencyMethods.SYSTEM:         lambda env, kwargs: system_class(name, env, kwargs),
+            DependencyMethods.BUILTIN:        lambda env, kwargs: builtin_class(name, env, kwargs),
+            DependencyMethods.CONFIG_TOOL:    None,
+        }
+        if configtool_class is not None:
+            self.classes[DependencyMethods.CONFIG_TOOL] = lambda env, kwargs: configtool_class(name, env, kwargs)
+
+    @staticmethod
+    def _process_method(method: DependencyMethods, env: 'Environment', for_machine: MachineChoice) -> bool:
+        """Report whether a method is valid or not.
+
+        If the method is valid, return true, otherwise return false. This is
+        used in a list comprehension to filter methods that are not possible.
+
+        By default this only remove EXTRAFRAMEWORK dependencies for non-mac platforms.
+        """
+        # Extra frameworks are only valid for macOS and other apple products
+        if (method is DependencyMethods.EXTRAFRAMEWORK and
+                not env.machines[for_machine].is_darwin()):
+            return False
+        return True
+
+    def __call__(self, env: 'Environment', for_machine: MachineChoice,
+                 kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']:
+        """Return a list of Dependencies with the arguments already attached."""
+        methods = process_method_kw(self.methods, kwargs)
+        nwargs = self.extra_kwargs.copy()
+        nwargs.update(kwargs)
+
+        return [functools.partial(self.classes[m], env, nwargs) for m in methods
+                if self._process_method(m, env, for_machine)]
+
+
+def factory_methods(methods: T.Set[DependencyMethods]) -> T.Callable[['FactoryFunc'], 'WrappedFactoryFunc']:
+    """Decorator for handling methods for dependency factory functions.
+
+    This helps to make factory functions self documenting
+    >>> @factory_methods([DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE])
+    >>> def factory(env: Environment, for_machine: MachineChoice, kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    >>>     pass
+    """
+
+    def inner(func: 'FactoryFunc') -> 'WrappedFactoryFunc':
+
+        @functools.wraps(func)
+        def wrapped(env: 'Environment', for_machine: MachineChoice, kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']:
+            return func(env, for_machine, kwargs, process_method_kw(methods, kwargs))
+
+        return wrapped
+
+    return inner
diff -Nru meson-0.53.2/mesonbuild/dependencies/framework.py meson-0.61.2/mesonbuild/dependencies/framework.py
--- meson-0.53.2/mesonbuild/dependencies/framework.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/framework.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,119 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .base import DependencyTypeName, ExternalDependency, DependencyException
+from ..mesonlib import MesonException, Version, stringlistify
+from .. import mlog
+from pathlib import Path
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+class ExtraFrameworkDependency(ExternalDependency):
+    system_framework_paths: T.Optional[T.List[str]] = None
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        paths = stringlistify(kwargs.get('paths', []))
+        super().__init__(DependencyTypeName('extraframeworks'), env, kwargs, language=language)
+        self.name = name
+        # Full path to framework directory
+        self.framework_path: T.Optional[str] = None
+        if not self.clib_compiler:
+            raise DependencyException('No C-like compilers are available')
+        if self.system_framework_paths is None:
+            try:
+                self.system_framework_paths = self.clib_compiler.find_framework_paths(self.env)
+            except MesonException as e:
+                if 'non-clang' in str(e):
+                    # Apple frameworks can only be found (and used) with the
+                    # system compiler. It is not available so bail immediately.
+                    self.is_found = False
+                    return
+                raise
+        self.detect(name, paths)
+
+    def detect(self, name: str, paths: T.List[str]) -> None:
+        if not paths:
+            paths = self.system_framework_paths
+        for p in paths:
+            mlog.debug(f'Looking for framework {name} in {p}')
+            # We need to know the exact framework path because it's used by the
+            # Qt5 dependency class, and for setting the include path. We also
+            # want to avoid searching in an invalid framework path which wastes
+            # time and can cause a false positive.
+            framework_path = self._get_framework_path(p, name)
+            if framework_path is None:
+                continue
+            # We want to prefer the specified paths (in order) over the system
+            # paths since these are "extra" frameworks.
+            # For example, Python2's framework is in /System/Library/Frameworks and
+            # Python3's framework is in /Library/Frameworks, but both are called
+            # Python.framework. We need to know for sure that the framework was
+            # found in the path we expect.
+            allow_system = p in self.system_framework_paths
+            args = self.clib_compiler.find_framework(name, self.env, [p], allow_system)
+            if args is None:
+                continue
+            self.link_args = args
+            self.framework_path = framework_path.as_posix()
+            self.compile_args = ['-F' + self.framework_path]
+            # We need to also add -I includes to the framework because all
+            # cross-platform projects such as OpenGL, Python, Qt, GStreamer,
+            # etc do not use "framework includes":
+            # https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/IncludingFrameworks.html
+            incdir = self._get_framework_include_path(framework_path)
+            if incdir:
+                self.compile_args += ['-I' + incdir]
+            self.is_found = True
+            return
+
+    def _get_framework_path(self, path: str, name: str) -> T.Optional[Path]:
+        p = Path(path)
+        lname = name.lower()
+        for d in p.glob('*.framework/'):
+            if lname == d.name.rsplit('.', 1)[0].lower():
+                return d
+        return None
+
+    def _get_framework_latest_version(self, path: Path) -> str:
+        versions = []
+        for each in path.glob('Versions/*'):
+            # macOS filesystems are usually case-insensitive
+            if each.name.lower() == 'current':
+                continue
+            versions.append(Version(each.name))
+        if len(versions) == 0:
+            # most system frameworks do not have a 'Versions' directory
+            return 'Headers'
+        return 'Versions/{}/Headers'.format(sorted(versions)[-1]._s)
+
+    def _get_framework_include_path(self, path: Path) -> T.Optional[str]:
+        # According to the spec, 'Headers' must always be a symlink to the
+        # Headers directory inside the currently-selected version of the
+        # framework, but sometimes frameworks are broken. Look in 'Versions'
+        # for the currently-selected version or pick the latest one.
+        trials = ('Headers', 'Versions/Current/Headers',
+                  self._get_framework_latest_version(path))
+        for each in trials:
+            trial = path / each
+            if trial.is_dir():
+                return trial.as_posix()
+        return None
+
+    def log_info(self) -> str:
+        return self.framework_path or ''
+
+    def log_tried(self) -> str:
+        return 'framework'
diff -Nru meson-0.53.2/mesonbuild/dependencies/hdf5.py meson-0.61.2/mesonbuild/dependencies/hdf5.py
--- meson-0.53.2/mesonbuild/dependencies/hdf5.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/hdf5.py	2022-01-17 10:50:45.000000000 +0000
@@ -14,117 +14,166 @@
 
 # This file contains the detection logic for miscellaneous external dependencies.
 
-import subprocess
+import functools
+import os
+import re
 import shutil
+import subprocess
 from pathlib import Path
 
-from .. import mlog
-from ..mesonlib import split_args, listify
-from .base import (DependencyException, DependencyMethods, ExternalDependency, ExternalProgram,
-                   PkgConfigDependency)
-
-class HDF5Dependency(ExternalDependency):
-
-    def __init__(self, environment, kwargs):
-        language = kwargs.get('language', 'c')
-        super().__init__('hdf5', environment, language, kwargs)
-        kwargs['required'] = False
-        kwargs['silent'] = True
-        self.is_found = False
-        methods = listify(self.methods)
-
-        if language not in ('c', 'cpp', 'fortran'):
-            raise DependencyException('Language {} is not supported with HDF5.'.format(language))
-
-        if set([DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]).intersection(methods):
-            pkgconfig_files = ['hdf5', 'hdf5-serial']
-            PCEXE = shutil.which('pkg-config')
-            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)
-                if ret.returncode == 0:
-                    for pkg in ret.stdout.split('\n'):
-                        if pkg.startswith(('hdf5')):
-                            pkgconfig_files.append(pkg.split(' ', 1)[0])
-                    pkgconfig_files = list(set(pkgconfig_files))  # dedupe
-
-            for pkg in pkgconfig_files:
-                pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language)
-                if not pkgdep.found():
-                    continue
-
-                self.compile_args = pkgdep.get_compile_args()
-                # some broken pkgconfig don't actually list the full path to the needed includes
-                newinc = []
-                for arg in self.compile_args:
-                    if arg.startswith('-I'):
-                        stem = 'static' if kwargs.get('static', False) else 'shared'
-                        if (Path(arg[2:]) / stem).is_dir():
-                            newinc.append('-I' + str(Path(arg[2:]) / stem))
-                self.compile_args += newinc
-
-                # derive needed libraries by language
-                pd_link_args = pkgdep.get_link_args()
-                link_args = []
-                for larg in pd_link_args:
-                    lpath = Path(larg)
-                    # some pkg-config hdf5.pc (e.g. Ubuntu) don't include the commonly-used HL HDF5 libraries,
-                    # so let's add them if they exist
-                    # additionally, some pkgconfig HDF5 HL files are malformed so let's be sure to find HL anyway
-                    if lpath.is_file():
-                        hl = []
-                        if language == 'cpp':
-                            hl += ['_hl_cpp', '_cpp']
-                        elif language == 'fortran':
-                            hl += ['_hl_fortran', 'hl_fortran', '_fortran']
-                        hl += ['_hl']  # C HL library, always needed
-
-                        suffix = '.' + lpath.name.split('.', 1)[1]  # in case of .dll.a
-                        for h in hl:
-                            hlfn = lpath.parent / (lpath.name.split('.', 1)[0] + h + suffix)
-                            if hlfn.is_file():
-                                link_args.append(str(hlfn))
-                        # HDF5 C libs are required by other HDF5 languages
-                        link_args.append(larg)
-                    else:
-                        link_args.append(larg)
-
-                self.link_args = link_args
-                self.version = pkgdep.get_version()
-                self.is_found = True
-                self.pcdep = pkgdep
-                return
-
-        if DependencyMethods.AUTO in methods:
-            wrappers = {'c': 'h5cc', 'cpp': 'h5c++', 'fortran': 'h5fc'}
-            comp_args = []
-            link_args = []
-            # have to always do C as well as desired language
-            for lang in set([language, 'c']):
-                prog = ExternalProgram(wrappers[lang], silent=True)
-                if not prog.found():
-                    return
-                cmd = prog.get_command() + ['-show']
-                p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
-                if p.returncode != 0:
-                    mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
-                    mlog.debug(mlog.bold('Standard output\n'), p.stdout)
-                    mlog.debug(mlog.bold('Standard error\n'), p.stderr)
-                    return
-                args = split_args(p.stdout)
-                for arg in args[1:]:
-                    if arg.startswith(('-I', '-f', '-D')) or arg == '-pthread':
-                        comp_args.append(arg)
-                    elif arg.startswith(('-L', '-l', '-Wl')):
-                        link_args.append(arg)
-                    elif Path(arg).is_file():
-                        link_args.append(arg)
-            self.compile_args = comp_args
-            self.link_args = link_args
-            self.is_found = True
+from ..mesonlib import OrderedSet, join_args
+from .base import DependencyException, DependencyMethods
+from .configtool import ConfigToolDependency
+from .pkgconfig import PkgConfigDependency
+from .factory import factory_methods
+import typing as T
+
+if T.TYPE_CHECKING:
+    from .factory import DependencyGenerator
+    from ..environment import Environment
+    from ..mesonlib import MachineChoice
+
+
+class HDF5PkgConfigDependency(PkgConfigDependency):
+
+    """Handle brokenness in the HDF5 pkg-config files."""
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        language = language or 'c'
+        if language not in {'c', 'cpp', 'fortran'}:
+            raise DependencyException(f'Language {language} is not supported with HDF5.')
+
+        super().__init__(name, environment, kwargs, language)
+        if not self.is_found:
+            return
+
+        # some broken pkgconfig don't actually list the full path to the needed includes
+        newinc = []  # type: T.List[str]
+        for arg in self.compile_args:
+            if arg.startswith('-I'):
+                stem = 'static' if kwargs.get('static', False) else 'shared'
+                if (Path(arg[2:]) / stem).is_dir():
+                    newinc.append('-I' + str(Path(arg[2:]) / stem))
+        self.compile_args += newinc
+
+        link_args = []  # type: T.List[str]
+        for larg in self.get_link_args():
+            lpath = Path(larg)
+            # some pkg-config hdf5.pc (e.g. Ubuntu) don't include the commonly-used HL HDF5 libraries,
+            # so let's add them if they exist
+            # additionally, some pkgconfig HDF5 HL files are malformed so let's be sure to find HL anyway
+            if lpath.is_file():
+                hl = []
+                if language == 'cpp':
+                    hl += ['_hl_cpp', '_cpp']
+                elif language == 'fortran':
+                    hl += ['_hl_fortran', 'hl_fortran', '_fortran']
+                hl += ['_hl']  # C HL library, always needed
+
+                suffix = '.' + lpath.name.split('.', 1)[1]  # in case of .dll.a
+                for h in hl:
+                    hlfn = lpath.parent / (lpath.name.split('.', 1)[0] + h + suffix)
+                    if hlfn.is_file():
+                        link_args.append(str(hlfn))
+                # HDF5 C libs are required by other HDF5 languages
+                link_args.append(larg)
+            else:
+                link_args.append(larg)
+
+        self.link_args = link_args
+
+
+class HDF5ConfigToolDependency(ConfigToolDependency):
+
+    """Wrapper around hdf5 binary config tools."""
+
+    version_arg = '-showconfig'
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        language = language or 'c'
+        if language not in {'c', 'cpp', 'fortran'}:
+            raise DependencyException(f'Language {language} is not supported with HDF5.')
+
+        if language == 'c':
+            cenv = 'CC'
+            tools = ['h5cc', 'h5pcc']
+        elif language == 'cpp':
+            cenv = 'CXX'
+            tools = ['h5c++', 'h5pc++']
+        elif language == 'fortran':
+            cenv = 'FC'
+            tools = ['h5fc', 'h5pfc']
+        else:
+            raise DependencyException('How did you get here?')
+
+        # We need this before we call super()
+        for_machine = self.get_for_machine_from_kwargs(kwargs)
+
+        nkwargs = kwargs.copy()
+        nkwargs['tools'] = tools
+
+        # Override the compiler that the config tools are going to use by
+        # setting the environment variables that they use for the compiler and
+        # linkers.
+        compiler = environment.coredata.compilers[for_machine][language]
+        try:
+            os.environ[f'HDF5_{cenv}'] = join_args(compiler.get_exelist())
+            os.environ[f'HDF5_{cenv}LINKER'] = join_args(compiler.get_linker_exelist())
+            super().__init__(name, environment, nkwargs, language)
+        finally:
+            del os.environ[f'HDF5_{cenv}']
+            del os.environ[f'HDF5_{cenv}LINKER']
+        if not self.is_found:
             return
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]
+        # We first need to call the tool with -c to get the compile arguments
+        # and then without -c to get the link arguments.
+        args = self.get_config_value(['-show', '-c'], 'args')[1:]
+        args += self.get_config_value(['-show', '-noshlib' if kwargs.get('static', False) else '-shlib'], 'args')[1:]
+        for arg in args:
+            if arg.startswith(('-I', '-f', '-D')) or arg == '-pthread':
+                self.compile_args.append(arg)
+            elif arg.startswith(('-L', '-l', '-Wl')):
+                self.link_args.append(arg)
+            elif Path(arg).is_file():
+                self.link_args.append(arg)
+
+        # If the language is not C we need to add C as a subdependency
+        if language != 'c':
+            nkwargs = kwargs.copy()
+            nkwargs['language'] = 'c'
+            # I'm being too clever for mypy and pylint
+            self.is_found = self._add_sub_dependency(hdf5_factory(environment, for_machine, nkwargs))  # pylint: disable=no-value-for-parameter
+
+    def _sanitize_version(self, ver: str) -> str:
+        v = re.search(r'\s*HDF5 Version: (\d+\.\d+\.\d+)', ver)
+        return v.group(1)
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL})
+def hdf5_factory(env: 'Environment', for_machine: 'MachineChoice',
+                 kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    language = kwargs.get('language')
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        # Use an ordered set so that these remain the first tried pkg-config files
+        pkgconfig_files = OrderedSet(['hdf5', 'hdf5-serial'])
+        # FIXME: This won't honor pkg-config paths, and cross-native files
+        PCEXE = shutil.which('pkg-config')
+        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)
+            if ret.returncode == 0:
+                for pkg in ret.stdout.split('\n'):
+                    if pkg.startswith('hdf5'):
+                        pkgconfig_files.add(pkg.split(' ', 1)[0])
+
+        for pkg in pkgconfig_files:
+            candidates.append(functools.partial(HDF5PkgConfigDependency, pkg, env, kwargs, language))
+
+    if DependencyMethods.CONFIG_TOOL in methods:
+        candidates.append(functools.partial(HDF5ConfigToolDependency, 'hdf5', env, kwargs, language))
+
+    return candidates
diff -Nru meson-0.53.2/mesonbuild/dependencies/__init__.py meson-0.61.2/mesonbuild/dependencies/__init__.py
--- meson-0.53.2/mesonbuild/dependencies/__init__.py	2020-01-23 22:29:05.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/__init__.py	2021-11-02 19:58:07.000000000 +0000
@@ -14,60 +14,259 @@
 
 from .boost import BoostDependency
 from .cuda import CudaDependency
-from .hdf5 import HDF5Dependency
-from .base import (  # noqa: F401
-    Dependency, DependencyException, DependencyMethods, ExternalProgram, EmptyExternalProgram, NonExistingExternalProgram,
-    ExternalDependency, NotFoundDependency, ExternalLibrary, ExtraFrameworkDependency, InternalDependency,
-    PkgConfigDependency, CMakeDependency, find_external_dependency, get_dep_identifier, packages, _packages_accept_language)
-from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency
-from .coarrays import CoarrayDependency
-from .mpi import MPIDependency
-from .scalapack import ScalapackDependency
-from .misc import (BlocksDependency, NetCDFDependency, OpenMPDependency, Python3Dependency, ThreadDependency, PcapDependency, CupsDependency, LibWmfDependency, LibGCryptDependency, GpgmeDependency, ShadercDependency)
+from .hdf5 import hdf5_factory
+from .base import Dependency, InternalDependency, ExternalDependency, NotFoundDependency
+from .base import (
+        ExternalLibrary, DependencyException, DependencyMethods,
+        BuiltinDependency, SystemDependency)
+from .cmake import CMakeDependency
+from .configtool import ConfigToolDependency
+from .dub import DubDependency
+from .framework import ExtraFrameworkDependency
+from .pkgconfig import PkgConfigDependency
+from .factory import DependencyFactory
+from .detect import find_external_dependency, get_dep_identifier, packages, _packages_accept_language
+from .dev import (
+    ValgrindDependency, JDKSystemDependency, gmock_factory, gtest_factory,
+    llvm_factory, zlib_factory)
+from .coarrays import coarray_factory
+from .mpi import mpi_factory
+from .scalapack import scalapack_factory
+from .misc import (
+    BlocksDependency, OpenMPDependency, cups_factory, curses_factory, gpgme_factory,
+    libgcrypt_factory, libwmf_factory, netcdf_factory, pcap_factory, python3_factory,
+    shaderc_factory, threads_factory, ThreadDependency, iconv_factory, intl_factory,
+)
 from .platform import AppleFrameworks
-from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency, VulkanDependency
+from .qt import qt4_factory, qt5_factory, qt6_factory
+from .ui import GnuStepDependency, WxDependency, gl_factory, sdl2_factory, vulkan_factory
 
+__all__ = [
+    'Dependency',
+    'InternalDependency',
+    'ExternalDependency',
+    'SystemDependency',
+    'BuiltinDependency',
+    'NotFoundDependency',
+    'ExternalLibrary',
+    'DependencyException',
+    'DependencyMethods',
 
+    'CMakeDependency',
+    'ConfigToolDependency',
+    'DubDependency',
+    'ExtraFrameworkDependency',
+    'PkgConfigDependency',
+
+    'DependencyFactory',
+
+    'ThreadDependency',
+
+    'find_external_dependency',
+    'get_dep_identifier',
+]
+
+"""Dependency representations and discovery logic.
+
+Meson attempts to largely abstract away dependency discovery information, and
+to encapsulate that logic itself so that the DSL doesn't have too much direct
+information. There are some cases where this is impossible/undesirable, such
+as the `get_variable()` method.
+
+Meson has four primary dependency types:
+  1. pkg-config
+  2. apple frameworks
+  3. CMake
+  4. system
+
+Plus a few more niche ones.
+
+When a user calls `dependency('foo')` Meson creates a list of candidates, and
+tries those candidates in order to find one that matches the criteria
+provided by the user (such as version requirements, or optional components
+that are required.)
+
+Except to work around bugs or handle odd corner cases, pkg-config and CMake
+generally just workâ„¢, though there are exceptions. Most of this package is
+concerned with dependencies that don't (always) provide CMake and/or
+pkg-config files.
+
+For these cases one needs to write a `system` dependency. These dependencies
+descend directly from `ExternalDependency`, in their constructor they
+manually set up the necessary link and compile args (and additional
+dependencies as necessary).
+
+For example, imagine a dependency called Foo, it uses an environment variable
+called `$FOO_ROOT` to point to its install root, which looks like this:
+```txt
+$FOOROOT
+→ include/
+→ lib/
+```
+To use Foo, you need its include directory, and you need to link to
+`lib/libfoo.ext`.
+
+You could write code that looks like:
+
+```python
+class FooSystemDependency(ExternalDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        root = os.environ.get('FOO_ROOT')
+        if root is None:
+            mlog.debug('$FOO_ROOT is unset.')
+            self.is_found = False
+            return
+
+        lib = self.clib_compiler.find_library('foo', environment, [os.path.join(root, 'lib')])
+        if lib is None:
+            mlog.debug('Could not find lib.')
+            self.is_found = False
+            return
+
+        self.compile_args.append(f'-I{os.path.join(root, "include")}')
+        self.link_args.append(lib)
+        self.is_found = True
+```
+
+This code will look for `FOO_ROOT` in the environment, handle `FOO_ROOT` being
+undefined gracefully, then set its `compile_args` and `link_args` gracefully.
+It will also gracefully handle not finding the required lib (hopefully that
+doesn't happen, but it could if, for example, the lib is only static and
+shared linking is requested).
+
+There are a couple of things about this that still aren't ideal. For one, we
+don't want to be reading random environment variables at this point. Those
+should actually be added to `envconfig.Properties` and read in
+`environment.Environment._set_default_properties_from_env` (see how
+`BOOST_ROOT` is handled). We can also handle the `static` keyword. So
+now that becomes:
+
+```python
+class FooSystemDependency(ExternalDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        root = environment.properties[self.for_machine].foo_root
+        if root is None:
+            mlog.debug('foo_root is unset.')
+            self.is_found = False
+            return
+
+        static = Mesonlib.LibType.STATIC if kwargs.get('static', False) else Mesonlib.LibType.SHARED
+        lib = self.clib_compiler.find_library(
+            'foo', environment, [os.path.join(root, 'lib')], libtype=static)
+        if lib is None:
+            mlog.debug('Could not find lib.')
+            self.is_found = False
+            return
+
+        self.compile_args.append(f'-I{os.path.join(root, "include")}')
+        self.link_args.append(lib)
+        self.is_found = True
+```
+
+This is nicer in a couple of ways. First we can properly cross compile as we
+are allowed to set `FOO_ROOT` for both the build and host machines, it also
+means that users can override this in their machine files, and if that
+environment variables changes during a Meson reconfigure Meson won't re-read
+it, this is important for reproducibility. Finally, Meson will figure out
+whether it should be finding `libfoo.so` or `libfoo.a` (or the platform
+specific names). Things are looking pretty good now, so it can be added to
+the `packages` dict below:
+
+```python
+packages.update({
+    'foo': FooSystemDependency,
+})
+```
+
+Now, what if foo also provides pkg-config, but it's only shipped on Unices,
+or only included in very recent versions of the dependency? We can use the
+`DependencyFactory` class:
+
+```python
+foo_factory = DependencyFactory(
+    'foo',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    system_class=FooSystemDependency,
+)
+```
+
+This is a helper function that will generate a default pkg-config based
+dependency, and use the `FooSystemDependency` as well. It can also handle
+custom finders for pkg-config and cmake based dependencies that need some
+extra help. You would then add the `foo_factory` to packages instead of
+`FooSystemDependency`:
+
+```python
+packages.update({
+    'foo': foo_factory,
+})
+```
+
+If you have a dependency that is very complicated, (such as having multiple
+implementations) you may need to write your own factory function. There are a
+number of examples in this package.
+
+_Note_ before we moved to factory functions it was common to use an
+`ExternalDependency` class that would instantiate different types of
+dependencies and hold the one it found. There are a number of drawbacks to
+this approach, and no new dependencies should do this.
+"""
+
+# This is a dict where the keys should be strings, and the values must be one
+# of:
+# - An ExternalDependency subclass
+# - A DependencyFactory object
+# - A callable with a signature of (Environment, MachineChoice, Dict[str, Any]) -> List[Callable[[], ExternalDependency]]
 packages.update({
     # From dev:
-    'gtest': GTestDependency,
-    'gmock': GMockDependency,
-    'llvm': LLVMDependency,
+    'gtest': gtest_factory,
+    'gmock': gmock_factory,
+    'llvm': llvm_factory,
     'valgrind': ValgrindDependency,
+    'zlib': zlib_factory,
+    'jdk': JDKSystemDependency,
 
     'boost': BoostDependency,
     'cuda': CudaDependency,
 
     # per-file
-    'coarray': CoarrayDependency,
-    'hdf5': HDF5Dependency,
-    'mpi': MPIDependency,
-    'scalapack': ScalapackDependency,
+    'coarray': coarray_factory,
+    'hdf5': hdf5_factory,
+    'mpi': mpi_factory,
+    'scalapack': scalapack_factory,
 
     # From misc:
     'blocks': BlocksDependency,
-    'netcdf': NetCDFDependency,
+    'curses': curses_factory,
+    'netcdf': netcdf_factory,
     'openmp': OpenMPDependency,
-    'python3': Python3Dependency,
-    'threads': ThreadDependency,
-    'pcap': PcapDependency,
-    'cups': CupsDependency,
-    'libwmf': LibWmfDependency,
-    'libgcrypt': LibGCryptDependency,
-    'gpgme': GpgmeDependency,
-    'shaderc': ShadercDependency,
+    'python3': python3_factory,
+    'threads': threads_factory,
+    'pcap': pcap_factory,
+    'cups': cups_factory,
+    'libwmf': libwmf_factory,
+    'libgcrypt': libgcrypt_factory,
+    'gpgme': gpgme_factory,
+    'shaderc': shaderc_factory,
+    'iconv': iconv_factory,
+    'intl': intl_factory,
 
     # From platform:
     'appleframeworks': AppleFrameworks,
 
     # From ui:
-    'gl': GLDependency,
+    'gl': gl_factory,
     'gnustep': GnuStepDependency,
-    'qt4': Qt4Dependency,
-    'qt5': Qt5Dependency,
-    'sdl2': SDL2Dependency,
+    'qt4': qt4_factory,
+    'qt5': qt5_factory,
+    'qt6': qt6_factory,
+    'sdl2': sdl2_factory,
     'wxwidgets': WxDependency,
-    'vulkan': VulkanDependency,
+    'vulkan': vulkan_factory,
 })
 _packages_accept_language.update({
     'hdf5',
diff -Nru meson-0.53.2/mesonbuild/dependencies/misc.py meson-0.61.2/mesonbuild/dependencies/misc.py
--- meson-0.53.2/mesonbuild/dependencies/misc.py	2020-01-23 22:29:05.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/misc.py	2021-12-26 16:24:25.000000000 +0000
@@ -18,67 +18,49 @@
 import functools
 import re
 import sysconfig
+import typing as T
 
-from .. import mlog
 from .. import mesonlib
+from .. import mlog
 from ..environment import detect_cpu_family
-from ..mesonlib import listify
-
-from .base import (
-    DependencyException, DependencyMethods, ExternalDependency,
-    ExtraFrameworkDependency, PkgConfigDependency,
-    CMakeDependency, ConfigToolDependency,
-)
-
-
-class NetCDFDependency(ExternalDependency):
-
-    def __init__(self, environment, kwargs):
-        language = kwargs.get('language', 'c')
-        super().__init__('netcdf', environment, language, kwargs)
-        kwargs['required'] = False
-        kwargs['silent'] = True
-        self.is_found = False
-        methods = listify(self.methods)
-
-        if language not in ('c', 'cpp', 'fortran'):
-            raise DependencyException('Language {} is not supported with NetCDF.'.format(language))
+from .base import DependencyException, DependencyMethods
+from .base import BuiltinDependency, SystemDependency
+from .cmake import CMakeDependency
+from .configtool import ConfigToolDependency
+from .factory import DependencyFactory, factory_methods
+from .pkgconfig import PkgConfigDependency
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment, MachineChoice
+    from .factory import DependencyGenerator
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE})
+def netcdf_factory(env: 'Environment',
+                   for_machine: 'MachineChoice',
+                   kwargs: T.Dict[str, T.Any],
+                   methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    language = kwargs.get('language', 'c')
+    if language not in ('c', 'cpp', 'fortran'):
+        raise DependencyException(f'Language {language} is not supported with NetCDF.')
+
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        if language == 'fortran':
+            pkg = 'netcdf-fortran'
+        else:
+            pkg = 'netcdf'
 
-        if set([DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]).intersection(methods):
-            pkgconfig_files = ['netcdf']
+        candidates.append(functools.partial(PkgConfigDependency, pkg, env, kwargs, language=language))
 
-            if language == 'fortran':
-                pkgconfig_files.append('netcdf-fortran')
+    if DependencyMethods.CMAKE in methods:
+        candidates.append(functools.partial(CMakeDependency, 'NetCDF', env, kwargs, language=language))
 
-            self.compile_args = []
-            self.link_args = []
-            self.pcdep = []
-            for pkg in pkgconfig_files:
-                pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language)
-                if pkgdep.found():
-                    self.compile_args.extend(pkgdep.get_compile_args())
-                    self.link_args.extend(pkgdep.get_link_args())
-                    self.version = pkgdep.get_version()
-                    self.is_found = True
-                    self.pcdep.append(pkgdep)
-            if self.is_found:
-                return
+    return candidates
 
-        if set([DependencyMethods.AUTO, DependencyMethods.CMAKE]).intersection(methods):
-            cmakedep = CMakeDependency('NetCDF', environment, kwargs, language=self.language)
-            if cmakedep.found():
-                self.compile_args = cmakedep.get_compile_args()
-                self.link_args = cmakedep.get_link_args()
-                self.version = cmakedep.get_version()
-                self.is_found = True
-                return
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.AUTO, DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE]
-
-
-class OpenMPDependency(ExternalDependency):
+class OpenMPDependency(SystemDependency):
     # Map date of specification release (which is the macro value) to a version.
     VERSIONS = {
         '201811': '5.0',
@@ -92,10 +74,16 @@
         '199810': '1.0',
     }
 
-    def __init__(self, environment, kwargs):
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
         language = kwargs.get('language')
-        super().__init__('openmp', environment, language, kwargs)
+        super().__init__('openmp', environment, kwargs, language=language)
         self.is_found = False
+        if self.clib_compiler.get_id() == 'nagfor':
+            # No macro defined for OpenMP, but OpenMP 3.1 is supported.
+            self.version = '3.1'
+            self.is_found = True
+            self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
+            return
         if self.clib_compiler.get_id() == 'pgi':
             # through at least PGI 19.4, there is no macro defined for OpenMP, but OpenMP 3.1 is supported.
             self.version = '3.1'
@@ -111,55 +99,42 @@
             openmp_date = None
 
         if openmp_date:
-            self.version = self.VERSIONS[openmp_date]
+            try:
+                self.version = self.VERSIONS[openmp_date]
+            except KeyError:
+                mlog.debug(f'Could not find an OpenMP version matching {openmp_date}')
+                if openmp_date == '_OPENMP':
+                    mlog.debug('This can be caused by flags such as gcc\'s `-fdirectives-only`, which affect preprocessor behavior.')
+                return
             # Flang has omp_lib.h
             header_names = ('omp.h', 'omp_lib.h')
             for name in header_names:
                 if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]:
                     self.is_found = True
-                    self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
+                    self.compile_args = self.clib_compiler.openmp_flags()
+                    self.link_args = self.clib_compiler.openmp_link_flags()
                     break
             if not self.is_found:
                 mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.')
 
 
-class ThreadDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('threads', environment, None, kwargs)
-        self.name = 'threads'
-        self.is_found = False
-        methods = listify(self.methods)
-        if DependencyMethods.AUTO in methods:
-            self.is_found = True
-            # Happens if you are using a language with threads
-            # concept without C, such as plain Cuda.
-            if self.clib_compiler is None:
-                self.compile_args = []
-                self.link_args = []
-            else:
-                self.compile_args = self.clib_compiler.thread_flags(environment)
-                self.link_args = self.clib_compiler.thread_link_flags(environment)
-            return
-
-        if DependencyMethods.CMAKE in methods:
-            # for unit tests and for those who simply want
-            # dependency('threads', method: 'cmake')
-            cmakedep = CMakeDependency('Threads', environment, kwargs)
-            if cmakedep.found():
-                self.compile_args = cmakedep.get_compile_args()
-                self.link_args = cmakedep.get_link_args()
-                self.version = cmakedep.get_version()
-                self.is_found = True
-                return
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.AUTO, DependencyMethods.CMAKE]
+class ThreadDependency(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs)
+        self.is_found = True
+        # Happens if you are using a language with threads
+        # concept without C, such as plain Cuda.
+        if self.clib_compiler is None:
+            self.compile_args = []
+            self.link_args = []
+        else:
+            self.compile_args = self.clib_compiler.thread_flags(environment)
+            self.link_args = self.clib_compiler.thread_link_flags(environment)
 
 
-class BlocksDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('blocks', environment, None, kwargs)
+class BlocksDependency(SystemDependency):
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__('blocks', environment, kwargs)
         self.name = 'blocks'
         self.is_found = False
 
@@ -190,12 +165,14 @@
             self.is_found = True
 
 
-class Python3Dependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('python3', environment, None, kwargs)
+class Python3DependencySystem(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs)
 
         if not environment.machines.matches_build_machine(self.for_machine):
             return
+        if not environment.machines[self.for_machine].is_windows():
+            return
 
         self.name = 'python3'
         self.static = kwargs.get('static', False)
@@ -203,30 +180,8 @@
         self.version = '3'
         self._find_libpy3_windows(environment)
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'python3', environment, kwargs))
-
-        if DependencyMethods.SYSCONFIG in methods:
-            candidates.append(functools.partial(Python3Dependency, environment, kwargs))
-
-        if DependencyMethods.EXTRAFRAMEWORK in methods:
-            # In OSX the Python 3 framework does not have a version
-            # number in its name.
-            # There is a python in /System/Library/Frameworks, but that's
-            # python 2, Python 3 will always be in /Library
-            candidates.append(functools.partial(
-                ExtraFrameworkDependency, 'Python', False, ['/Library/Frameworks'],
-                environment, kwargs.get('language', None), kwargs))
-
-        return candidates
-
     @staticmethod
-    def get_windows_python_arch():
+    def get_windows_python_arch() -> T.Optional[str]:
         pyplat = sysconfig.get_platform()
         if pyplat == 'mingw':
             pycc = sysconfig.get_config_var('CC')
@@ -235,28 +190,27 @@
             elif pycc.startswith(('i686', 'i386')):
                 return '32'
             else:
-                mlog.log('MinGW Python built with unknown CC {!r}, please file'
-                         'a bug'.format(pycc))
+                mlog.log(f'MinGW Python built with unknown CC {pycc!r}, please file a bug')
                 return None
         elif pyplat == 'win32':
             return '32'
         elif pyplat in ('win64', 'win-amd64'):
             return '64'
-        mlog.log('Unknown Windows Python platform {!r}'.format(pyplat))
+        mlog.log(f'Unknown Windows Python platform {pyplat!r}')
         return None
 
-    def get_windows_link_args(self):
+    def get_windows_link_args(self) -> T.Optional[T.List[str]]:
         pyplat = sysconfig.get_platform()
         if pyplat.startswith('win'):
             vernum = sysconfig.get_config_var('py_version_nodot')
             if self.static:
-                libpath = Path('libs') / 'libpython{}.a'.format(vernum)
+                libpath = Path('libs') / f'libpython{vernum}.a'
             else:
                 comp = self.get_compiler()
                 if comp.id == "gcc":
-                    libpath = 'python{}.dll'.format(vernum)
+                    libpath = Path(f'python{vernum}.dll')
                 else:
-                    libpath = Path('libs') / 'python{}.lib'.format(vernum)
+                    libpath = Path('libs') / f'python{vernum}.lib'
             lib = Path(sysconfig.get_config_var('base')) / libpath
         elif pyplat == 'mingw':
             if self.static:
@@ -269,7 +223,7 @@
             return None
         return [str(lib)]
 
-    def _find_libpy3_windows(self, env):
+    def _find_libpy3_windows(self, env: 'Environment') -> None:
         '''
         Find python3 libraries on Windows and also verify that the arch matches
         what we are building for.
@@ -285,7 +239,7 @@
             arch = '64'
         else:
             # We can't cross-compile Python 3 dependencies on Windows yet
-            mlog.log('Unknown architecture {!r} for'.format(arch),
+            mlog.log(f'Unknown architecture {arch!r} for',
                      mlog.bold(self.name))
             self.is_found = False
             return
@@ -310,250 +264,354 @@
         self.version = sysconfig.get_config_var('py_version')
         self.is_found = True
 
-    @staticmethod
-    def get_methods():
-        if mesonlib.is_windows():
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSCONFIG]
-        elif mesonlib.is_osx():
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.EXTRAFRAMEWORK]
-        else:
-            return [DependencyMethods.PKGCONFIG]
-
-    def log_tried(self):
+    def log_tried(self) -> str:
         return 'sysconfig'
 
-class PcapDependency(ExternalDependency):
+class PcapDependencyConfigTool(ConfigToolDependency):
 
-    def __init__(self, environment, kwargs):
-        super().__init__('pcap', environment, None, kwargs)
+    tools = ['pcap-config']
+    tool_name = 'pcap-config'
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'pcap', environment, kwargs))
-
-        if DependencyMethods.CONFIG_TOOL in methods:
-            candidates.append(functools.partial(ConfigToolDependency.factory,
-                                                'pcap', environment, None,
-                                                kwargs, ['pcap-config'],
-                                                'pcap-config',
-                                                PcapDependency.tool_finish_init))
-
-        return candidates
-
-    @staticmethod
-    def tool_finish_init(ctdep):
-        ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
-        ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
-        ctdep.version = PcapDependency.get_pcap_lib_version(ctdep)
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+        self.version = self.get_pcap_lib_version()
 
-    @staticmethod
-    def get_pcap_lib_version(ctdep):
+    def get_pcap_lib_version(self) -> T.Optional[str]:
         # Since we seem to need to run a program to discover the pcap version,
         # we can't do that when cross-compiling
-        if not ctdep.env.machines.matches_build_machine(ctdep.for_machine):
+        # FIXME: this should be handled if we have an exe_wrapper
+        if not self.env.machines.matches_build_machine(self.for_machine):
             return None
 
-        v = ctdep.clib_compiler.get_return_value('pcap_lib_version', 'string',
-                                                 '#include ', ctdep.env, [], [ctdep])
-        v = re.sub(r'libpcap version ', '', v)
+        v = self.clib_compiler.get_return_value('pcap_lib_version', 'string',
+                                                '#include ', self.env, [], [self])
+        v = re.sub(r'libpcap version ', '', str(v))
         v = re.sub(r' -- Apple version.*$', '', v)
         return v
 
 
-class CupsDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('cups', environment, None, kwargs)
-
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
+class CupsDependencyConfigTool(ConfigToolDependency):
 
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'cups', environment, kwargs))
+    tools = ['cups-config']
+    tool_name = 'cups-config'
 
-        if DependencyMethods.CONFIG_TOOL in methods:
-            candidates.append(functools.partial(ConfigToolDependency.factory,
-                                                'cups', environment, None,
-                                                kwargs, ['cups-config'],
-                                                'cups-config', CupsDependency.tool_finish_init))
-
-        if DependencyMethods.EXTRAFRAMEWORK in methods:
-            if mesonlib.is_osx():
-                candidates.append(functools.partial(
-                    ExtraFrameworkDependency, 'cups', False, None, environment,
-                    kwargs.get('language', None), kwargs))
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--ldflags', '--libs'], 'link_args')
 
-        if DependencyMethods.CMAKE in methods:
-            candidates.append(functools.partial(CMakeDependency, 'Cups', environment, kwargs))
 
-        return candidates
+class LibWmfDependencyConfigTool(ConfigToolDependency):
 
-    @staticmethod
-    def tool_finish_init(ctdep):
-        ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
-        ctdep.link_args = ctdep.get_config_value(['--ldflags', '--libs'], 'link_args')
+    tools = ['libwmf-config']
+    tool_name = 'libwmf-config'
 
-    @staticmethod
-    def get_methods():
-        if mesonlib.is_osx():
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK, DependencyMethods.CMAKE]
-        else:
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.CMAKE]
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
 
 
-class LibWmfDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('libwmf', environment, None, kwargs)
+class LibGCryptDependencyConfigTool(ConfigToolDependency):
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
+    tools = ['libgcrypt-config']
+    tool_name = 'libgcrypt-config'
 
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'libwmf', environment, kwargs))
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+        self.version = self.get_config_value(['--version'], 'version')[0]
 
-        if DependencyMethods.CONFIG_TOOL in methods:
-            candidates.append(functools.partial(ConfigToolDependency.factory,
-                                                'libwmf', environment, None, kwargs, ['libwmf-config'], 'libwmf-config', LibWmfDependency.tool_finish_init))
 
-        return candidates
+class GpgmeDependencyConfigTool(ConfigToolDependency):
 
-    @staticmethod
-    def tool_finish_init(ctdep):
-        ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
-        ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
+    tools = ['gpgme-config']
+    tool_name = 'gpg-config'
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+        self.version = self.get_config_value(['--version'], 'version')[0]
 
 
-class LibGCryptDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('libgcrypt', environment, None, kwargs)
+class ShadercDependency(SystemDependency):
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__('shaderc', environment, kwargs)
 
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'libgcrypt', environment, kwargs))
+        static_lib = 'shaderc_combined'
+        shared_lib = 'shaderc_shared'
 
-        if DependencyMethods.CONFIG_TOOL in methods:
-            candidates.append(functools.partial(ConfigToolDependency.factory,
-                                                'libgcrypt', environment, None, kwargs, ['libgcrypt-config'],
-                                                'libgcrypt-config',
-                                                LibGCryptDependency.tool_finish_init))
+        libs = [shared_lib, static_lib]
+        if self.static:
+            libs.reverse()
 
-        return candidates
+        cc = self.get_compiler()
 
-    @staticmethod
-    def tool_finish_init(ctdep):
-        ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
-        ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
-        ctdep.version = ctdep.get_config_value(['--version'], 'version')[0]
+        for lib in libs:
+            self.link_args = cc.find_library(lib, environment, [])
+            if self.link_args is not None:
+                self.is_found = True
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
+                if self.static and lib != static_lib:
+                    mlog.warning(f'Static library {static_lib!r} not found for dependency '
+                                 f'{self.name!r}, may not be statically linked')
 
+                break
 
-class GpgmeDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('gpgme', environment, None, kwargs)
+    def log_tried(self) -> str:
+        return 'system'
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
 
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'gpgme', environment, kwargs))
+class CursesConfigToolDependency(ConfigToolDependency):
 
-        if DependencyMethods.CONFIG_TOOL in methods:
-            candidates.append(functools.partial(ConfigToolDependency.factory,
-                                                'gpgme', environment, None, kwargs, ['gpgme-config'],
-                                                'gpgme-config',
-                                                GpgmeDependency.tool_finish_init))
+    """Use the curses config tools."""
 
-        return candidates
+    tool = 'curses-config'
+    # ncurses5.4-config is for macOS Catalina
+    tools = ['ncursesw6-config', 'ncursesw5-config', 'ncurses6-config', 'ncurses5-config', 'ncurses5.4-config']
 
-    @staticmethod
-    def tool_finish_init(ctdep):
-        ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
-        ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
-        ctdep.version = ctdep.get_config_value(['--version'], 'version')[0]
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
 
+class CursesSystemDependency(SystemDependency):
 
-class ShadercDependency(ExternalDependency):
+    """Curses dependency the hard way.
 
-    def __init__(self, environment, kwargs):
-        super().__init__('shaderc', environment, None, kwargs)
+    This replaces hand rolled find_library() and has_header() calls. We
+    provide this for portability reasons, there are a large number of curses
+    implementations, and the differences between them can be very annoying.
+    """
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+
+        candidates = [
+            ('pdcurses', ['pdcurses/curses.h']),
+            ('ncursesw',  ['ncursesw/ncurses.h', 'ncurses.h']),
+            ('ncurses',  ['ncurses/ncurses.h', 'ncurses/curses.h', 'ncurses.h']),
+            ('curses',  ['curses.h']),
+        ]
+
+        # Not sure how else to elegently break out of both loops
+        for lib, headers in candidates:
+            l = self.clib_compiler.find_library(lib, env, [])
+            if l:
+                for header in headers:
+                    h = self.clib_compiler.has_header(header, '', env)
+                    if h[0]:
+                        self.is_found = True
+                        self.link_args = l
+                        # Not sure how to find version for non-ncurses curses
+                        # implementations. The one in illumos/OpenIndiana
+                        # doesn't seem to have a version defined in the header.
+                        if lib.startswith('ncurses'):
+                            v, _ = self.clib_compiler.get_define('NCURSES_VERSION', f'#include <{header}>', env, [], [self])
+                            self.version = v.strip('"')
+                        if lib.startswith('pdcurses'):
+                            v_major, _ = self.clib_compiler.get_define('PDC_VER_MAJOR', f'#include <{header}>', env, [], [self])
+                            v_minor, _ = self.clib_compiler.get_define('PDC_VER_MINOR', f'#include <{header}>', env, [], [self])
+                            self.version = f'{v_major}.{v_minor}'
+
+                        # Check the version if possible, emit a warning if we can't
+                        req = kwargs.get('version')
+                        if req:
+                            if self.version:
+                                self.is_found = mesonlib.version_compare(self.version, req)
+                            else:
+                                mlog.warning('Cannot determine version of curses to compare against.')
+
+                        if self.is_found:
+                            mlog.debug('Curses library:', l)
+                            mlog.debug('Curses header:', header)
+                            break
+            if self.is_found:
+                break
 
-        static_lib = 'shaderc_combined'
-        shared_lib = 'shaderc_shared'
 
-        libs = [shared_lib, static_lib]
-        if self.static:
-            libs.reverse()
+class IconvBuiltinDependency(BuiltinDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+        code = '''#include \n\nint main() {\n    iconv_open("","");\n}''' # [ignore encoding] this is C, not python, Mr. Lint
 
-        cc = self.get_compiler()
+        if self.clib_compiler.links(code, env)[0]:
+            self.is_found = True
 
-        for lib in libs:
-            self.link_args = cc.find_library(lib, environment, [])
-            if self.link_args is not None:
-                self.is_found = True
 
-                if self.static and lib != static_lib:
-                    mlog.warning('Static library {!r} not found for dependency {!r}, may '
-                                 'not be statically linked'.format(static_lib, self.name))
+class IconvSystemDependency(SystemDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
 
-                break
+        h = self.clib_compiler.has_header('iconv.h', '', env)
+        self.link_args = self.clib_compiler.find_library('iconv', env, [], self.libtype)
 
-    def log_tried(self):
-        return 'system'
+        if h[0] and self.link_args:
+            self.is_found = True
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.PKGCONFIG in methods:
-            # ShaderC packages their shared and static libs together
-            # and provides different pkg-config files for each one. We
-            # smooth over this difference by handling the static
-            # keyword before handing off to the pkg-config handler.
-            shared_libs = ['shaderc']
-            static_libs = ['shaderc_combined', 'shaderc_static']
-
-            if kwargs.get('static', False):
-                c = [functools.partial(PkgConfigDependency, name, environment, kwargs)
-                     for name in static_libs + shared_libs]
-            else:
-                c = [functools.partial(PkgConfigDependency, name, environment, kwargs)
-                     for name in shared_libs + static_libs]
-            candidates.extend(c)
+
+class IntlBuiltinDependency(BuiltinDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+
+        if self.clib_compiler.has_function('ngettext', '', env)[0]:
+            self.is_found = True
+
+
+class IntlSystemDependency(SystemDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+
+        h = self.clib_compiler.has_header('libintl.h', '', env)
+        self.link_args = self.clib_compiler.find_library('intl', env, [], self.libtype)
+
+        if h[0] and self.link_args:
+            self.is_found = True
+
+            if self.static:
+                if not self._add_sub_dependency(iconv_factory(env, self.for_machine, {'static': True})):
+                    self.is_found = False
+                    return
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM})
+def curses_factory(env: 'Environment',
+                   for_machine: 'MachineChoice',
+                   kwargs: T.Dict[str, T.Any],
+                   methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        pkgconfig_files = ['pdcurses', 'ncursesw', 'ncurses', 'curses']
+        for pkg in pkgconfig_files:
+            candidates.append(functools.partial(PkgConfigDependency, pkg, env, kwargs))
+
+    # There are path handling problems with these methods on msys, and they
+    # don't apply to windows otherwise (cygwin is handled separately from
+    # windows)
+    if not env.machines[for_machine].is_windows():
+        if DependencyMethods.CONFIG_TOOL in methods:
+            candidates.append(functools.partial(CursesConfigToolDependency, 'curses', env, kwargs))
 
         if DependencyMethods.SYSTEM in methods:
-            candidates.append(functools.partial(ShadercDependency, environment, kwargs))
+            candidates.append(functools.partial(CursesSystemDependency, 'curses', env, kwargs))
 
-        return candidates
+    return candidates
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.SYSTEM, DependencyMethods.PKGCONFIG]
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM})
+def shaderc_factory(env: 'Environment',
+                    for_machine: 'MachineChoice',
+                    kwargs: T.Dict[str, T.Any],
+                    methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    """Custom DependencyFactory for ShaderC.
+
+    ShaderC's odd you get three different libraries from the same build
+    thing are just easier to represent as a separate function than
+    twisting DependencyFactory even more.
+    """
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        # ShaderC packages their shared and static libs together
+        # and provides different pkg-config files for each one. We
+        # smooth over this difference by handling the static
+        # keyword before handing off to the pkg-config handler.
+        shared_libs = ['shaderc']
+        static_libs = ['shaderc_combined', 'shaderc_static']
+
+        if kwargs.get('static', False):
+            c = [functools.partial(PkgConfigDependency, name, env, kwargs)
+                 for name in static_libs + shared_libs]
+        else:
+            c = [functools.partial(PkgConfigDependency, name, env, kwargs)
+                 for name in shared_libs + static_libs]
+        candidates.extend(c)
+
+    if DependencyMethods.SYSTEM in methods:
+        candidates.append(functools.partial(ShadercDependency, env, kwargs))
+
+    return candidates
+
+
+cups_factory = DependencyFactory(
+    'cups',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK, DependencyMethods.CMAKE],
+    configtool_class=CupsDependencyConfigTool,
+    cmake_name='Cups',
+)
+
+gpgme_factory = DependencyFactory(
+    'gpgme',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    configtool_class=GpgmeDependencyConfigTool,
+)
+
+libgcrypt_factory = DependencyFactory(
+    'libgcrypt',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    configtool_class=LibGCryptDependencyConfigTool,
+)
+
+libwmf_factory = DependencyFactory(
+    'libwmf',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    configtool_class=LibWmfDependencyConfigTool,
+)
+
+pcap_factory = DependencyFactory(
+    'pcap',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    configtool_class=PcapDependencyConfigTool,
+    pkgconfig_name='libpcap',
+)
+
+python3_factory = DependencyFactory(
+    'python3',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.EXTRAFRAMEWORK],
+    system_class=Python3DependencySystem,
+    # There is no version number in the macOS version number
+    framework_name='Python',
+    # There is a python in /System/Library/Frameworks, but that's python 2.x,
+    # Python 3 will always be in /Library
+    extra_kwargs={'paths': ['/Library/Frameworks']},
+)
+
+threads_factory = DependencyFactory(
+    'threads',
+    [DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
+    cmake_name='Threads',
+    system_class=ThreadDependency,
+)
+
+iconv_factory = DependencyFactory(
+    'iconv',
+    [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
+    builtin_class=IconvBuiltinDependency,
+    system_class=IconvSystemDependency,
+)
+
+intl_factory = DependencyFactory(
+    'intl',
+    [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
+    builtin_class=IntlBuiltinDependency,
+    system_class=IntlSystemDependency,
+)
diff -Nru meson-0.53.2/mesonbuild/dependencies/mpi.py meson-0.61.2/mesonbuild/dependencies/mpi.py
--- meson-0.53.2/mesonbuild/dependencies/mpi.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/mpi.py	2021-08-18 11:22:15.000000000 +0000
@@ -12,111 +12,95 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import functools
 import typing as T
 import os
 import re
-import subprocess
 
-from .. import mlog
-from .. import mesonlib
-from ..mesonlib import split_args, listify
 from ..environment import detect_cpu_family
-from .base import (DependencyException, DependencyMethods, ExternalDependency, ExternalProgram,
-                   PkgConfigDependency)
-
-
-class MPIDependency(ExternalDependency):
-
-    def __init__(self, environment, kwargs: dict):
-        language = kwargs.get('language', 'c')
-        super().__init__('mpi', environment, language, kwargs)
-        kwargs['required'] = False
-        kwargs['silent'] = True
-        self.is_found = False
-        methods = listify(self.methods)
-
-        env_vars = []
-        default_wrappers = []
-        pkgconfig_files = []
+from .base import DependencyMethods, detect_compiler, SystemDependency
+from .configtool import ConfigToolDependency
+from .factory import factory_methods
+from .pkgconfig import PkgConfigDependency
+
+if T.TYPE_CHECKING:
+    from .factory import DependencyGenerator
+    from ..environment import Environment, MachineChoice
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM})
+def mpi_factory(env: 'Environment',
+                for_machine: 'MachineChoice',
+                kwargs: T.Dict[str, T.Any],
+                methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    language = kwargs.get('language', 'c')
+    if language not in {'c', 'cpp', 'fortran'}:
+        # OpenMPI doesn't work without any other languages
+        return []
+
+    candidates: T.List['DependencyGenerator'] = []
+    compiler = detect_compiler('mpi', env, for_machine, language)
+    if compiler is None:
+        return []
+    compiler_is_intel = compiler.get_id() in {'intel', 'intel-cl'}
+
+    # Only OpenMPI has pkg-config, and it doesn't work with the intel compilers
+    if DependencyMethods.PKGCONFIG in methods and not compiler_is_intel:
+        pkg_name = None
         if language == 'c':
-            cid = environment.detect_c_compiler(self.for_machine).get_id()
-            if cid in ('intel', 'intel-cl'):
-                env_vars.append('I_MPI_CC')
-                # IntelMPI doesn't have .pc files
-                default_wrappers.append('mpiicc')
-            else:
-                env_vars.append('MPICC')
-                pkgconfig_files.append('ompi-c')
-            default_wrappers.append('mpicc')
+            pkg_name = 'ompi-c'
         elif language == 'cpp':
-            cid = environment.detect_cpp_compiler(self.for_machine).get_id()
-            if cid in ('intel', 'intel-cl'):
-                env_vars.append('I_MPI_CXX')
-                # IntelMPI doesn't have .pc files
-                default_wrappers.append('mpiicpc')
-            else:
-                env_vars.append('MPICXX')
-                pkgconfig_files.append('ompi-cxx')
-                default_wrappers += ['mpic++', 'mpicxx', 'mpiCC']  # these are not for intelmpi
+            pkg_name = 'ompi-cxx'
         elif language == 'fortran':
-            cid = environment.detect_fortran_compiler(self.for_machine).get_id()
-            if cid in ('intel', 'intel-cl'):
-                env_vars.append('I_MPI_F90')
-                # IntelMPI doesn't have .pc files
-                default_wrappers.append('mpiifort')
-            else:
-                env_vars += ['MPIFC', 'MPIF90', 'MPIF77']
-                pkgconfig_files.append('ompi-fort')
-            default_wrappers += ['mpifort', 'mpif90', 'mpif77']
-        else:
-            raise DependencyException('Language {} is not supported with MPI.'.format(language))
+            pkg_name = 'ompi-fort'
+        candidates.append(functools.partial(
+            PkgConfigDependency, pkg_name, env, kwargs, language=language))
+
+    if DependencyMethods.CONFIG_TOOL in methods:
+        nwargs = kwargs.copy()
+
+        if compiler_is_intel:
+            if env.machines[for_machine].is_windows():
+                nwargs['version_arg'] = '-v'
+                nwargs['returncode_value'] = 3
+
+            if language == 'c':
+                tool_names = [os.environ.get('I_MPI_CC'), 'mpiicc']
+            elif language == 'cpp':
+                tool_names = [os.environ.get('I_MPI_CXX'), 'mpiicpc']
+            elif language == 'fortran':
+                tool_names = [os.environ.get('I_MPI_F90'), 'mpiifort']
+
+            cls = IntelMPIConfigToolDependency  # type: T.Type[ConfigToolDependency]
+        else: # OpenMPI, which doesn't work with intel
+            #
+            # We try the environment variables for the tools first, but then
+            # fall back to the hardcoded names
+            if language == 'c':
+                tool_names = [os.environ.get('MPICC'), 'mpicc']
+            elif language == 'cpp':
+                tool_names = [os.environ.get('MPICXX'), 'mpic++', 'mpicxx', 'mpiCC']
+            elif language == 'fortran':
+                tool_names = [os.environ.get(e) for e in ['MPIFC', 'MPIF90', 'MPIF77']]
+                tool_names.extend(['mpifort', 'mpif90', 'mpif77'])
+
+            cls = OpenMPIConfigToolDependency
+
+        tool_names = [t for t in tool_names if t]  # remove empty environment variables
+        assert tool_names
+
+        nwargs['tools'] = tool_names
+        candidates.append(functools.partial(
+            cls, tool_names[0], env, nwargs, language=language))
+
+    if DependencyMethods.SYSTEM in methods:
+        candidates.append(functools.partial(
+            MSMPIDependency, 'msmpi', env, kwargs, language=language))
 
-        if set([DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]).intersection(methods):
-            for pkg in pkgconfig_files:
-                pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language)
-                if pkgdep.found():
-                    self.compile_args = pkgdep.get_compile_args()
-                    self.link_args = pkgdep.get_link_args()
-                    self.version = pkgdep.get_version()
-                    self.is_found = True
-                    self.pcdep = pkgdep
-                    return
-
-        if DependencyMethods.AUTO in methods:
-            for var in env_vars:
-                if var in os.environ:
-                    wrappers = [os.environ[var]]
-                    break
-            else:
-                # Or search for default wrappers.
-                wrappers = default_wrappers
-
-            for prog in wrappers:
-                # Note: Some use OpenMPI with Intel compilers on Linux
-                result = self._try_openmpi_wrapper(prog, cid)
-                if result is not None:
-                    self.is_found = True
-                    self.version = result[0]
-                    self.compile_args = self._filter_compile_args(result[1])
-                    self.link_args = self._filter_link_args(result[2], cid)
-                    break
-                result = self._try_other_wrapper(prog, cid)
-                if result is not None:
-                    self.is_found = True
-                    self.version = result[0]
-                    self.compile_args = self._filter_compile_args(result[1])
-                    self.link_args = self._filter_link_args(result[2], cid)
-                    break
-
-            if not self.is_found and mesonlib.is_windows():
-                # only Intel Fortran compiler is compatible with Microsoft MPI at this time.
-                if language == 'fortran' and cid != 'intel-cl':
-                    return
-                result = self._try_msmpi()
-                if result is not None:
-                    self.is_found = True
-                    self.version, self.compile_args, self.link_args = result
-            return
+    return candidates
+
+
+class _MPIConfigToolDependency(ConfigToolDependency):
 
     def _filter_compile_args(self, args: T.Sequence[str]) -> T.List[str]:
         """
@@ -124,7 +108,7 @@
         Drop -O2 and everything that is not needed.
         """
         result = []
-        multi_args = ('-I', )
+        multi_args: T.Tuple[str, ...] = ('-I', )
         if self.language == 'fortran':
             fc = self.env.coredata.compilers[self.for_machine]['fortran']
             multi_args += fc.get_module_incdir_args()
@@ -142,7 +126,7 @@
                 result.append(f)
         return result
 
-    def _filter_link_args(self, args: T.Sequence[str], cid: str) -> T.List[str]:
+    def _filter_link_args(self, args: T.Sequence[str]) -> T.List[str]:
         """
         MPI wrappers return a bunch of garbage args.
         Drop -O2 and everything that is not needed.
@@ -150,7 +134,7 @@
         result = []
         include_next = False
         for f in args:
-            if self._is_link_arg(f, cid):
+            if self._is_link_arg(f):
                 result.append(f)
                 if f in ('-L', '-Xlinker'):
                     include_next = True
@@ -159,121 +143,94 @@
                 result.append(f)
         return result
 
-    @staticmethod
-    def _is_link_arg(f: str, cid: str) -> bool:
-        if cid == 'intel-cl':
+    def _is_link_arg(self, f: str) -> bool:
+        if self.clib_compiler.id == 'intel-cl':
             return f == '/link' or f.startswith('/LIBPATH') or f.endswith('.lib')   # always .lib whether static or dynamic
         else:
             return (f.startswith(('-L', '-l', '-Xlinker')) or
                     f == '-pthread' or
                     (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')))
 
-    def _try_openmpi_wrapper(self, prog, cid: str):
-        # https://www.open-mpi.org/doc/v4.0/man1/mpifort.1.php
-        if cid == 'intel-cl':  # IntelCl doesn't support OpenMPI
-            return None
-        prog = ExternalProgram(prog, silent=True)
-        if not prog.found():
-            return None
-
-        # compiler args
-        cmd = prog.get_command() + ['--showme:compile']
-        p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
-        if p.returncode != 0:
-            mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
-            mlog.debug(mlog.bold('Standard output\n'), p.stdout)
-            mlog.debug(mlog.bold('Standard error\n'), p.stderr)
-            return None
-        cargs = split_args(p.stdout)
-        # link args
-        cmd = prog.get_command() + ['--showme:link']
-        p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
-        if p.returncode != 0:
-            mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
-            mlog.debug(mlog.bold('Standard output\n'), p.stdout)
-            mlog.debug(mlog.bold('Standard error\n'), p.stderr)
-            return None
-        libs = split_args(p.stdout)
-        # version
-        cmd = prog.get_command() + ['--showme:version']
-        p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
-        if p.returncode != 0:
-            mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
-            mlog.debug(mlog.bold('Standard output\n'), p.stdout)
-            mlog.debug(mlog.bold('Standard error\n'), p.stderr)
-            return None
-        v = re.search(r'\d+.\d+.\d+', p.stdout)
+
+class IntelMPIConfigToolDependency(_MPIConfigToolDependency):
+
+    """Wrapper around Intel's mpiicc and friends."""
+
+    version_arg = '-v'  # --version is not the same as -v
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language=language)
+        if not self.is_found:
+            return
+
+        args = self.get_config_value(['-show'], 'link and compile args')
+        self.compile_args = self._filter_compile_args(args)
+        self.link_args = self._filter_link_args(args)
+
+    def _sanitize_version(self, out: str) -> str:
+        v = re.search(r'(\d{4}) Update (\d)', out)
         if v:
-            version = v.group(0)
-        else:
-            version = None
+            return '{}.{}'.format(v.group(1), v.group(2))
+        return out
 
-        return version, cargs, libs
 
-    def _try_other_wrapper(self, prog, cid: str) -> T.Tuple[str, T.List[str], T.List[str]]:
-        prog = ExternalProgram(prog, silent=True)
-        if not prog.found():
-            return None
-
-        cmd = prog.get_command()
-        if cid == 'intel-cl':
-            cmd.append('/show')
-        else:
-            cmd.append('-show')
-        p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
-        if p.returncode != 0:
-            mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
-            mlog.debug(mlog.bold('Standard output\n'), p.stdout)
-            mlog.debug(mlog.bold('Standard error\n'), p.stderr)
-            return None
-
-        version = None
-        stdout = p.stdout
-        if 'Intel(R) MPI Library' in p.stdout:  # intel-cl: remove messy compiler logo
-            out = stdout.split('\n', 2)
-            version = out[0]
-            stdout = out[2]
-
-        if version is None:
-            p = subprocess.run(cmd + ['-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, timeout=15)
-            if p.returncode == 0:
-                version = p.stdout.split('\n', 1)[0]
-
-        args = split_args(stdout)
-
-        return version, args, args
-
-    def _try_msmpi(self) -> T.Tuple[str, T.List[str], T.List[str]]:
-        if self.language == 'cpp':
-            # MS-MPI does not support the C++ version of MPI, only the standard C API.
-            return None
-        if 'MSMPI_INC' not in os.environ:
-            return None
+class OpenMPIConfigToolDependency(_MPIConfigToolDependency):
+
+    """Wrapper around OpenMPI mpicc and friends."""
 
-        incdir = os.environ['MSMPI_INC']
+    version_arg = '--showme:version'
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language=language)
+        if not self.is_found:
+            return
+
+        c_args = self.get_config_value(['--showme:compile'], 'compile_args')
+        self.compile_args = self._filter_compile_args(c_args)
+
+        l_args = self.get_config_value(['--showme:link'], 'link_args')
+        self.link_args = self._filter_link_args(l_args)
+
+    def _sanitize_version(self, out: str) -> str:
+        v = re.search(r'\d+.\d+.\d+', out)
+        if v:
+            return v.group(0)
+        return out
+
+
+class MSMPIDependency(SystemDependency):
+
+    """The Microsoft MPI."""
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language=language)
+        # MSMPI only supports the C API
+        if language not in {'c', 'fortran', None}:
+            self.is_found = False
+            return
+        # MSMPI is only for windows, obviously
+        if not self.env.machines[self.for_machine].is_windows():
+            return
+
+        incdir = os.environ.get('MSMPI_INC')
         arch = detect_cpu_family(self.env.coredata.compilers.host)
+        libdir = None
         if arch == 'x86':
-            if 'MSMPI_LIB32' not in os.environ:
-                return None
-            libdir = os.environ['MSMPI_LIB32']
+            libdir = os.environ.get('MSMPI_LIB32')
             post = 'x86'
         elif arch == 'x86_64':
-            if 'MSMPI_LIB64' not in os.environ:
-                return None
-            libdir = os.environ['MSMPI_LIB64']
+            libdir = os.environ.get('MSMPI_LIB64')
             post = 'x64'
-        else:
-            return None
 
+        if libdir is None or incdir is None:
+            self.is_found = False
+            return
+
+        self.is_found = True
+        self.link_args = ['-l' + os.path.join(libdir, 'msmpi')]
+        self.compile_args = ['-I' + incdir, '-I' + os.path.join(incdir, post)]
         if self.language == 'fortran':
-            return (None,
-                    ['-I' + incdir, '-I' + os.path.join(incdir, post)],
-                    [os.path.join(libdir, 'msmpi.lib'), os.path.join(libdir, 'msmpifec.lib')])
-        else:
-            return (None,
-                    ['-I' + incdir, '-I' + os.path.join(incdir, post)],
-                    [os.path.join(libdir, 'msmpi.lib')])
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]
+            self.link_args.append('-l' + os.path.join(libdir, 'msmpifec'))
diff -Nru meson-0.53.2/mesonbuild/dependencies/pkgconfig.py meson-0.61.2/mesonbuild/dependencies/pkgconfig.py
--- meson-0.53.2/mesonbuild/dependencies/pkgconfig.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/pkgconfig.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,497 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .base import ExternalDependency, DependencyException, sort_libpaths, DependencyTypeName
+from ..mesonlib import MachineChoice, OptionKey, OrderedSet, PerMachine, Popen_safe
+from ..programs import find_external_program, ExternalProgram
+from .. import mlog
+from pathlib import PurePath
+import re
+import os
+import shlex
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+class PkgConfigDependency(ExternalDependency):
+    # The class's copy of the pkg-config path. Avoids having to search for it
+    # multiple times in the same Meson invocation.
+    class_pkgbin: PerMachine[T.Union[None, bool, ExternalProgram]] = PerMachine(None, None)
+    # We cache all pkg-config subprocess invocations to avoid redundant calls
+    pkgbin_cache: T.Dict[
+        T.Tuple[ExternalProgram, T.Tuple[str, ...], T.FrozenSet[T.Tuple[str, str]]],
+        T.Tuple[int, str, str]
+    ] = {}
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        super().__init__(DependencyTypeName('pkgconfig'), environment, kwargs, language=language)
+        self.name = name
+        self.is_libtool = False
+        # Store a copy of the pkg-config path on the object itself so it is
+        # stored in the pickled coredata and recovered.
+        self.pkgbin: T.Union[None, bool, ExternalProgram] = None
+
+        # Only search for pkg-config for each machine the first time and store
+        # the result in the class definition
+        if PkgConfigDependency.class_pkgbin[self.for_machine] is False:
+            mlog.debug(f'Pkg-config binary for {self.for_machine} is cached as not found.')
+        elif PkgConfigDependency.class_pkgbin[self.for_machine] is not None:
+            mlog.debug(f'Pkg-config binary for {self.for_machine} is cached.')
+        else:
+            assert PkgConfigDependency.class_pkgbin[self.for_machine] is None
+            mlog.debug(f'Pkg-config binary for {self.for_machine} is not cached.')
+            for potential_pkgbin in find_external_program(
+                    self.env, self.for_machine, 'pkgconfig', 'Pkg-config',
+                    environment.default_pkgconfig, allow_default_for_cross=False):
+                version_if_ok = self.check_pkgconfig(potential_pkgbin)
+                if not version_if_ok:
+                    continue
+                if not self.silent:
+                    mlog.log('Found pkg-config:', mlog.bold(potential_pkgbin.get_path()),
+                             f'({version_if_ok})')
+                PkgConfigDependency.class_pkgbin[self.for_machine] = potential_pkgbin
+                break
+            else:
+                if not self.silent:
+                    mlog.log('Found Pkg-config:', mlog.red('NO'))
+                # Set to False instead of None to signify that we've already
+                # searched for it and not found it
+                PkgConfigDependency.class_pkgbin[self.for_machine] = False
+
+        self.pkgbin = PkgConfigDependency.class_pkgbin[self.for_machine]
+        if self.pkgbin is False:
+            self.pkgbin = None
+            msg = f'Pkg-config binary for machine {self.for_machine} not found. Giving up.'
+            if self.required:
+                raise DependencyException(msg)
+            else:
+                mlog.debug(msg)
+                return
+
+        assert isinstance(self.pkgbin, ExternalProgram)
+        mlog.debug('Determining dependency {!r} with pkg-config executable '
+                   '{!r}'.format(name, self.pkgbin.get_path()))
+        ret, self.version, _ = self._call_pkgbin(['--modversion', name])
+        if ret != 0:
+            return
+
+        self.is_found = True
+
+        try:
+            # Fetch cargs to be used while using this dependency
+            self._set_cargs()
+            # Fetch the libraries and library paths needed for using this
+            self._set_libs()
+        except DependencyException as e:
+            mlog.debug(f"pkg-config error with '{name}': {e}")
+            if self.required:
+                raise
+            else:
+                self.compile_args = []
+                self.link_args = []
+                self.is_found = False
+                self.reason = e
+
+    def __repr__(self) -> str:
+        s = '<{0} {1}: {2} {3}>'
+        return s.format(self.__class__.__name__, self.name, self.is_found,
+                        self.version_reqs)
+
+    def _call_pkgbin_real(self, args: T.List[str], env: T.Dict[str, str]) -> T.Tuple[int, str, str]:
+        assert isinstance(self.pkgbin, ExternalProgram)
+        cmd = self.pkgbin.get_command() + args
+        p, out, err = Popen_safe(cmd, env=env)
+        rc, out, err = p.returncode, out.strip(), err.strip()
+        call = ' '.join(cmd)
+        mlog.debug(f"Called `{call}` -> {rc}\n{out}")
+        return rc, out, err
+
+    @staticmethod
+    def setup_env(env: T.MutableMapping[str, str], environment: 'Environment', for_machine: MachineChoice,
+                  extra_path: T.Optional[str] = None) -> None:
+        extra_paths: T.List[str] = environment.coredata.options[OptionKey('pkg_config_path', machine=for_machine)].value[:]
+        if extra_path and extra_path not in extra_paths:
+            extra_paths.append(extra_path)
+        sysroot = environment.properties[for_machine].get_sys_root()
+        if sysroot:
+            env['PKG_CONFIG_SYSROOT_DIR'] = sysroot
+        new_pkg_config_path = ':'.join([p for p in extra_paths])
+        env['PKG_CONFIG_PATH'] = new_pkg_config_path
+
+        pkg_config_libdir_prop = environment.properties[for_machine].get_pkg_config_libdir()
+        if pkg_config_libdir_prop:
+            new_pkg_config_libdir = ':'.join([p for p in pkg_config_libdir_prop])
+            env['PKG_CONFIG_LIBDIR'] = new_pkg_config_libdir
+        # Dump all PKG_CONFIG environment variables
+        for key, value in env.items():
+            if key.startswith('PKG_'):
+                mlog.debug(f'env[{key}]: {value}')
+
+    def _call_pkgbin(self, args: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str, str]:
+        # Always copy the environment since we're going to modify it
+        # with pkg-config variables
+        if env is None:
+            env = os.environ.copy()
+        else:
+            env = env.copy()
+
+        assert isinstance(self.pkgbin, ExternalProgram)
+        PkgConfigDependency.setup_env(env, self.env, self.for_machine)
+
+        fenv = frozenset(env.items())
+        targs = tuple(args)
+        cache = PkgConfigDependency.pkgbin_cache
+        if (self.pkgbin, targs, fenv) not in cache:
+            cache[(self.pkgbin, targs, fenv)] = self._call_pkgbin_real(args, env)
+        return cache[(self.pkgbin, targs, fenv)]
+
+    def _convert_mingw_paths(self, args: T.List[str]) -> T.List[str]:
+        '''
+        Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo
+        paths so convert them to C:/foo. We cannot resolve other paths starting
+        with / like /home/foo so leave them as-is so that the user gets an
+        error/warning from the compiler/linker.
+        '''
+        if not self.env.machines.build.is_windows():
+            return args
+        converted = []
+        for arg in args:
+            pargs: T.Tuple[str, ...] = tuple()
+            # Library search path
+            if arg.startswith('-L/'):
+                pargs = PurePath(arg[2:]).parts
+                tmpl = '-L{}:/{}'
+            elif arg.startswith('-I/'):
+                pargs = PurePath(arg[2:]).parts
+                tmpl = '-I{}:/{}'
+            # Full path to library or .la file
+            elif arg.startswith('/'):
+                pargs = PurePath(arg).parts
+                tmpl = '{}:/{}'
+            elif arg.startswith(('-L', '-I')) or (len(arg) > 2 and arg[1] == ':'):
+                # clean out improper '\\ ' as comes from some Windows pkg-config files
+                arg = arg.replace('\\ ', ' ')
+            if len(pargs) > 1 and len(pargs[1]) == 1:
+                arg = tmpl.format(pargs[1], '/'.join(pargs[2:]))
+            converted.append(arg)
+        return converted
+
+    def _split_args(self, cmd: str) -> T.List[str]:
+        # pkg-config paths follow Unix conventions, even on Windows; split the
+        # output using shlex.split rather than mesonlib.split_args
+        return shlex.split(cmd)
+
+    def _set_cargs(self) -> None:
+        env = None
+        if self.language == 'fortran':
+            # gfortran doesn't appear to look in system paths for INCLUDE files,
+            # so don't allow pkg-config to suppress -I flags for system paths
+            env = os.environ.copy()
+            env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1'
+        ret, out, err = self._call_pkgbin(['--cflags', self.name], env=env)
+        if ret != 0:
+            raise DependencyException(f'Could not generate cargs for {self.name}:\n{err}\n')
+        self.compile_args = self._convert_mingw_paths(self._split_args(out))
+
+    def _search_libs(self, out: str, out_raw: str) -> T.Tuple[T.List[str], T.List[str]]:
+        '''
+        @out: PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs
+        @out_raw: pkg-config --libs
+
+        We always look for the file ourselves instead of depending on the
+        compiler to find it with -lfoo or foo.lib (if possible) because:
+        1. We want to be able to select static or shared
+        2. We need the full path of the library to calculate RPATH values
+        3. De-dup of libraries is easier when we have absolute paths
+
+        Libraries that are provided by the toolchain or are not found by
+        find_library() will be added with -L -l pairs.
+        '''
+        # Library paths should be safe to de-dup
+        #
+        # First, figure out what library paths to use. Originally, we were
+        # doing this as part of the loop, but due to differences in the order
+        # of -L values between pkg-config and pkgconf, we need to do that as
+        # a separate step. See:
+        # https://github.com/mesonbuild/meson/issues/3951
+        # https://github.com/mesonbuild/meson/issues/4023
+        #
+        # Separate system and prefix paths, and ensure that prefix paths are
+        # always searched first.
+        prefix_libpaths: OrderedSet[str] = OrderedSet()
+        # We also store this raw_link_args on the object later
+        raw_link_args = self._convert_mingw_paths(self._split_args(out_raw))
+        for arg in raw_link_args:
+            if arg.startswith('-L') and not arg.startswith(('-L-l', '-L-L')):
+                path = arg[2:]
+                if not os.path.isabs(path):
+                    # Resolve the path as a compiler in the build directory would
+                    path = os.path.join(self.env.get_build_dir(), path)
+                prefix_libpaths.add(path)
+        # Library paths are not always ordered in a meaningful way
+        #
+        # Instead of relying on pkg-config or pkgconf to provide -L flags in a
+        # specific order, we reorder library paths ourselves, according to th
+        # order specified in PKG_CONFIG_PATH. See:
+        # https://github.com/mesonbuild/meson/issues/4271
+        #
+        # Only prefix_libpaths are reordered here because there should not be
+        # too many system_libpaths to cause library version issues.
+        pkg_config_path: T.List[str] = self.env.coredata.options[OptionKey('pkg_config_path', machine=self.for_machine)].value
+        pkg_config_path = self._convert_mingw_paths(pkg_config_path)
+        prefix_libpaths = OrderedSet(sort_libpaths(list(prefix_libpaths), pkg_config_path))
+        system_libpaths: OrderedSet[str] = OrderedSet()
+        full_args = self._convert_mingw_paths(self._split_args(out))
+        for arg in full_args:
+            if arg.startswith(('-L-l', '-L-L')):
+                # These are D language arguments, not library paths
+                continue
+            if arg.startswith('-L') and arg[2:] not in prefix_libpaths:
+                system_libpaths.add(arg[2:])
+        # Use this re-ordered path list for library resolution
+        libpaths = list(prefix_libpaths) + list(system_libpaths)
+        # Track -lfoo libraries to avoid duplicate work
+        libs_found: OrderedSet[str] = OrderedSet()
+        # Track not-found libraries to know whether to add library paths
+        libs_notfound = []
+        # Generate link arguments for this library
+        link_args = []
+        for lib in full_args:
+            if lib.startswith(('-L-l', '-L-L')):
+                # These are D language arguments, add them as-is
+                pass
+            elif lib.startswith('-L'):
+                # We already handled library paths above
+                continue
+            elif lib.startswith('-l:'):
+                # see: https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a
+                # also : See the documentation of -lnamespec | --library=namespec in the linker manual
+                #                     https://sourceware.org/binutils/docs-2.18/ld/Options.html
+
+                # Don't resolve the same -l:libfoo.a argument again
+                if lib in libs_found:
+                    continue
+                libfilename = lib[3:]
+                foundname = None
+                for libdir in libpaths:
+                    target = os.path.join(libdir, libfilename)
+                    if os.path.exists(target):
+                        foundname = target
+                        break
+                if foundname is None:
+                    if lib in libs_notfound:
+                        continue
+                    else:
+                        mlog.warning('Library {!r} not found for dependency {!r}, may '
+                                    'not be successfully linked'.format(libfilename, self.name))
+                    libs_notfound.append(lib)
+                else:
+                    lib = foundname
+            elif lib.startswith('-l'):
+                # Don't resolve the same -lfoo argument again
+                if lib in libs_found:
+                    continue
+                if self.clib_compiler:
+                    args = self.clib_compiler.find_library(lib[2:], self.env,
+                                                           libpaths, self.libtype)
+                # If the project only uses a non-clib language such as D, Rust,
+                # C#, Python, etc, all we can do is limp along by adding the
+                # arguments as-is and then adding the libpaths at the end.
+                else:
+                    args = None
+                if args is not None:
+                    libs_found.add(lib)
+                    # Replace -l arg with full path to library if available
+                    # else, library is either to be ignored, or is provided by
+                    # the compiler, can't be resolved, and should be used as-is
+                    if args:
+                        if not args[0].startswith('-l'):
+                            lib = args[0]
+                    else:
+                        continue
+                else:
+                    # Library wasn't found, maybe we're looking in the wrong
+                    # places or the library will be provided with LDFLAGS or
+                    # LIBRARY_PATH from the environment (on macOS), and many
+                    # other edge cases that we can't account for.
+                    #
+                    # Add all -L paths and use it as -lfoo
+                    if lib in libs_notfound:
+                        continue
+                    if self.static:
+                        mlog.warning('Static library {!r} not found for dependency {!r}, may '
+                                     'not be statically linked'.format(lib[2:], self.name))
+                    libs_notfound.append(lib)
+            elif lib.endswith(".la"):
+                shared_libname = self.extract_libtool_shlib(lib)
+                shared_lib = os.path.join(os.path.dirname(lib), shared_libname)
+                if not os.path.exists(shared_lib):
+                    shared_lib = os.path.join(os.path.dirname(lib), ".libs", shared_libname)
+
+                if not os.path.exists(shared_lib):
+                    raise DependencyException(f'Got a libtools specific "{lib}" dependencies'
+                                              'but we could not compute the actual shared'
+                                              'library path')
+                self.is_libtool = True
+                lib = shared_lib
+                if lib in link_args:
+                    continue
+            link_args.append(lib)
+        # Add all -Lbar args if we have -lfoo args in link_args
+        if libs_notfound:
+            # Order of -L flags doesn't matter with ld, but it might with other
+            # linkers such as MSVC, so prepend them.
+            link_args = ['-L' + lp for lp in prefix_libpaths] + link_args
+        return link_args, raw_link_args
+
+    def _set_libs(self) -> None:
+        env = None
+        libcmd = ['--libs']
+
+        if self.static:
+            libcmd.append('--static')
+
+        libcmd.append(self.name)
+
+        # Force pkg-config to output -L fields even if they are system
+        # paths so we can do manual searching with cc.find_library() later.
+        env = os.environ.copy()
+        env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1'
+        ret, out, err = self._call_pkgbin(libcmd, env=env)
+        if ret != 0:
+            raise DependencyException(f'Could not generate libs for {self.name}:\n{err}\n')
+        # Also get the 'raw' output without -Lfoo system paths for adding -L
+        # args with -lfoo when a library can't be found, and also in
+        # gnome.generate_gir + gnome.gtkdoc which need -L -l arguments.
+        ret, out_raw, err_raw = self._call_pkgbin(libcmd)
+        if ret != 0:
+            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:
+        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
+
+        ret, out, err = self._call_pkgbin(options)
+        variable = ''
+        if ret != 0:
+            if self.required:
+                raise DependencyException(f'dependency {self.name} not found:\n{err}\n')
+        else:
+            variable = out.strip()
+
+            # pkg-config doesn't distinguish between empty and non-existent variables
+            # use the variable list to check for variable existence
+            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']
+                    else:
+                        mlog.warning(f"pkgconfig variable '{variable_name}' not defined for dependency {self.name}.")
+
+        mlog.debug(f'Got pkgconfig variable {variable_name} : {variable}')
+        return variable
+
+    def check_pkgconfig(self, pkgbin: ExternalProgram) -> T.Optional[str]:
+        if not pkgbin.found():
+            mlog.log(f'Did not find pkg-config by name {pkgbin.name!r}')
+            return None
+        command_as_string = ' '.join(pkgbin.get_command())
+        try:
+            helptext = Popen_safe(pkgbin.get_command() + ['--help'])[1]
+            if 'Pure-Perl' in helptext:
+                mlog.log(f'found pkg-config {command_as_string!r} but it is Strawberry Perl and thus broken. Ignoring...')
+                return None
+            p, out = Popen_safe(pkgbin.get_command() + ['--version'])[0:2]
+            if p.returncode != 0:
+                mlog.warning(f'Found pkg-config {command_as_string!r} but it failed when run')
+                return None
+        except FileNotFoundError:
+            mlog.warning(f'We thought we found pkg-config {command_as_string!r} but now it\'s not there. How odd!')
+            return None
+        except PermissionError:
+            msg = f'Found pkg-config {command_as_string!r} but didn\'t have permissions to run it.'
+            if not self.env.machines.build.is_windows():
+                msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.'
+            mlog.warning(msg)
+            return None
+        return out.strip()
+
+    def extract_field(self, la_file: str, fieldname: str) -> T.Optional[str]:
+        with open(la_file, encoding='utf-8') as f:
+            for line in f:
+                arr = line.strip().split('=')
+                if arr[0] == fieldname:
+                    return arr[1][1:-1]
+        return None
+
+    def extract_dlname_field(self, la_file: str) -> T.Optional[str]:
+        return self.extract_field(la_file, 'dlname')
+
+    def extract_libdir_field(self, la_file: str) -> T.Optional[str]:
+        return self.extract_field(la_file, 'libdir')
+
+    def extract_libtool_shlib(self, la_file: str) -> T.Optional[str]:
+        '''
+        Returns the path to the shared library
+        corresponding to this .la file
+        '''
+        dlname = self.extract_dlname_field(la_file)
+        if dlname is None:
+            return None
+
+        # Darwin uses absolute paths where possible; since the libtool files never
+        # contain absolute paths, use the libdir field
+        if self.env.machines[self.for_machine].is_darwin():
+            dlbasename = os.path.basename(dlname)
+            libdir = self.extract_libdir_field(la_file)
+            if libdir is None:
+                return dlbasename
+            return os.path.join(libdir, dlbasename)
+        # From the comments in extract_libtool(), older libtools had
+        # a path rather than the raw dlname
+        return os.path.basename(dlname)
+
+    def log_tried(self) -> str:
+        return self.type_name
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     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)
+            except DependencyException:
+                pass
+        if default_value is not None:
+            return default_value
+        raise DependencyException(f'Could not get pkg-config variable and no default provided for {self!r}')
diff -Nru meson-0.53.2/mesonbuild/dependencies/platform.py meson-0.61.2/mesonbuild/dependencies/platform.py
--- meson-0.53.2/mesonbuild/dependencies/platform.py	2019-05-02 18:59:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/platform.py	2021-08-18 11:22:15.000000000 +0000
@@ -15,12 +15,16 @@
 # This file contains the detection logic for external dependencies that are
 # platform-specific (generally speaking).
 
-from .base import ExternalDependency, DependencyException
+from .base import DependencyTypeName, ExternalDependency, DependencyException
 from ..mesonlib import MesonException
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
 
 class AppleFrameworks(ExternalDependency):
-    def __init__(self, env, kwargs):
-        super().__init__('appleframeworks', env, None, kwargs)
+    def __init__(self, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(DependencyTypeName('appleframeworks'), env, kwargs)
         modules = kwargs.get('modules', [])
         if isinstance(modules, str):
             modules = [modules]
@@ -47,8 +51,8 @@
             else:
                 self.is_found = False
 
-    def log_info(self):
+    def log_info(self) -> str:
         return ', '.join(self.frameworks)
 
-    def log_tried(self):
+    def log_tried(self) -> str:
         return 'framework'
diff -Nru meson-0.53.2/mesonbuild/dependencies/qt.py meson-0.61.2/mesonbuild/dependencies/qt.py
--- meson-0.53.2/mesonbuild/dependencies/qt.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/qt.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,438 @@
+# Copyright 2013-2017 The Meson development team
+# Copyright © 2021 Intel Corporation
+# SPDX-license-identifier: Apache-2.0
+
+# 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.
+
+"""Dependency finders for the Qt framework."""
+
+import abc
+import re
+import os
+import typing as T
+
+from .base import DependencyException, DependencyMethods
+from .configtool import ConfigToolDependency
+from .framework import ExtraFrameworkDependency
+from .pkgconfig import PkgConfigDependency
+from .factory import DependencyFactory
+from .. import mlog
+from .. import mesonlib
+
+if T.TYPE_CHECKING:
+    from ..compilers import Compiler
+    from ..envconfig import MachineInfo
+    from ..environment import Environment
+
+
+def _qt_get_private_includes(mod_inc_dir: str, module: str, mod_version: str) -> T.List[str]:
+    # usually Qt5 puts private headers in /QT_INSTALL_HEADERS/module/VERSION/module/private
+    # except for at least QtWebkit and Enginio where the module version doesn't match Qt version
+    # as an example with Qt 5.10.1 on linux you would get:
+    # /usr/include/qt5/QtCore/5.10.1/QtCore/private/
+    # /usr/include/qt5/QtWidgets/5.10.1/QtWidgets/private/
+    # /usr/include/qt5/QtWebKit/5.212.0/QtWebKit/private/
+
+    # on Qt4 when available private folder is directly in module folder
+    # like /usr/include/QtCore/private/
+    if int(mod_version.split('.')[0]) < 5:
+        return []
+
+    private_dir = os.path.join(mod_inc_dir, mod_version)
+    # fallback, let's try to find a directory with the latest version
+    if not os.path.exists(private_dir):
+        dirs = [filename for filename in os.listdir(mod_inc_dir)
+                if os.path.isdir(os.path.join(mod_inc_dir, filename))]
+
+        for dirname in sorted(dirs, reverse=True):
+            if len(dirname.split('.')) == 3:
+                private_dir = dirname
+                break
+    return [private_dir, os.path.join(private_dir, 'Qt' + module)]
+
+
+def get_qmake_host_bins(qvars: T.Dict[str, str]) -> str:
+    # Prefer QT_HOST_BINS (qt5, correct for cross and native compiling)
+    # but fall back to QT_INSTALL_BINS (qt4)
+    if 'QT_HOST_BINS' in qvars:
+        return qvars['QT_HOST_BINS']
+    return qvars['QT_INSTALL_BINS']
+
+
+def _get_modules_lib_suffix(version: str, info: 'MachineInfo', is_debug: bool) -> str:
+    """Get the module suffix based on platform and debug type."""
+    suffix = ''
+    if info.is_windows():
+        if is_debug:
+            suffix += 'd'
+        if version.startswith('4'):
+            suffix += '4'
+    if info.is_darwin():
+        if is_debug:
+            suffix += '_debug'
+    if mesonlib.version_compare(version, '>= 5.14.0'):
+        if info.is_android():
+            if info.cpu_family == 'x86':
+                suffix += '_x86'
+            elif info.cpu_family == 'x86_64':
+                suffix += '_x86_64'
+            elif info.cpu_family == 'arm':
+                suffix += '_armeabi-v7a'
+            elif info.cpu_family == 'aarch64':
+                suffix += '_arm64-v8a'
+            else:
+                mlog.warning(f'Android target arch "{info.cpu_family}"" for Qt5 is unknown, '
+                             'module detection may not work')
+    return suffix
+
+
+class QtExtraFrameworkDependency(ExtraFrameworkDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language=language)
+        self.mod_name = name[2:]
+
+    def get_compile_args(self, with_private_headers: bool = False, qt_version: str = "0") -> T.List[str]:
+        if self.found():
+            mod_inc_dir = os.path.join(self.framework_path, 'Headers')
+            args = ['-I' + mod_inc_dir]
+            if with_private_headers:
+                args += ['-I' + dirname for dirname in _qt_get_private_includes(mod_inc_dir, self.mod_name, qt_version)]
+            return args
+        return []
+
+
+class _QtBase:
+
+    """Mixin class for shared components between PkgConfig and Qmake."""
+
+    link_args: T.List[str]
+    clib_compiler: 'Compiler'
+    env: 'Environment'
+
+    def __init__(self, name: str, kwargs: T.Dict[str, T.Any]):
+        self.qtname = name.capitalize()
+        self.qtver = name[-1]
+        if self.qtver == "4":
+            self.qtpkgname = 'Qt'
+        else:
+            self.qtpkgname = self.qtname
+
+        self.private_headers = T.cast(bool, kwargs.get('private_headers', False))
+
+        self.requested_modules = mesonlib.stringlistify(mesonlib.extract_as_list(kwargs, 'modules'))
+        if not self.requested_modules:
+            raise DependencyException('No ' + self.qtname + '  modules specified.')
+
+        self.qtmain = T.cast(bool, kwargs.get('main', False))
+        if not isinstance(self.qtmain, bool):
+            raise DependencyException('"main" argument must be a boolean')
+
+    def _link_with_qtmain(self, is_debug: bool, libdir: T.Union[str, T.List[str]]) -> bool:
+        libdir = mesonlib.listify(libdir)  # TODO: shouldn't be necessary
+        base_name = 'qtmaind' if is_debug else 'qtmain'
+        qtmain = self.clib_compiler.find_library(base_name, self.env, libdir)
+        if qtmain:
+            self.link_args.append(qtmain[0])
+            return True
+        return False
+
+    def get_exe_args(self, compiler: 'Compiler') -> T.List[str]:
+        # Originally this was -fPIE but nowadays the default
+        # for upstream and distros seems to be -reduce-relocations
+        # which requires -fPIC. This may cause a performance
+        # penalty when using self-built Qt or on platforms
+        # where -fPIC is not required. If this is an issue
+        # for you, patches are welcome.
+        return compiler.get_pic_args()
+
+    def log_details(self) -> str:
+        return f'modules: {", ".join(sorted(self.requested_modules))}'
+
+
+class QtPkgConfigDependency(_QtBase, PkgConfigDependency, metaclass=abc.ABCMeta):
+
+    """Specialization of the PkgConfigDependency for Qt."""
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        _QtBase.__init__(self, name, kwargs)
+
+        # Always use QtCore as the "main" dependency, since it has the extra
+        # pkg-config variables that a user would expect to get. If "Core" is
+        # not a requested module, delete the compile and link arguments to
+        # avoid linking with something they didn't ask for
+        PkgConfigDependency.__init__(self, self.qtpkgname + 'Core', env, kwargs)
+        if 'Core' not in self.requested_modules:
+            self.compile_args = []
+            self.link_args = []
+
+        for m in self.requested_modules:
+            mod = PkgConfigDependency(self.qtpkgname + m, self.env, kwargs, language=self.language)
+            if not mod.found():
+                self.is_found = False
+                return
+            if self.private_headers:
+                qt_inc_dir = mod.get_pkgconfig_variable('includedir', {})
+                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
+                    # up correctly. /usr/local/opt/qt/include/Qt + m_name is a
+                    # symlink to /usr/local/opt/qt/include, but the pkg-config
+                    # file points to /usr/local/Cellar/qt/x.y.z/Headers/, and
+                    # the Qt + m_name there is not a symlink, it's a file
+                    mod_private_dir = qt_inc_dir
+                mod_private_inc = _qt_get_private_includes(mod_private_dir, m, mod.version)
+                for directory in mod_private_inc:
+                    mod.compile_args.append('-I' + directory)
+            self._add_sub_dependency([lambda: mod])
+
+        if self.env.machines[self.for_machine].is_windows() and self.qtmain:
+            # Check if we link with debug binaries
+            debug_lib_name = self.qtpkgname + 'Core' + _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], True)
+            is_debug = False
+            for arg in self.get_link_args():
+                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', {})
+            if not self._link_with_qtmain(is_debug, libdir):
+                self.is_found = False
+                return
+
+        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', {})
+            if prefix:
+                self.bindir = os.path.join(prefix, 'bin')
+
+    @staticmethod
+    @abc.abstractmethod
+    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> T.Optional[str]:
+        pass
+
+    @abc.abstractmethod
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        pass
+
+    def log_info(self) -> str:
+        return 'pkg-config'
+
+
+class QmakeQtDependency(_QtBase, ConfigToolDependency, metaclass=abc.ABCMeta):
+
+    """Find Qt using Qmake as a config-tool."""
+
+    tool_name = 'qmake'
+    version_arg = '-v'
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        _QtBase.__init__(self, name, kwargs)
+        self.tools = [f'qmake-{self.qtname}', 'qmake']
+
+        # Add additional constraints that the Qt version is met, but preserve
+        # any version requrements the user has set as well. For example, if Qt5
+        # is requested, add "">= 5, < 6", but if the user has ">= 5.6", don't
+        # lose that.
+        kwargs = kwargs.copy()
+        _vers = mesonlib.listify(kwargs.get('version', []))
+        _vers.extend([f'>= {self.qtver}', f'< {int(self.qtver) + 1}'])
+        kwargs['version'] = _vers
+
+        ConfigToolDependency.__init__(self, name, env, kwargs)
+        if not self.found():
+            return
+
+        # Query library path, header path, and binary path
+        stdo = self.get_config_value(['-query'], 'args')
+        qvars: T.Dict[str, str] = {}
+        for line in stdo:
+            line = line.strip()
+            if line == '':
+                continue
+            k, v = line.split(':', 1)
+            qvars[k] = v
+        # Qt on macOS uses a framework, but Qt for iOS/tvOS does not
+        xspec = qvars.get('QMAKE_XSPEC', '')
+        if self.env.machines.host.is_darwin() and not any(s in xspec for s in ['ios', 'tvos']):
+            mlog.debug("Building for macOS, looking for framework")
+            self._framework_detect(qvars, self.requested_modules, kwargs)
+            # Sometimes Qt is built not as a framework (for instance, when using conan pkg manager)
+            # skip and fall back to normal procedure then
+            if self.is_found:
+                return
+            else:
+                mlog.debug("Building for macOS, couldn't find framework, falling back to library search")
+        incdir = qvars['QT_INSTALL_HEADERS']
+        self.compile_args.append('-I' + incdir)
+        libdir = qvars['QT_INSTALL_LIBS']
+        # Used by qt.compilers_detect()
+        self.bindir = get_qmake_host_bins(qvars)
+
+        # Use the buildtype by default, but look at the b_vscrt option if the
+        # compiler supports it.
+        is_debug = self.env.coredata.get_option(mesonlib.OptionKey('buildtype')) == 'debug'
+        if mesonlib.OptionKey('b_vscrt') in self.env.coredata.options:
+            if self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value in {'mdd', 'mtd'}:
+                is_debug = True
+        modules_lib_suffix = _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], is_debug)
+
+        for module in self.requested_modules:
+            mincdir = os.path.join(incdir, 'Qt' + module)
+            self.compile_args.append('-I' + mincdir)
+
+            if module == 'QuickTest':
+                define_base = 'QMLTEST'
+            elif module == 'Test':
+                define_base = 'TESTLIB'
+            else:
+                define_base = module.upper()
+            self.compile_args.append(f'-DQT_{define_base}_LIB')
+
+            if self.private_headers:
+                priv_inc = self.get_private_includes(mincdir, module)
+                for directory in priv_inc:
+                    self.compile_args.append('-I' + directory)
+            libfiles = self.clib_compiler.find_library(
+                self.qtpkgname + module + modules_lib_suffix, self.env,
+                mesonlib.listify(libdir)) # TODO: shouldn't be necissary
+            if libfiles:
+                libfile = libfiles[0]
+            else:
+                mlog.log("Could not find:", module,
+                         self.qtpkgname + module + modules_lib_suffix,
+                         'in', libdir)
+                self.is_found = False
+                break
+            self.link_args.append(libfile)
+
+        if self.env.machines[self.for_machine].is_windows() and self.qtmain:
+            if not self._link_with_qtmain(is_debug, libdir):
+                self.is_found = False
+
+    def _sanitize_version(self, version: str) -> str:
+        m = re.search(rf'({self.qtver}(\.\d+)+)', version)
+        if m:
+            return m.group(0).rstrip('.')
+        return version
+
+    @abc.abstractmethod
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        pass
+
+    def _framework_detect(self, qvars: T.Dict[str, str], modules: T.List[str], kwargs: T.Dict[str, T.Any]) -> None:
+        libdir = qvars['QT_INSTALL_LIBS']
+
+        # ExtraFrameworkDependency doesn't support any methods
+        fw_kwargs = kwargs.copy()
+        fw_kwargs.pop('method', None)
+        fw_kwargs['paths'] = [libdir]
+
+        for m in modules:
+            fname = 'Qt' + m
+            mlog.debug('Looking for qt framework ' + fname)
+            fwdep = QtExtraFrameworkDependency(fname, self.env, fw_kwargs, language=self.language)
+            if fwdep.found():
+                self.compile_args.append('-F' + libdir)
+                self.compile_args += fwdep.get_compile_args(with_private_headers=self.private_headers,
+                                                            qt_version=self.version)
+                self.link_args += fwdep.get_link_args()
+            else:
+                self.is_found = False
+                break
+        else:
+            self.is_found = True
+            # Used by self.compilers_detect()
+            self.bindir = get_qmake_host_bins(qvars)
+
+    def log_info(self) -> str:
+        return 'qmake'
+
+
+class Qt4ConfigToolDependency(QmakeQtDependency):
+
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        return []
+
+
+class Qt5ConfigToolDependency(QmakeQtDependency):
+
+    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)
+
+
+class Qt6ConfigToolDependency(QmakeQtDependency):
+
+    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)
+
+
+class Qt4PkgConfigDependency(QtPkgConfigDependency):
+
+    @staticmethod
+    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> T.Optional[str]:
+        # Only return one bins dir, because the tools are generally all in one
+        # directory for Qt4, in Qt5, they must all be in one directory. Return
+        # the first one found among the bin variables, in case one tool is not
+        # configured to be built.
+        applications = ['moc', 'uic', 'rcc', 'lupdate', 'lrelease']
+        for application in applications:
+            try:
+                return os.path.dirname(core.get_pkgconfig_variable(f'{application}_location', {}))
+            except mesonlib.MesonException:
+                pass
+        return None
+
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        return []
+
+
+class Qt5PkgConfigDependency(QtPkgConfigDependency):
+
+    @staticmethod
+    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str:
+        return core.get_pkgconfig_variable('host_bins', {})
+
+    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)
+
+
+class Qt6PkgConfigDependency(QtPkgConfigDependency):
+
+    @staticmethod
+    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str:
+        return core.get_pkgconfig_variable('host_bins', {})
+
+    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)
+
+
+qt4_factory = DependencyFactory(
+    'qt4',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    pkgconfig_class=Qt4PkgConfigDependency,
+    configtool_class=Qt4ConfigToolDependency,
+)
+
+qt5_factory = DependencyFactory(
+    'qt5',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    pkgconfig_class=Qt5PkgConfigDependency,
+    configtool_class=Qt5ConfigToolDependency,
+)
+
+qt6_factory = DependencyFactory(
+    'qt6',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    pkgconfig_class=Qt6PkgConfigDependency,
+    configtool_class=Qt6ConfigToolDependency,
+)
diff -Nru meson-0.53.2/mesonbuild/dependencies/scalapack.py meson-0.61.2/mesonbuild/dependencies/scalapack.py
--- meson-0.53.2/mesonbuild/dependencies/scalapack.py	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/scalapack.py	2021-08-18 11:22:15.000000000 +0000
@@ -1,4 +1,4 @@
-# Copyright 2013-2019 The Meson development team
+# Copyright 2013-2020 The Meson development team
 
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,108 +13,141 @@
 # limitations under the License.
 
 from pathlib import Path
+import functools
 import os
+import typing as T
 
-from .. import mesonlib
-from .base import CMakeDependency, DependencyMethods, ExternalDependency, PkgConfigDependency
+from .base import DependencyMethods
+from .base import DependencyException
+from .cmake import CMakeDependency
+from .pkgconfig import PkgConfigDependency
+from .factory import factory_methods
 
+if T.TYPE_CHECKING:
+    from ..environment import Environment, MachineChoice
+    from .factory import DependencyGenerator
 
-class ScalapackDependency(ExternalDependency):
-    def __init__(self, environment, kwargs: dict):
-        super().__init__('scalapack', environment, None, kwargs)
-        kwargs['required'] = False
-        kwargs['silent'] = True
-        self.is_found = False
-        self.static = kwargs.get('static', False)
-        methods = mesonlib.listify(self.methods)
-
-        if set([DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]).intersection(methods):
-            pkgconfig_files = []
-            mklroot = None
-            is_gcc = self.clib_compiler.get_id() == 'gcc'
-            # Intel MKL works with non-Intel compilers too -- but not gcc on windows
-            if 'MKLROOT' in os.environ and not (mesonlib.is_windows() and is_gcc):
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE})
+def scalapack_factory(env: 'Environment', for_machine: 'MachineChoice',
+                      kwargs: T.Dict[str, T.Any],
+                      methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        mkl = 'mkl-static-lp64-iomp' if kwargs.get('static', False) else 'mkl-dynamic-lp64-iomp'
+        candidates.append(functools.partial(
+            MKLPkgConfigDependency, mkl, env, kwargs))
+
+        for pkg in ['scalapack-openmpi', 'scalapack']:
+            candidates.append(functools.partial(
+                PkgConfigDependency, pkg, env, kwargs))
+
+    if DependencyMethods.CMAKE in methods:
+        candidates.append(functools.partial(
+            CMakeDependency, 'Scalapack', env, kwargs))
+
+    return candidates
+
+
+class MKLPkgConfigDependency(PkgConfigDependency):
+
+    """PkgConfigDependency for Intel MKL.
+
+    MKL's pkg-config is pretty much borked in every way. We need to apply a
+    bunch of fixups to make it work correctly.
+    """
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None):
+        _m = os.environ.get('MKLROOT')
+        self.__mklroot = Path(_m).resolve() if _m else None
+
+        # We need to call down into the normal super() method even if we don't
+        # find mklroot, otherwise we won't have all of the instance variables
+        # initialized that meson expects.
+        super().__init__(name, env, kwargs, language=language)
+
+        # Doesn't work with gcc on windows, but does on Linux
+        if (not self.__mklroot or (env.machines[self.for_machine].is_windows()
+                                   and self.clib_compiler.id == 'gcc')):
+            self.is_found = False
+
+        # This can happen either because we're using GCC, we couldn't find the
+        # mklroot, or the pkg-config couldn't find it.
+        if not self.is_found:
+            return
+
+        assert self.version != '', 'This should not happen if we didn\'t return above'
+
+        if self.version == 'unknown':
+            # At least by 2020 the version is in the pkg-config, just not with
+            # the correct name
+            v = self.get_variable(pkgconfig='Version', default_value='')
+
+            if not v and self.__mklroot:
                 try:
-                    mklroot = Path(os.environ['MKLROOT']).resolve()
-                except Exception:
+                    v = (
+                        self.__mklroot.as_posix()
+                        .split('compilers_and_libraries_')[1]
+                        .split('/', 1)[0]
+                    )
+                except IndexError:
                     pass
-            if mklroot is not None:
-                # MKL pkg-config is a start, but you have to add / change stuff
-                # https://software.intel.com/en-us/articles/intel-math-kernel-library-intel-mkl-and-pkg-config-tool
-                pkgconfig_files = (
-                    ['mkl-static-lp64-iomp'] if self.static else ['mkl-dynamic-lp64-iomp']
-                )
-                if mesonlib.is_windows():
-                    suffix = '.lib'
-                elif self.static:
-                    suffix = '.a'
-                else:
-                    suffix = ''
-                libdir = mklroot / 'lib/intel64'
-            # Intel compiler might not have Parallel Suite
-            pkgconfig_files += ['scalapack-openmpi', 'scalapack']
-
-            for pkg in pkgconfig_files:
-                pkgdep = PkgConfigDependency(
-                    pkg, environment, kwargs, language=self.language
-                )
-                if pkgdep.found():
-                    self.compile_args = pkgdep.get_compile_args()
-                    if mklroot:
-                        link_args = pkgdep.get_link_args()
-                        if is_gcc:
-                            for i, a in enumerate(link_args):
-                                if 'mkl_intel_lp64' in a:
-                                    link_args[i] = a.replace('intel', 'gf')
-                                    break
-                        # MKL pkg-config omits scalapack
-                        # be sure "-L" and "-Wl" are first if present
-                        i = 0
-                        for j, a in enumerate(link_args):
-                            if a.startswith(('-L', '-Wl')):
-                                i = j + 1
-                            elif j > 3:
-                                break
-                        if mesonlib.is_windows() or self.static:
-                            link_args.insert(
-                                i, str(libdir / ('mkl_scalapack_lp64' + suffix))
-                            )
-                            link_args.insert(
-                                i + 1, str(libdir / ('mkl_blacs_intelmpi_lp64' + suffix))
-                            )
-                        else:
-                            link_args.insert(i, '-lmkl_scalapack_lp64')
-                            link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')
-                    else:
-                        link_args = pkgdep.get_link_args()
-                    self.link_args = link_args
-
-                    self.version = pkgdep.get_version()
-                    if self.version == 'unknown' and mklroot:
-                        try:
-                            v = (
-                                mklroot.as_posix()
-                                .split('compilers_and_libraries_')[1]
-                                .split('/', 1)[0]
-                            )
-                            if v:
-                                self.version = v
-                        except IndexError:
-                            pass
-
-                    self.is_found = True
-                    self.pcdep = pkgdep
-                    return
-
-        if set([DependencyMethods.AUTO, DependencyMethods.CMAKE]).intersection(methods):
-            cmakedep = CMakeDependency('Scalapack', environment, kwargs, language=self.language)
-            if cmakedep.found():
-                self.compile_args = cmakedep.get_compile_args()
-                self.link_args = cmakedep.get_link_args()
-                self.version = cmakedep.get_version()
-                self.is_found = True
-                return
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.AUTO, DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE]
+
+            if v:
+                assert isinstance(v, str)
+                self.version = v
+
+    def _set_libs(self) -> None:
+        super()._set_libs()
+
+        if self.env.machines[self.for_machine].is_windows():
+            suffix = '.lib'
+        elif self.static:
+            suffix = '.a'
+        else:
+            suffix = ''
+        libdir = self.__mklroot / 'lib/intel64'
+
+        if self.clib_compiler.id == 'gcc':
+            for i, a in enumerate(self.link_args):
+                # only replace in filename, not in directory names
+                dirname, basename = os.path.split(a)
+                if 'mkl_intel_lp64' in basename:
+                    basename = basename.replace('intel', 'gf')
+                    self.link_args[i] = '/' + os.path.join(dirname, basename)
+        # MKL pkg-config omits scalapack
+        # be sure "-L" and "-Wl" are first if present
+        i = 0
+        for j, a in enumerate(self.link_args):
+            if a.startswith(('-L', '-Wl')):
+                i = j + 1
+            elif j > 3:
+                break
+        if self.env.machines[self.for_machine].is_windows() or self.static:
+            self.link_args.insert(
+                i, str(libdir / ('mkl_scalapack_lp64' + suffix))
+            )
+            self.link_args.insert(
+                i + 1, str(libdir / ('mkl_blacs_intelmpi_lp64' + suffix))
+            )
+        else:
+            self.link_args.insert(i, '-lmkl_scalapack_lp64')
+            self.link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')
+
+    def _set_cargs(self) -> None:
+        env = None
+        if self.language == 'fortran':
+            # gfortran doesn't appear to look in system paths for INCLUDE files,
+            # so don't allow pkg-config to suppress -I flags for system paths
+            env = os.environ.copy()
+            env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1'
+        ret, out, err = self._call_pkgbin([
+            '--cflags', self.name,
+            '--define-variable=prefix=' + self.__mklroot.as_posix()],
+            env=env)
+        if ret != 0:
+            raise DependencyException('Could not generate cargs for %s:\n%s\n' %
+                                      (self.name, err))
+        self.compile_args = self._convert_mingw_paths(self._split_args(out))
diff -Nru meson-0.53.2/mesonbuild/dependencies/ui.py meson-0.61.2/mesonbuild/dependencies/ui.py
--- meson-0.53.2/mesonbuild/dependencies/ui.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/dependencies/ui.py	2021-11-02 19:58:07.000000000 +0000
@@ -14,28 +14,28 @@
 
 # This file contains the detection logic for external dependencies that
 # are UI-related.
-import functools
 import os
-import re
 import subprocess
-from collections import OrderedDict
+import typing as T
 
 from .. import mlog
 from .. import mesonlib
 from ..mesonlib import (
-    MesonException, Popen_safe, extract_as_list, version_compare_many
+    Popen_safe, extract_as_list, version_compare_many
 )
 from ..environment import detect_cpu_family
 
-from .base import DependencyException, DependencyMethods
-from .base import ExternalDependency, ExternalProgram, NonExistingExternalProgram
-from .base import ExtraFrameworkDependency, PkgConfigDependency
-from .base import ConfigToolDependency
+from .base import DependencyException, DependencyMethods, DependencyTypeName, SystemDependency
+from .configtool import ConfigToolDependency
+from .factory import DependencyFactory
 
+if T.TYPE_CHECKING:
+    from ..environment import Environment
 
-class GLDependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('gl', environment, None, kwargs)
+
+class GLDependencySystem(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs)
 
         if self.env.machines[self.for_machine].is_darwin():
             self.is_found = True
@@ -50,27 +50,7 @@
             # FIXME: Detect version using self.clib_compiler
             return
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'gl', environment, kwargs))
-
-        if DependencyMethods.SYSTEM in methods:
-            candidates.append(functools.partial(GLDependency, environment, kwargs))
-
-        return candidates
-
-    @staticmethod
-    def get_methods():
-        if mesonlib.is_osx() or mesonlib.is_windows():
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
-        else:
-            return [DependencyMethods.PKGCONFIG]
-
-    def log_tried(self):
+    def log_tried(self) -> str:
         return 'system'
 
 class GnuStepDependency(ConfigToolDependency):
@@ -78,8 +58,8 @@
     tools = ['gnustep-config']
     tool_name = 'gnustep-config'
 
-    def __init__(self, environment, kwargs):
-        super().__init__('gnustep', environment, 'objc', kwargs)
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__('gnustep', environment, kwargs, language='objc')
         if not self.is_found:
             return
         self.modules = kwargs.get('modules', [])
@@ -89,13 +69,13 @@
             ['--gui-libs' if 'gui' in self.modules else '--base-libs'],
             'link_args'))
 
-    def find_config(self, versions=None):
+    def find_config(self, versions: T.Optional[T.List[str]] = None, returncode: int = 0) -> T.Tuple[T.Optional[T.List[str]], T.Optional[str]]:
         tool = [self.tools[0]]
         try:
             p, out = Popen_safe(tool + ['--help'])[:2]
         except (FileNotFoundError, PermissionError):
             return (None, None)
-        if p.returncode != 0:
+        if p.returncode != returncode:
             return (None, None)
         self.config = tool
         found_version = self.detect_version()
@@ -104,14 +84,16 @@
 
         return (tool, found_version)
 
-    def weird_filter(self, elems):
+    @staticmethod
+    def weird_filter(elems: T.List[str]) -> T.List[str]:
         """When building packages, the output of the enclosing Make is
         sometimes mixed among the subprocess output. I have no idea why. As a
         hack filter out everything that is not a flag.
         """
         return [e for e in elems if e.startswith('-')]
 
-    def filter_args(self, args):
+    @staticmethod
+    def filter_args(args: T.List[str]) -> T.List[str]:
         """gnustep-config returns a bunch of garbage args such as -O2 and so
         on. Drop everything that is not needed.
         """
@@ -125,7 +107,7 @@
                 result.append(f)
         return result
 
-    def detect_version(self):
+    def detect_version(self) -> str:
         gmake = self.get_config_value(['--variable=GNUMAKE'], 'variable')[0]
         makefile_dir = self.get_config_value(['--variable=GNUSTEP_MAKEFILES'], 'variable')[0]
         # This Makefile has the GNUStep version set
@@ -148,421 +130,17 @@
         return version
 
 
-def _qt_get_private_includes(mod_inc_dir, module, mod_version):
-    # usually Qt5 puts private headers in /QT_INSTALL_HEADERS/module/VERSION/module/private
-    # except for at least QtWebkit and Enginio where the module version doesn't match Qt version
-    # as an example with Qt 5.10.1 on linux you would get:
-    # /usr/include/qt5/QtCore/5.10.1/QtCore/private/
-    # /usr/include/qt5/QtWidgets/5.10.1/QtWidgets/private/
-    # /usr/include/qt5/QtWebKit/5.212.0/QtWebKit/private/
-
-    # on Qt4 when available private folder is directly in module folder
-    # like /usr/include/QtCore/private/
-    if int(mod_version.split('.')[0]) < 5:
-        return tuple()
-
-    private_dir = os.path.join(mod_inc_dir, mod_version)
-    # fallback, let's try to find a directory with the latest version
-    if not os.path.exists(private_dir):
-        dirs = [filename for filename in os.listdir(mod_inc_dir)
-                if os.path.isdir(os.path.join(mod_inc_dir, filename))]
-        dirs.sort(reverse=True)
-
-        for dirname in dirs:
-            if len(dirname.split('.')) == 3:
-                private_dir = dirname
-                break
-    return (private_dir,
-            os.path.join(private_dir, 'Qt' + module))
-
-class QtExtraFrameworkDependency(ExtraFrameworkDependency):
-    def __init__(self, name, required, paths, env, lang, kwargs):
-        super().__init__(name, required, paths, env, lang, kwargs)
-        self.mod_name = name[2:]
-
-    def get_compile_args(self, with_private_headers=False, qt_version="0"):
-        if self.found():
-            mod_inc_dir = os.path.join(self.framework_path, 'Headers')
-            args = ['-I' + mod_inc_dir]
-            if with_private_headers:
-                args += ['-I' + dirname for dirname in _qt_get_private_includes(mod_inc_dir, self.mod_name, qt_version)]
-            return args
-        return []
-
-class QtBaseDependency(ExternalDependency):
-    def __init__(self, name, env, kwargs):
-        super().__init__(name, env, 'cpp', kwargs)
-        self.qtname = name.capitalize()
-        self.qtver = name[-1]
-        if self.qtver == "4":
-            self.qtpkgname = 'Qt'
-        else:
-            self.qtpkgname = self.qtname
-        self.root = '/usr'
-        self.bindir = None
-        self.private_headers = kwargs.get('private_headers', False)
-        mods = extract_as_list(kwargs, 'modules')
-        self.requested_modules = mods
-        if not mods:
-            raise DependencyException('No ' + self.qtname + '  modules specified.')
-        self.from_text = 'pkg-config'
-
-        self.qtmain = kwargs.get('main', False)
-        if not isinstance(self.qtmain, bool):
-            raise DependencyException('"main" argument must be a boolean')
-
-        # Keep track of the detection methods used, for logging purposes.
-        methods = []
-        # Prefer pkg-config, then fallback to `qmake -query`
-        if DependencyMethods.PKGCONFIG in self.methods:
-            mlog.debug('Trying to find qt with pkg-config')
-            self._pkgconfig_detect(mods, kwargs)
-            methods.append('pkgconfig')
-        if not self.is_found and DependencyMethods.QMAKE in self.methods:
-            mlog.debug('Trying to find qt with qmake')
-            self.from_text = self._qmake_detect(mods, kwargs)
-            methods.append('qmake-' + self.name)
-            methods.append('qmake')
-        if not self.is_found:
-            # Reset compile args and link args
-            self.compile_args = []
-            self.link_args = []
-            self.from_text = mlog.format_list(methods)
-            self.version = None
-
-    def compilers_detect(self, interp_obj):
-        "Detect Qt (4 or 5) moc, uic, rcc in the specified bindir or in PATH"
-        # It is important that this list does not change order as the order of
-        # the returned ExternalPrograms will change as well
-        bins = ['moc', 'uic', 'rcc', 'lrelease']
-        found = {b: NonExistingExternalProgram(name='{}-{}'.format(b, self.name))
-                 for b in bins}
-
-        def gen_bins():
-            for b in bins:
-                if self.bindir:
-                    yield os.path.join(self.bindir, b), b, False
-                yield '{}-{}'.format(b, self.name), b, False
-                yield b, b, self.required if b != 'lrelease' else False
-
-        for b, name, required in gen_bins():
-            if found[name].found():
-                continue
-
-            # prefer the -qt of the tool to the plain one, as we
-            # don't know what the unsuffixed one points to without calling it.
-            p = interp_obj.find_program_impl([b], silent=True, required=required).held_object
-            if not p.found():
-                continue
-
-            if name == 'lrelease':
-                arg = ['-version']
-            elif mesonlib.version_compare(self.version, '>= 5'):
-                arg = ['--version']
-            else:
-                arg = ['-v']
-
-            # Ensure that the version of qt and each tool are the same
-            _, out, err = mesonlib.Popen_safe(p.get_command() + arg)
-            if b.startswith('lrelease') or not self.version.startswith('4'):
-                care = out
-            else:
-                care = err
-            if mesonlib.version_compare(self.version, '== {}'.format(care.split(' ')[-1])):
-                found[name] = p
-
-        return tuple([found[b] for b in bins])
-
-    def _pkgconfig_detect(self, mods, kwargs):
-        # We set the value of required to False so that we can try the
-        # qmake-based fallback if pkg-config fails.
-        kwargs['required'] = False
-        modules = OrderedDict()
-        for module in mods:
-            modules[module] = PkgConfigDependency(self.qtpkgname + module, self.env,
-                                                  kwargs, language=self.language)
-        for m_name, m in modules.items():
-            if not m.found():
-                self.is_found = False
-                return
-            self.compile_args += m.get_compile_args()
-            if self.private_headers:
-                qt_inc_dir = m.get_pkgconfig_variable('includedir', dict())
-                mod_private_dir = os.path.join(qt_inc_dir, 'Qt' + m_name)
-                if not os.path.isdir(mod_private_dir):
-                    # At least some versions of homebrew don't seem to set this
-                    # up correctly. /usr/local/opt/qt/include/Qt + m_name is a
-                    # symlink to /usr/local/opt/qt/include, but the pkg-config
-                    # file points to /usr/local/Cellar/qt/x.y.z/Headers/, and
-                    # the Qt + m_name there is not a symlink, it's a file
-                    mod_private_dir = qt_inc_dir
-                mod_private_inc = _qt_get_private_includes(mod_private_dir, m_name, m.version)
-                for directory in mod_private_inc:
-                    self.compile_args.append('-I' + directory)
-            self.link_args += m.get_link_args()
+class SDL2DependencyConfigTool(ConfigToolDependency):
 
-        if 'Core' in modules:
-            core = modules['Core']
-        else:
-            corekwargs = {'required': 'false', 'silent': 'true'}
-            core = PkgConfigDependency(self.qtpkgname + 'Core', self.env, corekwargs,
-                                       language=self.language)
-            modules['Core'] = core
-
-        if self.env.machines[self.for_machine].is_windows() and self.qtmain:
-            # Check if we link with debug binaries
-            debug_lib_name = self.qtpkgname + 'Core' + self._get_modules_lib_suffix(True)
-            is_debug = False
-            for arg in core.get_link_args():
-                if arg == '-l%s' % debug_lib_name or arg.endswith('%s.lib' % debug_lib_name) or arg.endswith('%s.a' % debug_lib_name):
-                    is_debug = True
-                    break
-            libdir = core.get_pkgconfig_variable('libdir', {})
-            if not self._link_with_qtmain(is_debug, libdir):
-                self.is_found = False
-                return
+    tools = ['sdl2-config']
+    tool_name = 'sdl2-config'
 
-        self.is_found = True
-        self.version = m.version
-        self.pcdep = list(modules.values())
-        # Try to detect moc, uic, rcc
-        # Used by self.compilers_detect()
-        self.bindir = self.get_pkgconfig_host_bins(core)
-        if not self.bindir:
-            # If exec_prefix is not defined, the pkg-config file is broken
-            prefix = core.get_pkgconfig_variable('exec_prefix', {})
-            if prefix:
-                self.bindir = os.path.join(prefix, 'bin')
-
-    def _qmake_detect(self, mods, kwargs):
-        for qmake in ('qmake-' + self.name, 'qmake'):
-            self.qmake = ExternalProgram.from_bin_list(
-                self.env.binaries.host, qmake)
-            if not self.qmake.found():
-                # Even when cross-compiling, if a cross-info qmake is not
-                # specified, we fallback to using the qmake in PATH because
-                # that's what we used to do
-                self.qmake = ExternalProgram.from_bin_list(
-                    self.env.binaries.build, qmake)
-            if not self.qmake.found():
-                self.qmake = ExternalProgram(qmake, silent=True)
-            if not self.qmake.found():
-                continue
-            # Check that the qmake is for qt5
-            pc, stdo = Popen_safe(self.qmake.get_command() + ['-v'])[0:2]
-            if pc.returncode != 0:
-                continue
-            if not 'Qt version ' + self.qtver in stdo:
-                mlog.log('QMake is not for ' + self.qtname)
-                continue
-            # Found qmake for Qt5!
-            break
-        else:
-            # Didn't find qmake :(
-            self.is_found = False
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
             return
-        self.version = re.search(self.qtver + r'(\.\d+)+', stdo).group(0)
-        # Query library path, header path, and binary path
-        mlog.log("Found qmake:", mlog.bold(self.qmake.get_path()), '(%s)' % self.version)
-        stdo = Popen_safe(self.qmake.get_command() + ['-query'])[1]
-        qvars = {}
-        for line in stdo.split('\n'):
-            line = line.strip()
-            if line == '':
-                continue
-            (k, v) = tuple(line.split(':', 1))
-            qvars[k] = v
-        # Qt on macOS uses a framework, but Qt for iOS/tvOS does not
-        xspec = qvars.get('QMAKE_XSPEC', '')
-        if self.env.machines.host.is_darwin() and not any(s in xspec for s in ['ios', 'tvos']):
-            mlog.debug("Building for macOS, looking for framework")
-            self._framework_detect(qvars, mods, kwargs)
-            return qmake
-        incdir = qvars['QT_INSTALL_HEADERS']
-        self.compile_args.append('-I' + incdir)
-        libdir = qvars['QT_INSTALL_LIBS']
-        # Used by self.compilers_detect()
-        self.bindir = self.get_qmake_host_bins(qvars)
-        self.is_found = True
-
-        is_debug = self.env.coredata.get_builtin_option('buildtype') == 'debug'
-        modules_lib_suffix = self._get_modules_lib_suffix(is_debug)
-
-        for module in mods:
-            mincdir = os.path.join(incdir, 'Qt' + module)
-            self.compile_args.append('-I' + mincdir)
-
-            if module == 'QuickTest':
-                define_base = 'QMLTEST'
-            elif module == 'Test':
-                define_base = 'TESTLIB'
-            else:
-                define_base = module.upper()
-            self.compile_args.append('-DQT_%s_LIB' % define_base)
-
-            if self.private_headers:
-                priv_inc = self.get_private_includes(mincdir, module)
-                for directory in priv_inc:
-                    self.compile_args.append('-I' + directory)
-            libfile = self.clib_compiler.find_library(self.qtpkgname + module + modules_lib_suffix,
-                                                      self.env,
-                                                      libdir)
-            if libfile:
-                libfile = libfile[0]
-            else:
-                self.is_found = False
-                break
-            self.link_args.append(libfile)
-
-        if self.env.machines[self.for_machine].is_windows() and self.qtmain:
-            if not self._link_with_qtmain(is_debug, libdir):
-                self.is_found = False
-
-        return qmake
-
-    def _get_modules_lib_suffix(self, is_debug):
-        suffix = ''
-        if self.env.machines[self.for_machine].is_windows():
-            if is_debug:
-                suffix += 'd'
-            if self.qtver == '4':
-                suffix += '4'
-        return suffix
-
-    def _link_with_qtmain(self, is_debug, libdir):
-        base_name = 'qtmaind' if is_debug else 'qtmain'
-        qtmain = self.clib_compiler.find_library(base_name, self.env, libdir)
-        if qtmain:
-            self.link_args.append(qtmain[0])
-            return True
-        return False
-
-    def _framework_detect(self, qvars, modules, kwargs):
-        libdir = qvars['QT_INSTALL_LIBS']
-
-        # ExtraFrameworkDependency doesn't support any methods
-        fw_kwargs = kwargs.copy()
-        fw_kwargs.pop('method', None)
-
-        for m in modules:
-            fname = 'Qt' + m
-            mlog.debug('Looking for qt framework ' + fname)
-            fwdep = QtExtraFrameworkDependency(fname, False, [libdir], self.env,
-                                               self.language, fw_kwargs)
-            self.compile_args.append('-F' + libdir)
-            if fwdep.found():
-                self.compile_args += fwdep.get_compile_args(with_private_headers=self.private_headers,
-                                                            qt_version=self.version)
-                self.link_args += fwdep.get_link_args()
-            else:
-                break
-        else:
-            self.is_found = True
-        # Used by self.compilers_detect()
-        self.bindir = self.get_qmake_host_bins(qvars)
-
-    def get_qmake_host_bins(self, qvars):
-        # Prefer QT_HOST_BINS (qt5, correct for cross and native compiling)
-        # but fall back to QT_INSTALL_BINS (qt4)
-        if 'QT_HOST_BINS' in qvars:
-            return qvars['QT_HOST_BINS']
-        else:
-            return qvars['QT_INSTALL_BINS']
-
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG, DependencyMethods.QMAKE]
-
-    def get_exe_args(self, compiler):
-        # Originally this was -fPIE but nowadays the default
-        # for upstream and distros seems to be -reduce-relocations
-        # which requires -fPIC. This may cause a performance
-        # penalty when using self-built Qt or on platforms
-        # where -fPIC is not required. If this is an issue
-        # for you, patches are welcome.
-        return compiler.get_pic_args()
-
-    def get_private_includes(self, mod_inc_dir, module):
-        return tuple()
-
-    def log_details(self):
-        module_str = ', '.join(self.requested_modules)
-        return 'modules: ' + module_str
-
-    def log_info(self):
-        return '{}'.format(self.from_text)
-
-    def log_tried(self):
-        return self.from_text
-
-
-class Qt4Dependency(QtBaseDependency):
-    def __init__(self, env, kwargs):
-        QtBaseDependency.__init__(self, 'qt4', env, kwargs)
-
-    def get_pkgconfig_host_bins(self, core):
-        # Only return one bins dir, because the tools are generally all in one
-        # directory for Qt4, in Qt5, they must all be in one directory. Return
-        # the first one found among the bin variables, in case one tool is not
-        # configured to be built.
-        applications = ['moc', 'uic', 'rcc', 'lupdate', 'lrelease']
-        for application in applications:
-            try:
-                return os.path.dirname(core.get_pkgconfig_variable('%s_location' % application, {}))
-            except MesonException:
-                pass
-
-
-class Qt5Dependency(QtBaseDependency):
-    def __init__(self, env, kwargs):
-        QtBaseDependency.__init__(self, 'qt5', env, kwargs)
-
-    def get_pkgconfig_host_bins(self, core):
-        return core.get_pkgconfig_variable('host_bins', {})
-
-    def get_private_includes(self, mod_inc_dir, module):
-        return _qt_get_private_includes(mod_inc_dir, module, self.version)
-
-
-# There are three different ways of depending on SDL2:
-# sdl2-config, pkg-config and OSX framework
-class SDL2Dependency(ExternalDependency):
-    def __init__(self, environment, kwargs):
-        super().__init__('sdl2', environment, None, kwargs)
-
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'sdl2', environment, kwargs))
-
-        if DependencyMethods.CONFIG_TOOL in methods:
-            candidates.append(functools.partial(ConfigToolDependency.factory,
-                                                'sdl2', environment, None,
-                                                kwargs, ['sdl2-config'],
-                                                'sdl2-config', SDL2Dependency.tool_finish_init))
-
-        if DependencyMethods.EXTRAFRAMEWORK in methods:
-            if mesonlib.is_osx():
-                candidates.append(functools.partial(ExtraFrameworkDependency,
-                                                    'sdl2', False, None, environment,
-                                                    kwargs.get('language', None), kwargs))
-                # fwdep.version = '2'  # FIXME
-        return candidates
-
-    @staticmethod
-    def tool_finish_init(ctdep):
-        ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
-        ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
-
-    @staticmethod
-    def get_methods():
-        if mesonlib.is_osx():
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK]
-        else:
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
 
 
 class WxDependency(ConfigToolDependency):
@@ -570,17 +148,30 @@
     tools = ['wx-config-3.0', 'wx-config', 'wx-config-gtk3']
     tool_name = 'wx-config'
 
-    def __init__(self, environment, kwargs):
-        super().__init__('WxWidgets', environment, None, kwargs)
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__('WxWidgets', environment, kwargs, language='cpp')
         if not self.is_found:
             return
         self.requested_modules = self.get_requested(kwargs)
+
+        extra_args = []
+        if self.static:
+            extra_args.append('--static=yes')
+
+            # Check to make sure static is going to work
+            err = Popen_safe(self.config + extra_args)[2]
+            if 'No config found to match' in err:
+                mlog.debug('WxWidgets is missing static libraries.')
+                self.is_found = False
+                return
+
         # wx-config seems to have a cflags as well but since it requires C++,
         # this should be good, at least for now.
-        self.compile_args = self.get_config_value(['--cxxflags'] + self.requested_modules, 'compile_args')
-        self.link_args = self.get_config_value(['--libs'] + self.requested_modules, 'link_args')
+        self.compile_args = self.get_config_value(['--cxxflags'] + extra_args + self.requested_modules, 'compile_args')
+        self.link_args = self.get_config_value(['--libs'] + extra_args + self.requested_modules, 'link_args')
 
-    def get_requested(self, kwargs):
+    @staticmethod
+    def get_requested(kwargs: T.Dict[str, T.Any]) -> T.List[str]:
         if 'modules' not in kwargs:
             return []
         candidates = extract_as_list(kwargs, 'modules')
@@ -590,10 +181,10 @@
         return candidates
 
 
-class VulkanDependency(ExternalDependency):
+class VulkanDependencySystem(SystemDependency):
 
-    def __init__(self, environment, kwargs):
-        super().__init__('vulkan', environment, None, kwargs)
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        super().__init__(name, environment, kwargs, language=language)
 
         try:
             self.vulkan_sdk = os.environ['VULKAN_SDK']
@@ -619,7 +210,7 @@
             inc_path = os.path.join(self.vulkan_sdk, inc_dir)
             header = os.path.join(inc_path, 'vulkan', 'vulkan.h')
             lib_path = os.path.join(self.vulkan_sdk, lib_dir)
-            find_lib = self.clib_compiler.find_library(lib_name, environment, lib_path)
+            find_lib = self.clib_compiler.find_library(lib_name, environment, [lib_path])
 
             if not find_lib:
                 raise DependencyException('VULKAN_SDK point to invalid directory (no lib)')
@@ -627,7 +218,8 @@
             if not os.path.isfile(header):
                 raise DependencyException('VULKAN_SDK point to invalid directory (no include)')
 
-            self.type_name = 'vulkan_sdk'
+            # XXX: this is very odd, and may deserve being removed
+            self.type_name = DependencyTypeName('vulkan_sdk')
             self.is_found = True
             self.compile_args.append('-I' + inc_path)
             self.link_args.append('-L' + lib_path)
@@ -640,28 +232,28 @@
             # simply try to guess it, usually works on linux
             libs = self.clib_compiler.find_library('vulkan', environment, [])
             if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment, disable_cache=True)[0]:
-                self.type_name = 'system'
                 self.is_found = True
                 for lib in libs:
                     self.link_args.append(lib)
                 return
 
-    @classmethod
-    def _factory(cls, environment, kwargs):
-        methods = cls._process_method_kw(kwargs)
-        candidates = []
-
-        if DependencyMethods.PKGCONFIG in methods:
-            candidates.append(functools.partial(PkgConfigDependency, 'vulkan', environment, kwargs))
-
-        if DependencyMethods.SYSTEM in methods:
-            candidates.append(functools.partial(VulkanDependency, environment, kwargs))
+    def log_tried(self) -> str:
+        return 'system'
 
-        return candidates
+gl_factory = DependencyFactory(
+    'gl',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    system_class=GLDependencySystem,
+)
 
-    @staticmethod
-    def get_methods():
-        return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
+sdl2_factory = DependencyFactory(
+    'sdl2',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK],
+    configtool_class=SDL2DependencyConfigTool,
+)
 
-    def log_tried(self):
-        return 'system'
+vulkan_factory = DependencyFactory(
+    'vulkan',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    system_class=VulkanDependencySystem,
+)
diff -Nru meson-0.53.2/mesonbuild/depfile.py meson-0.61.2/mesonbuild/depfile.py
--- meson-0.53.2/mesonbuild/depfile.py	2019-10-06 17:01:35.000000000 +0000
+++ meson-0.61.2/mesonbuild/depfile.py	2022-01-17 10:50:45.000000000 +0000
@@ -82,4 +82,4 @@
         deps.update(target.deps)
         for dep in target.deps:
             deps.update(self.get_all_dependencies(dep, visited))
-        return deps
+        return sorted(deps)
diff -Nru meson-0.53.2/mesonbuild/envconfig.py meson-0.61.2/mesonbuild/envconfig.py
--- meson-0.53.2/mesonbuild/envconfig.py	2020-01-23 22:34:28.000000000 +0000
+++ meson-0.61.2/mesonbuild/envconfig.py	2022-01-17 10:50:45.000000000 +0000
@@ -12,14 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import configparser, os, subprocess
+import subprocess
 import typing as T
+from enum import Enum
 
 from . import mesonlib
-from .mesonlib import EnvironmentException, split_args
+from .mesonlib import EnvironmentException, HoldableObject
 from . import mlog
-
-_T = T.TypeVar('_T')
+from pathlib import Path
 
 
 # These classes contains all the data pulled from configuration files (native
@@ -40,13 +40,20 @@
     'alpha',
     'arc',
     'arm',
+    'avr',
+    'c2000',
+    'csky',
+    'dspic',
     'e2k',
+    'ft32',
     'ia64',
+    'loongarch64',
     'm68k',
     'microblaze',
     'mips',
     'mips64',
     'parisc',
+    'pic24',
     'ppc',
     'ppc64',
     'riscv32',
@@ -55,20 +62,22 @@
     'rx',
     's390',
     's390x',
+    'sh4',
     'sparc',
     'sparc64',
     'wasm32',
     'wasm64',
     'x86',
-    'x86_64'
+    'x86_64',
 )
 
-# It would feel more natural to call this "64_BIT_CPU_FAMILES", but
+# It would feel more natural to call this "64_BIT_CPU_FAMILIES", but
 # python identifiers cannot start with numbers
-CPU_FAMILES_64_BIT = [
+CPU_FAMILIES_64_BIT = [
     'aarch64',
     'alpha',
     'ia64',
+    'loongarch64',
     'mips64',
     'ppc64',
     'riscv64',
@@ -78,55 +87,61 @@
     'x86_64',
 ]
 
-class MesonConfigFile:
-    @classmethod
-    def from_config_parser(cls, parser: configparser.ConfigParser) -> T.Dict[str, T.Dict[str, T.Dict[str, str]]]:
-        out = {}
-        # This is a bit hackish at the moment.
-        for s in parser.sections():
-            section = {}
-            for entry in parser[s]:
-                value = parser[s][entry]
-                # Windows paths...
-                value = value.replace('\\', '\\\\')
-                if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry:
-                    raise EnvironmentException('Malformed variable name %s in cross file..' % entry)
-                try:
-                    res = eval(value, {'__builtins__': None}, {'true': True, 'false': False})
-                except Exception:
-                    raise EnvironmentException('Malformed value in cross file variable %s.' % entry)
-
-                for i in (res if isinstance(res, list) else [res]):
-                    if not isinstance(i, (str, int, bool)):
-                        raise EnvironmentException('Malformed value in cross file variable %s.' % entry)
-
-                section[entry] = res
-
-            out[s] = section
-        return out
-
-class HasEnvVarFallback:
-    """
-    A tiny class to indicate that this class contains data that can be
-    initialized from either a config file or environment file. The `fallback`
-    field says whether env vars should be used. Downstream logic (e.g. subclass
-    methods) can check it to decide what to do, since env vars are currently
-    lazily decoded.
-
-    Frankly, this is a pretty silly class at the moment. The hope is the way
-    that we deal with environment variables will become more structured, and
-    this can be starting point.
-    """
-    def __init__(self, fallback: bool = True):
-        self.fallback = fallback
+# Map from language identifiers to environment variables.
+ENV_VAR_PROG_MAP: T.Mapping[str, str] = {
+    # Compilers
+    'c': 'CC',
+    'cpp': 'CXX',
+    'cs': 'CSC',
+    'd': 'DC',
+    'fortran': 'FC',
+    'objc': 'OBJC',
+    'objcpp': 'OBJCXX',
+    'rust': 'RUSTC',
+    'vala': 'VALAC',
+
+    # Linkers
+    'c_ld': 'CC_LD',
+    'cpp_ld': 'CXX_LD',
+    'd_ld': 'DC_LD',
+    'fortran_ld': 'FC_LD',
+    'objc_ld': 'OBJC_LD',
+    'objcpp_ld': 'OBJCXX_LD',
+    'rust_ld': 'RUSTC_LD',
+
+    # Binutils
+    'strip': 'STRIP',
+    'ar': 'AR',
+    'windres': 'WINDRES',
+
+    # Other tools
+    'cmake': 'CMAKE',
+    'qmake': 'QMAKE',
+    'pkgconfig': 'PKG_CONFIG',
+    'make': 'MAKE',
+    'vapigen': 'VAPIGEN',
+}
+
+# Deprecated environment variables mapped from the new variable to the old one
+# Deprecated in 0.54.0
+DEPRECATED_ENV_PROG_MAP: T.Mapping[str, str] = {
+    'd_ld': 'D_LD',
+    'fortran_ld': 'F_LD',
+    'rust_ld': 'RUST_LD',
+    'objcpp_ld': 'OBJCPP_LD',
+}
+
+class CMakeSkipCompilerTest(Enum):
+    ALWAYS = 'always'
+    NEVER = 'never'
+    DEP_ONLY = 'dep_only'
 
-class Properties(HasEnvVarFallback):
+class Properties:
     def __init__(
             self,
-            properties: T.Optional[T.Dict[str, T.Union[str, T.List[str]]]] = None,
-            fallback: bool = True):
-        super().__init__(fallback)
-        self.properties = properties or {}  # type: T.Dict[str, T.Union[str, T.List[str]]]
+            properties: T.Optional[T.Dict[str, T.Optional[T.Union[str, bool, int, T.List[str]]]]] = None,
+    ):
+        self.properties = properties or {}  # type: T.Dict[str, T.Optional[T.Union[str, bool, int, T.List[str]]]]
 
     def has_stdlib(self, language: str) -> bool:
         return language + '_stdlib' in self.properties
@@ -135,41 +150,100 @@
     # true, but without heterogenious dict annotations it's not practical to
     # narrow them
     def get_stdlib(self, language: str) -> T.Union[str, T.List[str]]:
-        return self.properties[language + '_stdlib']
+        stdlib = self.properties[language + '_stdlib']
+        if isinstance(stdlib, str):
+            return stdlib
+        assert isinstance(stdlib, list)
+        for i in stdlib:
+            assert isinstance(i, str)
+        return stdlib
+
+    def get_root(self) -> T.Optional[str]:
+        root = self.properties.get('root', None)
+        assert root is None or isinstance(root, str)
+        return root
+
+    def get_sys_root(self) -> T.Optional[str]:
+        sys_root = self.properties.get('sys_root', None)
+        assert sys_root is None or isinstance(sys_root, str)
+        return sys_root
+
+    def get_pkg_config_libdir(self) -> T.Optional[T.List[str]]:
+        p = self.properties.get('pkg_config_libdir', None)
+        if p is None:
+            return p
+        res = mesonlib.listify(p)
+        for i in res:
+            assert isinstance(i, str)
+        return res
+
+    def get_cmake_defaults(self) -> bool:
+        if 'cmake_defaults' not in self.properties:
+            return True
+        res = self.properties['cmake_defaults']
+        assert isinstance(res, bool)
+        return res
 
-    def get_root(self) -> T.Optional[T.Union[str, T.List[str]]]:
-        return self.properties.get('root', None)
+    def get_cmake_toolchain_file(self) -> T.Optional[Path]:
+        if 'cmake_toolchain_file' not in self.properties:
+            return None
+        raw = self.properties['cmake_toolchain_file']
+        assert isinstance(raw, str)
+        cmake_toolchain_file = Path(raw)
+        if not cmake_toolchain_file.is_absolute():
+            raise EnvironmentException(f'cmake_toolchain_file ({raw}) is not absolute')
+        return cmake_toolchain_file
+
+    def get_cmake_skip_compiler_test(self) -> CMakeSkipCompilerTest:
+        if 'cmake_skip_compiler_test' not in self.properties:
+            return CMakeSkipCompilerTest.DEP_ONLY
+        raw = self.properties['cmake_skip_compiler_test']
+        assert isinstance(raw, str)
+        try:
+            return CMakeSkipCompilerTest(raw)
+        except ValueError:
+            raise EnvironmentException(
+                '"{}" is not a valid value for cmake_skip_compiler_test. Supported values are {}'
+                .format(raw, [e.value for e in CMakeSkipCompilerTest]))
 
-    def get_sys_root(self) -> T.Optional[T.Union[str, T.List[str]]]:
-        return self.properties.get('sys_root', None)
+    def get_cmake_use_exe_wrapper(self) -> bool:
+        if 'cmake_use_exe_wrapper' not in self.properties:
+            return True
+        res = self.properties['cmake_use_exe_wrapper']
+        assert isinstance(res, bool)
+        return res
+
+    def get_java_home(self) -> T.Optional[Path]:
+        value = T.cast(T.Optional[str], self.properties.get('java_home'))
+        return Path(value) if value else None
 
-    def __eq__(self, other: T.Any) -> 'T.Union[bool, NotImplemented]':
+    def __eq__(self, other: object) -> bool:
         if isinstance(other, type(self)):
             return self.properties == other.properties
         return NotImplemented
 
     # TODO consider removing so Properties is less freeform
-    def __getitem__(self, key: str) -> T.Any:
+    def __getitem__(self, key: str) -> T.Optional[T.Union[str, bool, int, T.List[str]]]:
         return self.properties[key]
 
     # TODO consider removing so Properties is less freeform
-    def __contains__(self, item: T.Any) -> bool:
+    def __contains__(self, item: T.Union[str, bool, int, T.List[str]]) -> bool:
         return item in self.properties
 
     # TODO consider removing, for same reasons as above
-    def get(self, key: str, default: T.Any = None) -> T.Any:
+    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)
 
-class MachineInfo:
+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_FAMILES_64_BIT  # type: bool
+        self.is_64_bit = cpu_family in CPU_FAMILIES_64_BIT  # type: bool
 
-    def __eq__(self, other: T.Any) -> 'T.Union[bool, NotImplemented]':
-        if self.__class__ is not other.__class__:
+    def __eq__(self, other: object) -> bool:
+        if not isinstance(other, MachineInfo):
             return NotImplemented
         return \
             self.system == other.system and \
@@ -177,29 +251,29 @@
             self.cpu == other.cpu and \
             self.endian == other.endian
 
-    def __ne__(self, other: T.Any) -> 'T.Union[bool, NotImplemented]':
-        if self.__class__ is not other.__class__:
+    def __ne__(self, other: object) -> bool:
+        if not isinstance(other, MachineInfo):
             return NotImplemented
         return not self.__eq__(other)
 
     def __repr__(self) -> str:
-        return ''.format(self.system, self.cpu_family, self.cpu)
+        return f''
 
     @classmethod
     def from_literal(cls, literal: T.Dict[str, str]) -> 'MachineInfo':
         minimum_literal = {'cpu', 'cpu_family', 'endian', 'system'}
         if set(literal) < minimum_literal:
             raise EnvironmentException(
-                'Machine info is currently {}\n'.format(literal) +
+                f'Machine info is currently {literal}\n' +
                 'but is missing {}.'.format(minimum_literal - set(literal)))
 
         cpu_family = literal['cpu_family']
         if cpu_family not in known_cpu_families:
-            mlog.warning('Unknown CPU family %s, please report this at https://github.com/mesonbuild/meson/issues/new' % cpu_family)
+            mlog.warning(f'Unknown CPU family {cpu_family}, please report this at https://github.com/mesonbuild/meson/issues/new')
 
         endian = literal['endian']
         if endian not in ('little', 'big'):
-            mlog.warning('Unknown endian %s' % endian)
+            mlog.warning(f'Unknown endian {endian}')
 
         return cls(literal['system'], cpu_family, literal['cpu'], endian)
 
@@ -207,13 +281,13 @@
         """
         Machine is windows?
         """
-        return self.system == 'windows' or 'mingw' in self.system
+        return self.system == 'windows'
 
     def is_cygwin(self) -> bool:
         """
         Machine is cygwin?
         """
-        return self.system.startswith('cygwin')
+        return self.system == 'cygwin'
 
     def is_linux(self) -> bool:
         """
@@ -263,6 +337,16 @@
         """Machine is illumos or Solaris?"""
         return self.system == 'sunos'
 
+    def is_hurd(self) -> bool:
+        """
+        Machine is GNU/Hurd?
+        """
+        return self.system == 'gnu'
+
+    def is_irix(self) -> bool:
+        """Machine is IRIX?"""
+        return self.system.startswith('irix')
+
     # Various prefixes and suffixes for import libraries, shared libraries,
     # static libraries, and executables.
     # Versioning is added to these names in the backends as-needed.
@@ -281,52 +365,19 @@
     def libdir_layout_is_win(self) -> bool:
         return self.is_windows() or self.is_cygwin()
 
-class BinaryTable(HasEnvVarFallback):
+class BinaryTable:
+
     def __init__(
             self,
             binaries: T.Optional[T.Dict[str, T.Union[str, T.List[str]]]] = None,
-            fallback: bool = True):
-        super().__init__(fallback)
-        self.binaries = binaries or {}  # type: T.Dict[str, T.Union[str, T.List[str]]]
-        for name, command in self.binaries.items():
-            if not isinstance(command, (list, str)):
-                # TODO generalize message
-                raise mesonlib.MesonException(
-                    'Invalid type {!r} for binary {!r} in cross file'
-                    ''.format(command, name))
-
-    # Map from language identifiers to environment variables.
-    evarMap = {
-        # Compilers
-        'c': 'CC',
-        'cpp': 'CXX',
-        'cs': 'CSC',
-        'd': 'DC',
-        'fortran': 'FC',
-        'objc': 'OBJC',
-        'objcpp': 'OBJCXX',
-        'rust': 'RUSTC',
-        'vala': 'VALAC',
-
-        # Linkers
-        'c_ld': 'CC_LD',
-        'cpp_ld': 'CXX_LD',
-        'd_ld': 'D_LD',
-        'fortran_ld': 'F_LD',
-        'objc_ld': 'OBJC_LD',
-        'objcpp_ld': 'OBJCPP_LD',
-        'rust_ld': 'RUST_LD',
-
-        # Binutils
-        'strip': 'STRIP',
-        'ar': 'AR',
-        'windres': 'WINDRES',
-
-        # Other tools
-        'cmake': 'CMAKE',
-        'qmake': 'QMAKE',
-        'pkgconfig': 'PKG_CONFIG',
-    }  # type: T.Dict[str, str]
+    ):
+        self.binaries: T.Dict[str, T.List[str]] = {}
+        if binaries:
+            for name, command in binaries.items():
+                if not isinstance(command, (list, str)):
+                    raise mesonlib.MesonException(
+                        f'Invalid type {command!r} for entry {name!r} in cross file')
+                self.binaries[name] = mesonlib.listify(command)
 
     @staticmethod
     def detect_ccache() -> T.List[str]:
@@ -336,12 +387,21 @@
             return []
         return ['ccache']
 
-    @classmethod
-    def _warn_about_lang_pointing_to_cross(cls, compiler_exe: str, evar: str) -> None:
-        evar_str = os.environ.get(evar, 'WHO_WOULD_CALL_THEIR_COMPILER_WITH_THIS_NAME')
-        if evar_str == compiler_exe:
-            mlog.warning('''Env var %s seems to point to the cross compiler.
-This is probably wrong, it should always point to the native compiler.''' % evar)
+    @staticmethod
+    def detect_sccache() -> T.List[str]:
+        try:
+            subprocess.check_call(['sccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        except (OSError, subprocess.CalledProcessError):
+            return []
+        return ['sccache']
+
+    @staticmethod
+    def detect_compiler_cache() -> T.List[str]:
+        # Sccache is "newer" so it is assumed that people would prefer it by default.
+        cache = BinaryTable.detect_sccache()
+        if cache:
+            return cache
+        return BinaryTable.detect_ccache()
 
     @classmethod
     def parse_entry(cls, entry: T.Union[str, T.List[str]]) -> T.Tuple[T.List[str], T.List[str]]:
@@ -350,74 +410,37 @@
         if compiler[0] == 'ccache':
             compiler = compiler[1:]
             ccache = cls.detect_ccache()
+        elif compiler[0] == 'sccache':
+            compiler = compiler[1:]
+            ccache = cls.detect_sccache()
         else:
             ccache = []
         # Return value has to be a list of compiler 'choices'
         return compiler, ccache
 
     def lookup_entry(self, name: str) -> T.Optional[T.List[str]]:
-        """Lookup binaryk
+        """Lookup binary in cross/native file and fallback to environment.
 
         Returns command with args as list if found, Returns `None` if nothing is
         found.
-
-        First tries looking in explicit map, then tries environment variable.
         """
-        # Try explicit map, don't fall back on env var
         command = self.binaries.get(name)
-        if command is not None:
-            command = mesonlib.stringlistify(command)
-            # Relies on there being no "" env var
-            evar = self.evarMap.get(name, "")
-            self._warn_about_lang_pointing_to_cross(command[0], evar)
-        elif self.fallback:
-            # Relies on there being no "" env var
-            evar = self.evarMap.get(name, "")
-            command = os.environ.get(evar)
-            if command is not None:
-                command = split_args(command)
-
-        # Do not return empty or blank string entries
-        if command is not None and (len(command) == 0 or len(command[0].strip()) == 0):
+        if not command:
+            return None
+        elif not command[0].strip():
             return None
         return command
 
-class Directories:
-
-    """Data class that holds information about directories for native and cross
-    builds.
-    """
-
-    def __init__(self, bindir: T.Optional[str] = None, datadir: T.Optional[str] = None,
-                 includedir: T.Optional[str] = None, infodir: T.Optional[str] = None,
-                 libdir: T.Optional[str] = None, libexecdir: T.Optional[str] = None,
-                 localedir: T.Optional[str] = None, localstatedir: T.Optional[str] = None,
-                 mandir: T.Optional[str] = None, prefix: T.Optional[str] = None,
-                 sbindir: T.Optional[str] = None, sharedstatedir: T.Optional[str] = None,
-                 sysconfdir: T.Optional[str] = None):
-        self.bindir = bindir
-        self.datadir = datadir
-        self.includedir = includedir
-        self.infodir = infodir
-        self.libdir = libdir
-        self.libexecdir = libexecdir
-        self.localedir = localedir
-        self.localstatedir = localstatedir
-        self.mandir = mandir
-        self.prefix = prefix
-        self.sbindir = sbindir
-        self.sharedstatedir = sharedstatedir
-        self.sysconfdir = sysconfdir
-
-    def __contains__(self, key: str) -> bool:
-        return hasattr(self, key)
-
-    def __getitem__(self, key: str) -> T.Optional[str]:
-        # Mypy can't figure out what to do with getattr here, so we'll case for it
-        return T.cast(T.Optional[str], getattr(self, key))
-
-    def __setitem__(self, key: str, value: T.Optional[str]) -> None:
-        setattr(self, key, value)
+class CMakeVariables:
+    def __init__(self, variables: T.Optional[T.Dict[str, T.Any]] = None) -> None:
+        variables = variables or {}
+        self.variables = {}  # type: T.Dict[str, T.List[str]]
+
+        for key, value in variables.items():
+            value = mesonlib.listify(value)
+            for i in value:
+                assert isinstance(i, str)
+            self.variables[key] = value
 
-    def __iter__(self) -> T.Iterator[T.Tuple[str, str]]:
-        return iter(self.__dict__.items())
+    def get_variables(self) -> T.Dict[str, T.List[str]]:
+        return self.variables
diff -Nru meson-0.53.2/mesonbuild/environment.py meson-0.61.2/mesonbuild/environment.py
--- meson-0.53.2/mesonbuild/environment.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/environment.py	2021-11-02 19:58:13.000000000 +0000
@@ -1,4 +1,4 @@
-# Copyright 2012-2016 The Meson development team
+# Copyright 2012-2020 The Meson development team
 
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -12,23 +12,25 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os, platform, re, sys, shutil, subprocess
-import tempfile
-import shlex
+import itertools
+import os, platform, re, sys, shutil
 import typing as T
+import collections
 
 from . import coredata
-from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, DLinker, CcrxLinker, IntelVisualStudioLinker
 from . import mesonlib
 from .mesonlib import (
-    MesonException, EnvironmentException, MachineChoice, Popen_safe,
-    PerMachineDefaultable, PerThreeMachineDefaultable, split_args, quote_arg
+    MesonException, EnvironmentException, MachineChoice, Popen_safe, PerMachine,
+    PerMachineDefaultable, PerThreeMachineDefaultable, split_args, quote_arg, OptionKey,
+    search_version, MesonBugException
 )
 from . import mlog
+from .programs import (
+    ExternalProgram, EmptyExternalProgram
+)
 
 from .envconfig import (
-    BinaryTable, Directories, MachineInfo, MesonConfigFile,
-    Properties, known_cpu_families,
+    BinaryTable, MachineInfo, Properties, known_cpu_families, CMakeVariables,
 )
 from . import compilers
 from .compilers import (
@@ -40,81 +42,49 @@
     is_object,
     is_source,
 )
-from .linkers import (
-    AppleDynamicLinker,
-    ArmClangDynamicLinker,
-    ArmDynamicLinker,
-    CcrxDynamicLinker,
-    ClangClDynamicLinker,
-    DynamicLinker,
-    GnuBFDDynamicLinker,
-    GnuGoldDynamicLinker,
-    LLVMDynamicLinker,
-    MSVCDynamicLinker,
-    OptlinkDynamicLinker,
-    PGIDynamicLinker,
-    PGIStaticLinker,
-    SolarisDynamicLinker,
-    XilinkDynamicLinker,
-    CudaLinker,
-    VisualStudioLikeLinkerMixin,
-)
+
 from functools import lru_cache
-from .compilers import (
-    ArmCCompiler,
-    ArmCPPCompiler,
-    ArmclangCCompiler,
-    ArmclangCPPCompiler,
-    AppleClangCCompiler,
-    AppleClangCPPCompiler,
-    ClangCCompiler,
-    ClangCPPCompiler,
-    ClangObjCCompiler,
-    ClangObjCPPCompiler,
-    ClangClCCompiler,
-    ClangClCPPCompiler,
-    FlangFortranCompiler,
-    G95FortranCompiler,
-    GnuCCompiler,
-    GnuCPPCompiler,
-    GnuFortranCompiler,
-    GnuObjCCompiler,
-    GnuObjCPPCompiler,
-    ElbrusCCompiler,
-    ElbrusCPPCompiler,
-    ElbrusFortranCompiler,
-    EmscriptenCCompiler,
-    EmscriptenCPPCompiler,
-    IntelCCompiler,
-    IntelClCCompiler,
-    IntelCPPCompiler,
-    IntelClCPPCompiler,
-    IntelFortranCompiler,
-    IntelClFortranCompiler,
-    JavaCompiler,
-    MonoCompiler,
-    CudaCompiler,
-    VisualStudioCsCompiler,
-    NAGFortranCompiler,
-    Open64FortranCompiler,
-    PathScaleFortranCompiler,
-    PGICCompiler,
-    PGICPPCompiler,
-    PGIFortranCompiler,
-    RustCompiler,
-    CcrxCCompiler,
-    CcrxCPPCompiler,
-    SunFortranCompiler,
-    ValaCompiler,
-    VisualStudioCCompiler,
-    VisualStudioCPPCompiler,
-)
+from mesonbuild import envconfig
+
+if T.TYPE_CHECKING:
+    from configparser import ConfigParser
+
+    from .wrap.wrap import Resolver
 
 build_filename = 'meson.build'
 
 CompilersDict = T.Dict[str, Compiler]
 
-def detect_gcovr(min_version='3.3', new_rootdir_version='4.2', log=False):
+if T.TYPE_CHECKING:
+    import argparse
+
+
+def _get_env_var(for_machine: MachineChoice, is_cross: bool, var_name: str) -> T.Optional[str]:
+    """
+    Returns the exact env var and the value.
+    """
+    candidates = PerMachine(
+        # The prefixed build version takes priority, but if we are native
+        # compiling we fall back on the unprefixed host version. This
+        # allows native builds to never need to worry about the 'BUILD_*'
+        # ones.
+        ([var_name + '_FOR_BUILD'] if is_cross else [var_name]),
+        # Always just the unprefixed host versions
+        [var_name]
+    )[for_machine]
+    for var in candidates:
+        value = os.environ.get(var)
+        if value is not None:
+            break
+    else:
+        formatted = ', '.join([f'{var!r}' for var in candidates])
+        mlog.debug(f'None of {formatted} are defined in the environment, not changing global flags.')
+        return None
+    mlog.debug(f'Using {var!r} from environment with value: {value!r}')
+    return value
+
+
+def detect_gcovr(min_version='3.3', log=False):
     gcovr_exe = 'gcovr'
     try:
         p, found = Popen_safe([gcovr_exe, '--version'])[0:2]
@@ -125,11 +95,20 @@
     if p.returncode == 0 and mesonlib.version_compare(found, '>=' + min_version):
         if log:
             mlog.log('Found gcovr-{} at {}'.format(found, quote_arg(shutil.which(gcovr_exe))))
-        return gcovr_exe, mesonlib.version_compare(found, '>=' + new_rootdir_version)
+        return gcovr_exe, found
     return None, None
 
-def find_coverage_tools():
-    gcovr_exe, gcovr_new_rootdir = detect_gcovr()
+def detect_llvm_cov():
+    tools = get_llvm_tool_names('llvm-cov')
+    for tool in tools:
+        if mesonlib.exe_exists([tool, '--version']):
+            return tool
+    return None
+
+def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]:
+    gcovr_exe, gcovr_version = detect_gcovr()
+
+    llvm_cov_exe = detect_llvm_cov()
 
     lcov_exe = 'lcov'
     genhtml_exe = 'genhtml'
@@ -139,17 +118,20 @@
     if not mesonlib.exe_exists([genhtml_exe, '--version']):
         genhtml_exe = None
 
-    return gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe
+    return gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe
 
-def detect_ninja(version: str = '1.5', log: bool = False) -> str:
+def detect_ninja(version: str = '1.8.2', log: bool = False) -> T.List[str]:
     r = detect_ninja_command_and_version(version, log)
     return r[0] if r else None
 
-def detect_ninja_command_and_version(version: str = '1.5', log: bool = False) -> (str, str):
+def detect_ninja_command_and_version(version: str = '1.8.2', log: bool = False) -> T.Tuple[T.List[str], str]:
     env_ninja = os.environ.get('NINJA', None)
     for n in [env_ninja] if env_ninja else ['ninja', 'ninja-build', 'samu']:
+        prog = ExternalProgram(n, silent=True)
+        if not prog.found():
+            continue
         try:
-            p, found = Popen_safe([n, '--version'])[0:2]
+            p, found = Popen_safe(prog.command + ['--version'])[0:2]
         except (FileNotFoundError, PermissionError):
             # Doesn't exist in PATH or isn't executable
             continue
@@ -157,7 +139,6 @@
         # Perhaps we should add a way for the caller to know the failure mode
         # (not found or too old)
         if p.returncode == 0 and mesonlib.version_compare(found, '>=' + version):
-            n = shutil.which(n)
             if log:
                 name = os.path.basename(n)
                 if name.endswith('-' + found):
@@ -166,8 +147,9 @@
                     name = 'ninja'
                 if name == 'samu':
                     name = 'samurai'
-                mlog.log('Found {}-{} at {}'.format(name, found, quote_arg(n)))
-            return (n, found)
+                mlog.log('Found {}-{} at {}'.format(name, found,
+                         ' '.join([quote_arg(x) for x in prog.command])))
+            return (prog.command, found)
 
 def get_llvm_tool_names(tool: str) -> T.List[str]:
     # Ordered list of possible suffixes of LLVM executables to try. Start with
@@ -177,6 +159,9 @@
     # unless it becomes a stable release.
     suffixes = [
         '', # base (no suffix)
+        '-12',  '12',
+        '-11',  '11',
+        '-10',  '10',
         '-9',   '90',
         '-8',   '80',
         '-7',   '70',
@@ -188,7 +173,7 @@
         '-3.7', '37',
         '-3.6', '36',
         '-3.5', '35',
-        '-10',    # Debian development snapshot
+        '-13',    # Debian development snapshot
         '-devel', # FreeBSD development snapshot
     ]
     names = []
@@ -318,7 +303,7 @@
     """
     if mesonlib.is_windows():
         trial = detect_windows_arch(compilers)
-    elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd():
+    elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_qnx() or mesonlib.is_aix():
         trial = platform.processor().lower()
     else:
         trial = platform.machine().lower()
@@ -326,18 +311,28 @@
         trial = 'x86'
     elif trial == 'bepc':
         trial = 'x86'
+    elif trial == 'arm64':
+        trial = 'aarch64'
+    elif trial.startswith('aarch64'):
+        # This can be `aarch64_be`
+        trial = 'aarch64'
     elif trial.startswith('arm') or trial.startswith('earm'):
         trial = 'arm'
     elif trial.startswith(('powerpc64', 'ppc64')):
         trial = 'ppc64'
-    elif trial.startswith(('powerpc', 'ppc')):
-        trial = 'ppc'
-    elif trial == 'macppc':
+    elif trial.startswith(('powerpc', 'ppc')) or trial in {'macppc', 'power macintosh'}:
         trial = 'ppc'
     elif trial in ('amd64', 'x64', 'i86pc'):
         trial = 'x86_64'
     elif trial in {'sun4u', 'sun4v'}:
         trial = 'sparc64'
+    elif trial.startswith('mips'):
+        if '64' not in trial:
+            trial = 'mips'
+        else:
+            trial = 'mips64'
+    elif trial in {'ip30', 'ip35'}:
+        trial = 'mips64'
 
     # On Linux (and maybe others) there can be any mixture of 32/64 bit code in
     # the kernel, Python, system, 32-bit chroot on 64-bit host, etc. The only
@@ -354,50 +349,65 @@
         # ATM there is no 64 bit userland for PA-RISC. Thus always
         # report it as 32 bit for simplicity.
         trial = 'parisc'
+    elif trial == 'ppc':
+        # AIX always returns powerpc, check here for 64-bit
+        if any_compiler_has_define(compilers, '__64BIT__'):
+            trial = 'ppc64'
 
     if trial not in known_cpu_families:
-        mlog.warning('Unknown CPU family {!r}, please report this at '
+        mlog.warning(f'Unknown CPU family {trial!r}, please report this at '
                      'https://github.com/mesonbuild/meson/issues/new with the '
-                     'output of `uname -a` and `cat /proc/cpuinfo`'.format(trial))
+                     'output of `uname -a` and `cat /proc/cpuinfo`')
 
     return trial
 
-def detect_cpu(compilers: CompilersDict):
+def detect_cpu(compilers: CompilersDict) -> str:
     if mesonlib.is_windows():
         trial = detect_windows_arch(compilers)
-    elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd():
+    elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_aix():
         trial = platform.processor().lower()
     else:
         trial = platform.machine().lower()
+
     if trial in ('amd64', 'x64', 'i86pc'):
         trial = 'x86_64'
     if trial == 'x86_64':
         # Same check as above for cpu_family
         if any_compiler_has_define(compilers, '__i386__'):
             trial = 'i686' # All 64 bit cpus have at least this level of x86 support.
-    elif trial == 'aarch64':
+    elif trial.startswith('aarch64'):
         # Same check as above for cpu_family
         if any_compiler_has_define(compilers, '__arm__'):
             trial = 'arm'
+        else:
+            # for aarch64_be
+            trial = 'aarch64'
     elif trial.startswith('earm'):
         trial = 'arm'
     elif trial == 'e2k':
         # Make more precise CPU detection for Elbrus platform.
         trial = platform.processor().lower()
+    elif trial.startswith('mips'):
+        if '64' not in trial:
+            trial = 'mips'
+        else:
+            trial = 'mips64'
+    elif trial == 'ppc':
+        # AIX always returns powerpc, check here for 64-bit
+        if any_compiler_has_define(compilers, '__64BIT__'):
+            trial = 'ppc64'
+
     # Add more quirks here as bugs are reported. Keep in sync with
     # detect_cpu_family() above.
     return trial
 
-def detect_system():
-    system = platform.system().lower()
-    if system.startswith('cygwin'):
+def detect_system() -> str:
+    if sys.platform == 'cygwin':
         return 'cygwin'
-    return system
+    return platform.system().lower()
 
-def detect_msys2_arch():
-    if 'MSYSTEM_CARCH' in os.environ:
-        return os.environ['MSYSTEM_CARCH']
-    return None
+def detect_msys2_arch() -> T.Optional[str]:
+    return os.environ.get('MSYSTEM_CARCH', None)
 
 def detect_machine_info(compilers: T.Optional[CompilersDict] = None) -> MachineInfo:
     """Detect the machine we're running on
@@ -428,50 +438,15 @@
     true_build_cpu_family = detect_cpu_family({})
     return \
         (machine_info.cpu_family == true_build_cpu_family) or \
-        ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86'))
-
-def search_version(text):
-    # Usually of the type 4.1.4 but compiler output may contain
-    # stuff like this:
-    # (Sourcery CodeBench Lite 2014.05-29) 4.8.3 20140320 (prerelease)
-    # Limiting major version number to two digits seems to work
-    # thus far. When we get to GCC 100, this will break, but
-    # if we are still relevant when that happens, it can be
-    # considered an achievement in itself.
-    #
-    # This regex is reaching magic levels. If it ever needs
-    # to be updated, do not complexify but convert to something
-    # saner instead.
-    # We'll demystify it a bit with a verbose definition.
-    version_regex = re.compile(r"""
-    (? None:
         self.source_dir = source_dir
         self.build_dir = build_dir
         # Do not try to create build directories when build_dir is none.
@@ -484,10 +459,15 @@
             os.makedirs(self.log_dir, exist_ok=True)
             os.makedirs(self.info_dir, exist_ok=True)
             try:
-                self.coredata = coredata.load(self.get_build_dir())
+                self.coredata = coredata.load(self.get_build_dir())  # type: coredata.CoreData
                 self.first_invocation = False
             except FileNotFoundError:
                 self.create_new_coredata(options)
+            except coredata.MesonVersionMismatchException as e:
+                # This is routine, but tell the user the update happened
+                mlog.log('Regenerating configuration from scratch:', str(e))
+                coredata.read_cmd_line_file(self.build_dir, options)
+                self.create_new_coredata(options)
             except MesonException as e:
                 # If we stored previous command line options, we can recover from
                 # a broken/outdated coredata.
@@ -508,19 +488,17 @@
         # Stores machine infos, the only *three* machine one because we have a
         # target machine info on for the user (Meson never cares about the
         # target machine.)
-        machines = PerThreeMachineDefaultable()
+        machines: PerThreeMachineDefaultable[MachineInfo] = PerThreeMachineDefaultable()
 
         # Similar to coredata.compilers, but lower level in that there is no
         # meta data, only names/paths.
-        binaries = PerMachineDefaultable()
+        binaries = PerMachineDefaultable()  # type: PerMachineDefaultable[BinaryTable]
 
         # Misc other properties about each machine.
-        properties = PerMachineDefaultable()
+        properties = PerMachineDefaultable()  # type: PerMachineDefaultable[Properties]
 
-        # Store paths for native and cross build files. There is no target
-        # machine information here because nothing is installed for the target
-        # architecture, just the build and host architectures
-        paths = PerMachineDefaultable()
+        # CMake toolchain variables
+        cmakevars = PerMachineDefaultable()  # type: PerMachineDefaultable[CMakeVariables]
 
         ## Setup build machine defaults
 
@@ -532,1138 +510,292 @@
         binaries.build = BinaryTable()
         properties.build = Properties()
 
+        # Options with the key parsed into an OptionKey type.
+        #
+        # Note that order matters because of 'buildtype', if it is after
+        # 'optimization' and 'debug' keys, it override them.
+        self.options: T.MutableMapping[OptionKey, T.Union[str, T.List[str]]] = collections.OrderedDict()
+
         ## Read in native file(s) to override build machine configuration
 
         if self.coredata.config_files is not None:
-            config = MesonConfigFile.from_config_parser(
-                coredata.load_configs(self.coredata.config_files))
+            config = coredata.parse_machine_files(self.coredata.config_files)
             binaries.build = BinaryTable(config.get('binaries', {}))
-            paths.build = Directories(**config.get('paths', {}))
+            properties.build = Properties(config.get('properties', {}))
+            cmakevars.build = CMakeVariables(config.get('cmake', {}))
+            self._load_machine_file_options(
+                config, properties.build,
+                MachineChoice.BUILD if self.coredata.cross_files else MachineChoice.HOST)
 
         ## Read in cross file(s) to override host machine configuration
 
         if self.coredata.cross_files:
-            config = MesonConfigFile.from_config_parser(
-                coredata.load_configs(self.coredata.cross_files))
-            properties.host = Properties(config.get('properties', {}), False)
-            binaries.host = BinaryTable(config.get('binaries', {}), False)
+            config = coredata.parse_machine_files(self.coredata.cross_files)
+            properties.host = Properties(config.get('properties', {}))
+            binaries.host = BinaryTable(config.get('binaries', {}))
+            cmakevars.host = CMakeVariables(config.get('cmake', {}))
             if 'host_machine' in config:
                 machines.host = MachineInfo.from_literal(config['host_machine'])
             if 'target_machine' in config:
                 machines.target = MachineInfo.from_literal(config['target_machine'])
-            paths.host = Directories(**config.get('paths', {}))
+            # Keep only per machine options from the native file. The cross
+            # file takes precedence over all other options.
+            for key, value in list(self.options.items()):
+                if self.coredata.is_per_machine_option(key):
+                    self.options[key.as_build()] = value
+            self._load_machine_file_options(config, properties.host, MachineChoice.HOST)
 
         ## "freeze" now initialized configuration, and "save" to the class.
 
         self.machines = machines.default_missing()
         self.binaries = binaries.default_missing()
         self.properties = properties.default_missing()
-        self.paths = paths.default_missing()
+        self.cmakevars = cmakevars.default_missing()
+
+        # Command line options override those from cross/native files
+        self.options.update(options.cmd_line_options)
+
+        # Take default value from env if not set in cross/native files or command line.
+        self._set_default_options_from_env()
+        self._set_default_binaries_from_env()
+        self._set_default_properties_from_env()
+
+        # Warn if the user is using two different ways of setting build-type
+        # options that override each other
+        bt = OptionKey('buildtype')
+        db = OptionKey('debug')
+        op = OptionKey('optimization')
+        if bt in self.options and (db in self.options or op in self.options):
+            mlog.warning('Recommend using either -Dbuildtype or -Doptimization + -Ddebug. '
+                         'Using both is redundant since they override each other. '
+                         'See: https://mesonbuild.com/Builtin-options.html#build-type-options')
 
-        exe_wrapper = self.binaries.host.lookup_entry('exe_wrapper')
+        exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper')
         if exe_wrapper is not None:
-            from .dependencies import ExternalProgram
-            self.exe_wrapper = ExternalProgram.from_bin_list(
-                self.binaries.host,
-                'exe_wrapper')
+            self.exe_wrapper = ExternalProgram.from_bin_list(self, MachineChoice.HOST, 'exe_wrapper')
         else:
             self.exe_wrapper = None
 
-        self.cmd_line_options = options.cmd_line_options.copy()
-
-        # List of potential compilers.
-        if mesonlib.is_windows():
-            # Intel C and C++ compiler is icl on Windows, but icc and icpc elsewhere.
-            # Search for icl before cl, since Intel "helpfully" provides a
-            # cl.exe that returns *exactly the same thing* that microsofts
-            # cl.exe does, and if icl is present, it's almost certainly what
-            # you want.
-            self.default_c = ['icl', 'cl', 'cc', 'gcc', 'clang', 'clang-cl', 'pgcc']
-            # There is currently no pgc++ for Windows, only for  Mac and Linux.
-            self.default_cpp = ['icl', 'cl', 'c++', 'g++', 'clang++', 'clang-cl']
-            self.default_fortran = ['ifort', 'gfortran', 'flang', 'pgfortran', 'g95']
-            # Clang and clang++ are valid, but currently unsupported.
-            self.default_objc = ['cc', 'gcc']
-            self.default_objcpp = ['c++', 'g++']
-            self.default_cs = ['csc', 'mcs']
-        else:
-            if platform.machine().lower() == 'e2k':
-                # There are no objc or objc++ compilers for Elbrus,
-                # and there's no clang which can build binaries for host.
-                self.default_c = ['cc', 'gcc', 'lcc']
-                self.default_cpp = ['c++', 'g++', 'l++']
-                self.default_objc = []
-                self.default_objcpp = []
-            else:
-                self.default_c = ['cc', 'gcc', 'clang', 'pgcc', 'icc']
-                self.default_cpp = ['c++', 'g++', 'clang++', 'pgc++', 'icpc']
-                self.default_objc = ['cc', 'gcc', 'clang']
-                self.default_objcpp = ['c++', 'g++', 'clang++']
-            self.default_fortran = ['gfortran', 'flang', 'pgfortran', 'ifort', 'g95']
-            self.default_cs = ['mcs', 'csc']
-        self.default_d = ['ldc2', 'ldc', 'gdc', 'dmd']
-        self.default_java = ['javac']
-        self.default_cuda = ['nvcc']
-        self.default_rust = ['rustc']
-        self.default_swift = ['swiftc']
-        self.default_vala = ['valac']
-        self.default_static_linker = ['ar', 'gar']
-        self.default_strip = ['strip']
-        self.vs_static_linker = ['lib']
-        self.clang_cl_static_linker = ['llvm-lib']
-        self.cuda_static_linker = ['nvlink']
-        self.gcc_static_linker = ['gcc-ar']
-        self.clang_static_linker = ['llvm-ar']
         self.default_cmake = ['cmake']
         self.default_pkgconfig = ['pkg-config']
+        self.wrap_resolver: T.Optional['Resolver'] = None
 
-    def create_new_coredata(self, options):
+    def _load_machine_file_options(self, config: 'ConfigParser', properties: Properties, machine: MachineChoice) -> None:
+        """Read the contents of a Machine file and put it in the options store."""
+
+        # Look for any options in the deprecated paths section, warn about
+        # those, then assign them. They will be overwritten by the ones in the
+        # "built-in options" section if they're in both sections.
+        paths = config.get('paths')
+        if paths:
+            mlog.deprecation('The [paths] section is deprecated, use the [built-in options] section instead.')
+            for k, v in paths.items():
+                self.options[OptionKey.from_string(k).evolve(machine=machine)] = v
+
+        # Next look for compiler options in the "properties" section, this is
+        # also deprecated, and these will also be overwritten by the "built-in
+        # options" section. We need to remove these from this section, as well.
+        deprecated_properties: T.Set[str] = set()
+        for lang in compilers.all_languages:
+            deprecated_properties.add(lang + '_args')
+            deprecated_properties.add(lang + '_link_args')
+        for k, v in properties.properties.copy().items():
+            if k in deprecated_properties:
+                mlog.deprecation(f'{k} in the [properties] section of the machine file is deprecated, use the [built-in options] section.')
+                self.options[OptionKey.from_string(k).evolve(machine=machine)] = v
+                del properties.properties[k]
+
+        for section, values in config.items():
+            if ':' in section:
+                subproject, section = section.split(':')
+            else:
+                subproject = ''
+            if section == 'built-in options':
+                for k, v in values.items():
+                    key = OptionKey.from_string(k)
+                    # If we're in the cross file, and there is a `build.foo` warn about that. Later we'll remove it.
+                    if machine is MachineChoice.HOST and key.machine is not machine:
+                        mlog.deprecation('Setting build machine options in cross files, please use a native file instead, this will be removed in meson 0.60', once=True)
+                    if key.subproject:
+                        raise MesonException('Do not set subproject options in [built-in options] section, use [subproject:built-in options] instead.')
+                    self.options[key.evolve(subproject=subproject, machine=machine)] = v
+            elif section == 'project options' and machine is MachineChoice.HOST:
+                # Project options are only for the host machine, we don't want
+                # to read these from the native file
+                for k, v in values.items():
+                    # Project options are always for the host machine
+                    key = OptionKey.from_string(k)
+                    if key.subproject:
+                        raise MesonException('Do not set subproject options in [built-in options] section, use [subproject:built-in options] instead.')
+                    self.options[key.evolve(subproject=subproject)] = v
+
+    def _set_default_options_from_env(self) -> None:
+        opts: T.List[T.Tuple[str, str]] = (
+            [(v, f'{k}_args') for k, v in compilers.compilers.CFLAGS_MAPPING.items()] +
+            [
+                ('PKG_CONFIG_PATH', 'pkg_config_path'),
+                ('CMAKE_PREFIX_PATH', 'cmake_prefix_path'),
+                ('LDFLAGS', 'ldflags'),
+                ('CPPFLAGS', 'cppflags'),
+            ]
+        )
+
+        env_opts: T.DefaultDict[OptionKey, T.List[str]] = collections.defaultdict(list)
+
+        for (evar, keyname), for_machine in itertools.product(opts, MachineChoice):
+            p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
+            if p_env is not None:
+                # these may contain duplicates, which must be removed, else
+                # a duplicates-in-array-option warning arises.
+                if keyname == 'cmake_prefix_path':
+                    if self.machines[for_machine].is_windows():
+                        # Cannot split on ':' on Windows because its in the drive letter
+                        _p_env = p_env.split(os.pathsep)
+                    else:
+                        # https://github.com/mesonbuild/meson/issues/7294
+                        _p_env = re.split(r':|;', p_env)
+                    p_list = list(mesonlib.OrderedSet(_p_env))
+                elif keyname == 'pkg_config_path':
+                    p_list = list(mesonlib.OrderedSet(p_env.split(':')))
+                else:
+                    p_list = split_args(p_env)
+                p_list = [e for e in p_list if e]  # filter out any empty elements
+
+                # Take env vars only on first invocation, if the env changes when
+                # reconfiguring it gets ignored.
+                # FIXME: We should remember if we took the value from env to warn
+                # if it changes on future invocations.
+                if self.first_invocation:
+                    if keyname == 'ldflags':
+                        key = OptionKey('link_args', machine=for_machine, lang='c')  # needs a language to initialize properly
+                        for lang in compilers.compilers.LANGUAGES_USING_LDFLAGS:
+                            key = key.evolve(lang=lang)
+                            env_opts[key].extend(p_list)
+                    elif keyname == 'cppflags':
+                        key = OptionKey('env_args', machine=for_machine, lang='c')
+                        for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS:
+                            key = key.evolve(lang=lang)
+                            env_opts[key].extend(p_list)
+                    else:
+                        key = OptionKey.from_string(keyname).evolve(machine=for_machine)
+                        if evar in compilers.compilers.CFLAGS_MAPPING.values():
+                            # If this is an environment variable, we have to
+                            # store it separately until the compiler is
+                            # instantiated, as we don't know whether the
+                            # compiler will want to use these arguments at link
+                            # time and compile time (instead of just at compile
+                            # time) until we're instantiating that `Compiler`
+                            # object. This is required so that passing
+                            # `-Dc_args=` on the command line and `$CFLAGS`
+                            # have subtely different behavior. `$CFLAGS` will be
+                            # added to the linker command line if the compiler
+                            # acts as a linker driver, `-Dc_args` will not.
+                            #
+                            # We still use the original key as the base here, as
+                            # we want to inhert the machine and the compiler
+                            # language
+                            key = key.evolve('env_args')
+                        env_opts[key].extend(p_list)
+
+        # Only store options that are not already in self.options,
+        # otherwise we'd override the machine files
+        for k, v in env_opts.items():
+            if k not in self.options:
+                self.options[k] = v
+
+    def _set_default_binaries_from_env(self) -> None:
+        """Set default binaries from the environment.
+
+        For example, pkg-config can be set via PKG_CONFIG, or in the machine
+        file. We want to set the default to the env variable.
+        """
+        opts = itertools.chain(envconfig.DEPRECATED_ENV_PROG_MAP.items(),
+                               envconfig.ENV_VAR_PROG_MAP.items())
+
+        for (name, evar), for_machine in itertools.product(opts, MachineChoice):
+            p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
+            if p_env is not None:
+                self.binaries[for_machine].binaries.setdefault(name, mesonlib.split_args(p_env))
+
+    def _set_default_properties_from_env(self) -> None:
+        """Properties which can also be set from the environment."""
+        # name, evar, split
+        opts: T.List[T.Tuple[str, T.List[str], bool]] = [
+            ('boost_includedir', ['BOOST_INCLUDEDIR'], False),
+            ('boost_librarydir', ['BOOST_LIBRARYDIR'], False),
+            ('boost_root', ['BOOST_ROOT', 'BOOSTROOT'], True),
+            ('java_home', ['JAVA_HOME'], False),
+        ]
+
+        for (name, evars, split), for_machine in itertools.product(opts, MachineChoice):
+            for evar in evars:
+                p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
+                if p_env is not None:
+                    if split:
+                        self.properties[for_machine].properties.setdefault(name, p_env.split(os.pathsep))
+                    else:
+                        self.properties[for_machine].properties.setdefault(name, p_env)
+                    break
+
+    def create_new_coredata(self, options: 'argparse.Namespace') -> None:
         # WARNING: Don't use any values from coredata in __init__. It gets
         # re-initialized with project options by the interpreter during
         # build file parsing.
-        self.coredata = coredata.CoreData(options, self.scratch_dir)
-        # Used by the regenchecker script, which runs meson
-        self.coredata.meson_command = mesonlib.meson_command
+        # meson_command is used by the regenchecker script, which runs meson
+        self.coredata = coredata.CoreData(options, self.scratch_dir, mesonlib.get_meson_command())
         self.first_invocation = True
 
-    def is_cross_build(self) -> bool:
-        return self.coredata.is_cross_build()
+    def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
+        return self.coredata.is_cross_build(when_building_for)
 
-    def dump_coredata(self):
+    def dump_coredata(self) -> str:
         return coredata.save(self.coredata, self.get_build_dir())
 
-    def get_script_dir(self):
-        import mesonbuild.scripts
-        return os.path.dirname(mesonbuild.scripts.__file__)
-
-    def get_log_dir(self):
+    def get_log_dir(self) -> str:
         return self.log_dir
 
-    def get_coredata(self):
+    def get_coredata(self) -> coredata.CoreData:
         return self.coredata
 
-    def get_build_command(self, unbuffered=False):
-        cmd = mesonlib.meson_command[:]
+    @staticmethod
+    def get_build_command(unbuffered: bool = False) -> T.List[str]:
+        cmd = mesonlib.get_meson_command()
+        if cmd is None:
+            raise MesonBugException('No command?')
+        cmd = cmd.copy()
         if unbuffered and 'python' in os.path.basename(cmd[0]):
             cmd.insert(1, '-u')
         return cmd
 
-    def is_header(self, fname):
+    def is_header(self, fname: 'mesonlib.FileOrString') -> bool:
         return is_header(fname)
 
-    def is_source(self, fname):
+    def is_source(self, fname: 'mesonlib.FileOrString') -> bool:
         return is_source(fname)
 
-    def is_assembly(self, fname):
+    def is_assembly(self, fname: 'mesonlib.FileOrString') -> bool:
         return is_assembly(fname)
 
-    def is_llvm_ir(self, fname):
+    def is_llvm_ir(self, fname: 'mesonlib.FileOrString') -> bool:
         return is_llvm_ir(fname)
 
-    def is_object(self, fname):
+    def is_object(self, fname: 'mesonlib.FileOrString') -> bool:
         return is_object(fname)
 
     @lru_cache(maxsize=None)
     def is_library(self, fname):
         return is_library(fname)
 
-    @staticmethod
-    def get_gnu_compiler_defines(compiler):
-        """
-        Detect GNU compiler platform type (Apple, MinGW, Unix)
-        """
-        # Arguments to output compiler pre-processor defines to stdout
-        # gcc, g++, and gfortran all support these arguments
-        args = compiler + ['-E', '-dM', '-']
-        p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE)
-        if p.returncode != 0:
-            raise EnvironmentException('Unable to detect GNU compiler type:\n' + output + error)
-        # Parse several lines of the type:
-        # `#define ___SOME_DEF some_value`
-        # and extract `___SOME_DEF`
-        defines = {}
-        for line in output.split('\n'):
-            if not line:
-                continue
-            d, *rest = line.split(' ', 2)
-            if d != '#define':
-                continue
-            if len(rest) == 1:
-                defines[rest] = True
-            if len(rest) == 2:
-                defines[rest[0]] = rest[1]
-        return defines
-
-    @staticmethod
-    def get_gnu_version_from_defines(defines):
-        dot = '.'
-        major = defines.get('__GNUC__', '0')
-        minor = defines.get('__GNUC_MINOR__', '0')
-        patch = defines.get('__GNUC_PATCHLEVEL__', '0')
-        return dot.join((major, minor, patch))
-
-    @staticmethod
-    def get_lcc_version_from_defines(defines):
-        dot = '.'
-        generation_and_major = defines.get('__LCC__', '100')
-        generation = generation_and_major[:1]
-        major = generation_and_major[1:]
-        minor = defines.get('__LCC_MINOR__', '0')
-        return dot.join((generation, major, minor))
-
-    def _get_compilers(self, lang, for_machine):
-        '''
-        The list of compilers is detected in the exact same way for
-        C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here.
-        '''
-        value = self.binaries[for_machine].lookup_entry(lang)
-        if value is not None:
-            compilers, ccache = BinaryTable.parse_entry(value)
-            # Return value has to be a list of compiler 'choices'
-            compilers = [compilers]
-        else:
-            if not self.machines.matches_build_machine(for_machine):
-                raise EnvironmentException('{!r} compiler binary not defined in cross or native file'.format(lang))
-            compilers = getattr(self, 'default_' + lang)
-            ccache = BinaryTable.detect_ccache()
-
-        if self.machines.matches_build_machine(for_machine):
-            exe_wrap = None
-        else:
-            exe_wrap = self.get_exe_wrapper()
-
-        return compilers, ccache, exe_wrap
-
-    def _handle_exceptions(self, exceptions, binaries, bintype='compiler'):
-        errmsg = 'Unknown {}(s): {}'.format(bintype, binaries)
-        if exceptions:
-            errmsg += '\nThe follow exceptions were encountered:'
-            for (c, e) in exceptions.items():
-                errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e)
-        raise EnvironmentException(errmsg)
-
-    def _guess_win_linker(self, compiler: T.List[str], comp_class: Compiler,
-                          for_machine: MachineChoice, *,
-                          use_linker_prefix: bool = True) -> 'DynamicLinker':
-        self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
-
-        # Explicitly pass logo here so that we can get the version of link.exe
-        if not use_linker_prefix or comp_class.LINKER_PREFIX is None:
-            check_args = ['/logo', '--version']
-        elif isinstance(comp_class.LINKER_PREFIX, str):
-            check_args = [comp_class.LINKER_PREFIX + '/logo', comp_class.LINKER_PREFIX + '--version']
-        elif isinstance(comp_class.LINKER_PREFIX, list):
-            check_args = comp_class.LINKER_PREFIX + ['/logo'] + comp_class.LINKER_PREFIX + ['--version']
-
-        check_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value
+    def lookup_binary_entry(self, for_machine: MachineChoice, name: str) -> T.Optional[T.List[str]]:
+        return self.binaries[for_machine].lookup_entry(name)
 
-        override = []  # type: T.List[str]
-        value = self.binaries[for_machine].lookup_entry(comp_class.language + '_ld')
-        if value is not None:
-            override = comp_class.use_linker_args(value[0])
-            check_args += override
-
-        p, o, _ = Popen_safe(compiler + check_args)
-        if o.startswith('LLD'):
-            if '(compatible with GNU linkers)' in o:
-                return LLVMDynamicLinker(
-                    compiler, for_machine, comp_class.LINKER_PREFIX,
-                    override, version=search_version(o))
-
-        if value is not None:
-            compiler = value
-
-        p, o, e = Popen_safe(compiler + check_args)
-        if o.startswith('LLD'):
-            return ClangClDynamicLinker(
-                for_machine, [],
-                prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
-                exelist=compiler, version=search_version(o))
-        elif 'OPTLINK' in o:
-            # Opltink's stdout *may* beging with a \r character.
-            return OptlinkDynamicLinker(for_machine, version=search_version(o))
-        elif o.startswith('Microsoft') or e.startswith('Microsoft'):
-            out = o or e
-            match = re.search(r'.*(X86|X64|ARM|ARM64).*', out)
-            if match:
-                target = str(match.group(1))
-            else:
-                target = 'x86'
-
-            return MSVCDynamicLinker(
-                for_machine, [], machine=target, exelist=compiler,
-                prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
-                version=search_version(out))
-        elif 'GNU coreutils' in o:
-            raise EnvironmentException(
-                "Found GNU link.exe instead of MSVC link.exe. This link.exe "
-                "is not a linker. You may need to reorder entries to your "
-                "%PATH% variable to resolve this.")
-        raise EnvironmentException('Unable to determine dynamic linker')
-
-    def _guess_nix_linker(self, compiler: T.List[str], comp_class: T.Type[Compiler],
-                          for_machine: MachineChoice, *,
-                          extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
-        """Helper for guessing what linker to use on Unix-Like OSes.
-
-        :compiler: Invocation to use to get linker
-        :comp_class: The Compiler Type (uninstantiated)
-        :for_machine: which machine this linker targets
-        :extra_args: Any additional arguments required (such as a source file)
-        """
-        self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
-        extra_args = T.cast(T.List[str], extra_args or [])
-        extra_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value
-
-        if isinstance(comp_class.LINKER_PREFIX, str):
-            check_args = [comp_class.LINKER_PREFIX + '--version'] + extra_args
-        else:
-            check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args
-
-        override = []  # type: T.List[str]
-        value = self.binaries[for_machine].lookup_entry(comp_class.language + '_ld')
-        if value is not None:
-            override = comp_class.use_linker_args(value[0])
-            check_args += override
-
-        _, o, e = Popen_safe(compiler + check_args)
-        v = search_version(o)
-        if o.startswith('LLD'):
-            linker = LLVMDynamicLinker(
-                compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)  # type: DynamicLinker
-        elif e.startswith('lld-link: '):
-            # Toolchain wrapper got in the way; this happens with e.g. https://github.com/mstorsjo/llvm-mingw
-            # Let's try to extract the linker invocation command to grab the version.
-
-            _, o, e = Popen_safe(compiler + check_args + ['-v'])
-
-            try:
-                linker_cmd = re.match(r'.*\n(.*?)\nlld-link: ', e, re.DOTALL).group(1)
-                linker_cmd = shlex.split(linker_cmd)[0]
-            except (AttributeError, IndexError, ValueError):
-                pass
-            else:
-                _, o, e = Popen_safe([linker_cmd, '--version'])
-                v = search_version(o)
-
-            linker = LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
-        # first is for apple clang, second is for real gcc, the third is icc
-        elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e:
-            if isinstance(comp_class.LINKER_PREFIX, str):
-                _, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args)
-            else:
-                _, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args)
-            for line in e.split('\n'):
-                if 'PROJECT:ld' in line:
-                    v = line.split('-')[1]
-                    break
-            else:
-                v = 'unknown version'
-            linker = AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
-        elif 'GNU' in o:
-            if 'gold' in o:
-                cls = GnuGoldDynamicLinker
-            else:
-                cls = GnuBFDDynamicLinker
-            linker = cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
-        elif 'Solaris' in e or 'Solaris' in o:
-            linker = SolarisDynamicLinker(
-                compiler, for_machine, comp_class.LINKER_PREFIX, override,
-                version=search_version(e))
-        else:
-            raise EnvironmentException('Unable to determine dynamic linker')
-        return linker
-
-    def _detect_c_or_cpp_compiler(self, lang: str, for_machine: MachineChoice) -> Compiler:
-        popen_exceptions = {}
-        compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine)
-        is_cross = not self.machines.matches_build_machine(for_machine)
-        info = self.machines[for_machine]
-
-        for compiler in compilers:
-            if isinstance(compiler, str):
-                compiler = [compiler]
-            compiler_name = os.path.basename(compiler[0])
-
-            if not set(['cl', 'cl.exe', 'clang-cl', 'clang-cl.exe']).isdisjoint(compiler):
-                # Watcom C provides it's own cl.exe clone that mimics an older
-                # version of Microsoft's compiler. Since Watcom's cl.exe is
-                # just a wrapper, we skip using it if we detect its presence
-                # so as not to confuse Meson when configuring for MSVC.
-                #
-                # Additionally the help text of Watcom's cl.exe is paged, and
-                # the binary will not exit without human intervention. In
-                # practice, Meson will block waiting for Watcom's cl.exe to
-                # exit, which requires user input and thus will never exit.
-                if 'WATCOM' in os.environ:
-                    def sanitize(p):
-                        return os.path.normcase(os.path.abspath(p))
-
-                    watcom_cls = [sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl')),
-                                  sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl.exe'))]
-                    found_cl = sanitize(shutil.which('cl'))
-                    if found_cl in watcom_cls:
-                        continue
-                arg = '/?'
-            elif 'armcc' in compiler_name:
-                arg = '--vsn'
-            elif 'ccrx' in compiler_name:
-                arg = '-v'
-            elif 'icl' in compiler_name:
-                # if you pass anything to icl you get stuck in a pager
-                arg = ''
-            else:
-                arg = '--version'
-
-            try:
-                p, out, err = Popen_safe(compiler + [arg])
-            except OSError as e:
-                popen_exceptions[' '.join(compiler + [arg])] = e
-                continue
-
-            if 'ccrx' in compiler_name:
-                out = err
-
-            full_version = out.split('\n', 1)[0]
-            version = search_version(out)
-
-            guess_gcc_or_lcc = False
-            if 'Free Software Foundation' in out or 'xt-' in out:
-                guess_gcc_or_lcc = 'gcc'
-            if 'e2k' in out and 'lcc' in out:
-                guess_gcc_or_lcc = 'lcc'
-
-            if guess_gcc_or_lcc:
-                defines = self.get_gnu_compiler_defines(compiler)
-                if not defines:
-                    popen_exceptions[' '.join(compiler)] = 'no pre-processor defines'
-                    continue
-
-                if guess_gcc_or_lcc == 'lcc':
-                    version = self.get_lcc_version_from_defines(defines)
-                    cls = ElbrusCCompiler if lang == 'c' else ElbrusCPPCompiler
-                else:
-                    version = self.get_gnu_version_from_defines(defines)
-                    cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
-
-                linker = self._guess_nix_linker(compiler, cls, for_machine)
-
-                return cls(
-                    ccache + compiler, version, for_machine, is_cross,
-                    info, exe_wrap, defines, full_version=full_version,
-                    linker=linker)
-
-            if 'Emscripten' in out:
-                cls = EmscriptenCCompiler if lang == 'c' else EmscriptenCPPCompiler
-                self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-                return cls(
-                    ccache + compiler, version, for_machine, is_cross, info,
-                    exe_wrap, full_version=full_version)
-
-            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:'.
-                # So, searching for the 'Component' in out although we know it is
-                # present in second line, as we are not sure about the
-                # output format in future versions
-                arm_ver_str = re.search('.*Component.*', out)
-                if arm_ver_str is None:
-                    popen_exceptions[' '.join(compiler)] = 'version string not found'
-                    continue
-                arm_ver_str = arm_ver_str.group(0)
-                # Override previous values
-                version = search_version(arm_ver_str)
-                full_version = arm_ver_str
-                cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler
-                linker = ArmClangDynamicLinker(for_machine, version=version)
-                self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-                return cls(
-                    ccache + compiler, version, for_machine, is_cross, info,
-                    exe_wrap, full_version=full_version, linker=linker)
-            if 'CL.EXE COMPATIBILITY' in out:
-                # if this is clang-cl masquerading as cl, detect it as cl, not
-                # clang
-                arg = '--version'
-                try:
-                    p, out, err = Popen_safe(compiler + [arg])
-                except OSError as e:
-                    popen_exceptions[' '.join(compiler + [arg])] = e
-                version = search_version(out)
-                match = re.search('^Target: (.*?)-', out, re.MULTILINE)
-                if match:
-                    target = match.group(1)
-                else:
-                    target = 'unknown target'
-                cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler
-                linker = self._guess_win_linker(['lld-link'], cls, for_machine)
-                return cls(
-                    compiler, version, for_machine, is_cross, info, exe_wrap,
-                    target, linker=linker)
-            if 'clang' in out:
-                linker = None
-
-                # Even if the for_machine is darwin, we could be using vanilla
-                # clang.
-                if 'Apple' in out:
-                    cls = AppleClangCCompiler if lang == 'c' else AppleClangCPPCompiler
-                else:
-                    cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler
-
-                if 'windows' in out or self.machines[for_machine].is_windows():
-                    # If we're in a MINGW context this actually will use a gnu
-                    # style ld, but for clang on "real" windows we'll use
-                    # either link.exe or lld-link.exe
-                    try:
-                        linker = self._guess_win_linker(compiler, cls, for_machine)
-                    except MesonException:
-                        pass
-                if linker is None:
-                    linker = self._guess_nix_linker(compiler, cls, for_machine)
-
-                return cls(
-                    ccache + compiler, version, for_machine, is_cross, info,
-                    exe_wrap, full_version=full_version, linker=linker)
-
-            if 'Intel(R) C++ Intel(R)' in err:
-                version = search_version(err)
-                target = 'x86' if 'IA-32' in err else 'x86_64'
-                cls = IntelClCCompiler if lang == 'c' else IntelClCPPCompiler
-                self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-                linker = XilinkDynamicLinker(for_machine, [], version=version)
-                return cls(
-                    compiler, version, for_machine, is_cross, info=info,
-                    exe_wrap=exe_wrap, target=target, linker=linker)
-            if 'Microsoft' in out or 'Microsoft' in err:
-                # Latest versions of Visual Studio print version
-                # number to stderr but earlier ones print version
-                # on stdout.  Why? Lord only knows.
-                # Check both outputs to figure out version.
-                for lookat in [err, out]:
-                    version = search_version(lookat)
-                    if version != 'unknown version':
-                        break
-                else:
-                    m = 'Failed to detect MSVC compiler version: stderr was\n{!r}'
-                    raise EnvironmentException(m.format(err))
-                cl_signature = lookat.split('\n')[0]
-                match = re.search('.*(x86|x64|ARM|ARM64)$', cl_signature)
-                if match:
-                    target = match.group(1)
-                else:
-                    m = 'Failed to detect MSVC compiler target architecture: \'cl /?\' output is\n{}'
-                    raise EnvironmentException(m.format(cl_signature))
-                cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler
-                linker = self._guess_win_linker(['link'], cls, for_machine)
-                return cls(
-                    compiler, version, for_machine, is_cross, info, exe_wrap,
-                    target, linker=linker)
-            if 'PGI Compilers' in out:
-                cls = PGICCompiler if lang == 'c' else PGICPPCompiler
-                self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-                linker = PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version)
-                return cls(
-                    ccache + compiler, version, for_machine, is_cross,
-                    info, exe_wrap, linker=linker)
-            if '(ICC)' in out:
-                cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler
-                l = self._guess_nix_linker(compiler, cls, for_machine)
-                return cls(
-                    ccache + compiler, version, for_machine, is_cross, info,
-                    exe_wrap, full_version=full_version, linker=l)
-            if 'ARM' in out:
-                cls = ArmCCompiler if lang == 'c' else ArmCPPCompiler
-                self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-                linker = ArmDynamicLinker(for_machine, version=version)
-                return cls(
-                    ccache + compiler, version, for_machine, is_cross,
-                    info, exe_wrap, full_version=full_version, linker=linker)
-            if 'RX Family' in out:
-                cls = CcrxCCompiler if lang == 'c' else CcrxCPPCompiler
-                self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-                linker = CcrxDynamicLinker(for_machine, version=version)
-                return cls(
-                    ccache + compiler, version, for_machine, is_cross, info,
-                    exe_wrap, full_version=full_version, linker=linker)
-
-        self._handle_exceptions(popen_exceptions, compilers)
-
-    def detect_c_compiler(self, for_machine):
-        return self._detect_c_or_cpp_compiler('c', for_machine)
-
-    def detect_cpp_compiler(self, for_machine):
-        return self._detect_c_or_cpp_compiler('cpp', for_machine)
-
-    def detect_cuda_compiler(self, for_machine):
-        popen_exceptions = {}
-        is_cross = not self.machines.matches_build_machine(for_machine)
-        compilers, ccache, exe_wrap = self._get_compilers('cuda', for_machine)
-        info = self.machines[for_machine]
-        for compiler in compilers:
-            if isinstance(compiler, str):
-                compiler = [compiler]
-            else:
-                raise EnvironmentException()
-            arg = '--version'
-            try:
-                p, out, err = Popen_safe(compiler + [arg])
-            except OSError as e:
-                popen_exceptions[' '.join(compiler + [arg])] = e
-                continue
-            # Example nvcc printout:
-            #
-            #     nvcc: NVIDIA (R) Cuda compiler driver
-            #     Copyright (c) 2005-2018 NVIDIA Corporation
-            #     Built on Sat_Aug_25_21:08:01_CDT_2018
-            #     Cuda compilation tools, release 10.0, V10.0.130
-            #
-            # search_version() first finds the "10.0" after "release",
-            # rather than the more precise "10.0.130" after "V".
-            # The patch version number is occasionally important; For
-            # instance, on Linux,
-            #    - CUDA Toolkit 8.0.44 requires NVIDIA Driver 367.48
-            #    - CUDA Toolkit 8.0.61 requires NVIDIA Driver 375.26
-            # Luckily, the "V" also makes it very simple to extract
-            # the full version:
-            version = out.strip().split('V')[-1]
-            cpp_compiler = self.detect_cpp_compiler(for_machine)
-            cls = CudaCompiler
-            self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-            linker = CudaLinker(compiler, for_machine, 'nvlink', CudaCompiler.LINKER_PREFIX, [], version=CudaLinker.parse_version())
-            return cls(ccache + compiler, version, for_machine, is_cross, exe_wrap, host_compiler=cpp_compiler, info=info, linker=linker)
-        raise EnvironmentException('Could not find suitable CUDA compiler: "' + ' '.join(compilers) + '"')
-
-    def detect_fortran_compiler(self, for_machine: MachineChoice):
-        popen_exceptions = {}
-        compilers, ccache, exe_wrap = self._get_compilers('fortran', for_machine)
-        is_cross = not self.machines.matches_build_machine(for_machine)
-        info = self.machines[for_machine]
-        for compiler in compilers:
-            if isinstance(compiler, str):
-                compiler = [compiler]
-            for arg in ['--version', '-V']:
-                try:
-                    p, out, err = Popen_safe(compiler + [arg])
-                except OSError as e:
-                    popen_exceptions[' '.join(compiler + [arg])] = e
-                    continue
-
-                version = search_version(out)
-                full_version = out.split('\n', 1)[0]
-
-                guess_gcc_or_lcc = False
-                if 'GNU Fortran' in out:
-                    guess_gcc_or_lcc = 'gcc'
-                if 'e2k' in out and 'lcc' in out:
-                    guess_gcc_or_lcc = 'lcc'
-
-                if guess_gcc_or_lcc:
-                    defines = self.get_gnu_compiler_defines(compiler)
-                    if not defines:
-                        popen_exceptions[' '.join(compiler)] = 'no pre-processor defines'
-                        continue
-                    if guess_gcc_or_lcc == 'lcc':
-                        version = self.get_lcc_version_from_defines(defines)
-                        cls = ElbrusFortranCompiler
-                    else:
-                        version = self.get_gnu_version_from_defines(defines)
-                        cls = GnuFortranCompiler
-                    linker = self._guess_nix_linker(
-                        compiler, cls, for_machine)
-                    return cls(
-                        compiler, version, for_machine, is_cross, info,
-                        exe_wrap, defines, full_version=full_version,
-                        linker=linker)
-
-                if 'G95' in out:
-                    linker = self._guess_nix_linker(
-                        compiler, cls, for_machine)
-                    return G95FortranCompiler(
-                        compiler, version, for_machine, is_cross, info,
-                        exe_wrap, full_version=full_version, linker=linker)
-
-                if 'Sun Fortran' in err:
-                    version = search_version(err)
-                    linker = self._guess_nix_linker(
-                        compiler, cls, for_machine)
-                    return SunFortranCompiler(
-                        compiler, version, for_machine, is_cross, info,
-                        exe_wrap, full_version=full_version, linker=linker)
-
-                if 'Intel(R) Visual Fortran' in err:
-                    version = search_version(err)
-                    target = 'x86' if 'IA-32' in err else 'x86_64'
-                    cls = IntelClFortranCompiler
-                    self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-                    linker = XilinkDynamicLinker(for_machine, [], version=version)
-                    return cls(
-                        compiler, version, for_machine, is_cross, target,
-                        info, exe_wrap, linker=linker)
-
-                if 'ifort (IFORT)' in out:
-                    linker = self._guess_nix_linker(compiler, IntelFortranCompiler, for_machine)
-                    return IntelFortranCompiler(
-                        compiler, version, for_machine, is_cross, info,
-                        exe_wrap, full_version=full_version, linker=linker)
-
-                if 'PathScale EKOPath(tm)' in err:
-                    return PathScaleFortranCompiler(
-                        compiler, version, for_machine, is_cross, info,
-                        exe_wrap, full_version=full_version)
-
-                if 'PGI Compilers' in out:
-                    cls = PGIFortranCompiler
-                    self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-                    linker = PGIDynamicLinker(compiler, for_machine,
-                                              cls.LINKER_PREFIX, [], version=version)
-                    return cls(
-                        compiler, version, for_machine, is_cross, info, exe_wrap,
-                        full_version=full_version, linker=linker)
-
-                if 'flang' in out or 'clang' in out:
-                    linker = self._guess_nix_linker(
-                        compiler, FlangFortranCompiler, for_machine)
-                    return FlangFortranCompiler(
-                        compiler, version, for_machine, is_cross, info,
-                        exe_wrap, full_version=full_version, linker=linker)
-
-                if 'Open64 Compiler Suite' in err:
-                    linker = self._guess_nix_linker(
-                        compiler, Open64FortranCompiler, for_machine)
-                    return Open64FortranCompiler(
-                        compiler, version, for_machine, is_cross, info,
-                        exe_wrap, full_version=full_version, linker=linker)
-
-                if 'NAG Fortran' in err:
-                    linker = self._guess_nix_linker(
-                        compiler, NAGFortranCompiler, for_machine)
-                    return NAGFortranCompiler(
-                        compiler, version, for_machine, is_cross, info,
-                        exe_wrap, full_version=full_version, linker=linker)
-
-        self._handle_exceptions(popen_exceptions, compilers)
-
-    def get_scratch_dir(self):
+    def get_scratch_dir(self) -> str:
         return self.scratch_dir
 
-    def detect_objc_compiler(self, for_machine: MachineInfo) -> 'Compiler':
-        return self._detect_objc_or_objcpp_compiler(for_machine, True)
-
-    def detect_objcpp_compiler(self, for_machine: MachineInfo) -> 'Compiler':
-        return self._detect_objc_or_objcpp_compiler(for_machine, False)
-
-    def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool) -> 'Compiler':
-        popen_exceptions = {}
-        compilers, ccache, exe_wrap = self._get_compilers('objc' if objc else 'objcpp', for_machine)
-        is_cross = not self.machines.matches_build_machine(for_machine)
-        info = self.machines[for_machine]
-
-        for compiler in compilers:
-            if isinstance(compiler, str):
-                compiler = [compiler]
-            arg = ['--version']
-            try:
-                p, out, err = Popen_safe(compiler + arg)
-            except OSError as e:
-                popen_exceptions[' '.join(compiler + arg)] = e
-                continue
-            version = search_version(out)
-            if 'Free Software Foundation' in out:
-                defines = self.get_gnu_compiler_defines(compiler)
-                if not defines:
-                    popen_exceptions[' '.join(compiler)] = 'no pre-processor defines'
-                    continue
-                version = self.get_gnu_version_from_defines(defines)
-                comp = GnuObjCCompiler if objc else GnuObjCPPCompiler
-                linker = self._guess_nix_linker(compiler, comp, for_machine)
-                return comp(
-                    ccache + compiler, version, for_machine, is_cross, info,
-                    exe_wrap, defines, linker=linker)
-            if 'clang' in out:
-                linker = None
-                comp = ClangObjCCompiler if objc else ClangObjCPPCompiler
-                if 'windows' in out or self.machines[for_machine].is_windows():
-                    # If we're in a MINGW context this actually will use a gnu style ld
-                    try:
-                        linker = self._guess_win_linker(compiler, comp, for_machine)
-                    except MesonException:
-                        pass
-
-                if not linker:
-                    linker = self._guess_nix_linker(
-                        compiler, comp, for_machine)
-                return comp(
-                    ccache + compiler, version, for_machine,
-                    is_cross, info, exe_wrap, linker=linker)
-        self._handle_exceptions(popen_exceptions, compilers)
-
-    def detect_java_compiler(self, for_machine):
-        exelist = self.binaries.host.lookup_entry('java')
-        info = self.machines[for_machine]
-        if exelist is None:
-            # TODO support fallback
-            exelist = [self.default_java[0]]
-
-        try:
-            p, out, err = Popen_safe(exelist + ['-version'])
-        except OSError:
-            raise EnvironmentException('Could not execute Java compiler "%s"' % ' '.join(exelist))
-        if 'javac' in out or 'javac' in err:
-            version = search_version(err if 'javac' in err else out)
-            if not version or version == 'unknown version':
-                parts = (err if 'javac' in err else out).split()
-                if len(parts) > 1:
-                    version = parts[1]
-            comp_class = JavaCompiler
-            self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
-            return comp_class(exelist, version, for_machine, info)
-        raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
-    def detect_cs_compiler(self, for_machine):
-        compilers, ccache, exe_wrap = self._get_compilers('cs', for_machine)
-        popen_exceptions = {}
-        info = self.machines[for_machine]
-        for comp in compilers:
-            if not isinstance(comp, list):
-                comp = [comp]
-            try:
-                p, out, err = Popen_safe(comp + ['--version'])
-            except OSError as e:
-                popen_exceptions[' '.join(comp + ['--version'])] = e
-                continue
-
-            version = search_version(out)
-            if 'Mono' in out:
-                cls = MonoCompiler
-            elif "Visual C#" in out:
-                cls = VisualStudioCsCompiler
-            self.coredata.add_lang_args(cls.language, cls, for_machine, self)
-            return cls(comp, version, for_machine, info)
-
-        self._handle_exceptions(popen_exceptions, compilers)
-
-    def detect_vala_compiler(self, for_machine):
-        exelist = self.binaries.host.lookup_entry('vala')
-        is_cross = not self.machines.matches_build_machine(for_machine)
-        info = self.machines[for_machine]
-        if exelist is None:
-            # TODO support fallback
-            exelist = [self.default_vala[0]]
-
-        try:
-            p, out = Popen_safe(exelist + ['--version'])[0:2]
-        except OSError:
-            raise EnvironmentException('Could not execute Vala compiler "%s"' % ' '.join(exelist))
-        version = search_version(out)
-        if 'Vala' in out:
-            comp_class = ValaCompiler
-            self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
-            return comp_class(exelist, version, for_machine, info, is_cross)
-        raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
-    def detect_rust_compiler(self, for_machine):
-        popen_exceptions = {}
-        compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine)
-        is_cross = not self.machines.matches_build_machine(for_machine)
-        info = self.machines[for_machine]
-
-        cc = self.detect_c_compiler(for_machine)
-        is_link_exe = isinstance(cc.linker, VisualStudioLikeLinkerMixin)
-        override = self.binaries[for_machine].lookup_entry('rust_ld')
-
-        for compiler in compilers:
-            if isinstance(compiler, str):
-                compiler = [compiler]
-            arg = ['--version']
-            try:
-                p, out = Popen_safe(compiler + arg)[0:2]
-            except OSError as e:
-                popen_exceptions[' '.join(compiler + arg)] = e
-                continue
-
-            version = search_version(out)
-
-            if 'rustc' in out:
-                # On Linux and mac rustc will invoke gcc (clang for mac
-                # presumably) and it can do this windows, for dynamic linking.
-                # this means the easiest way to C compiler for dynamic linking.
-                # figure out what linker to use is to just get the value of the
-                # C compiler and use that as the basis of the rust linker.
-                # However, there are two things we need to change, if CC is not
-                # the default use that, and second add the necessary arguments
-                # to rust to use -fuse-ld
-
-                if override is None:
-                    extra_args = {}
-                    always_args = []
-                    if is_link_exe:
-                        compiler.extend(['-C', 'linker={}'.format(cc.linker.exelist[0])])
-                        extra_args['direct'] = True
-                        extra_args['machine'] = cc.linker.machine
-                    elif not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or
-                              isinstance(cc, GnuCCompiler)):
-                        c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0]
-                        compiler.extend(['-C', 'linker={}'.format(c)])
-
-                    # This trickery with type() gets us the class of the linker
-                    # so we can initialize a new copy for the Rust Compiler
-                    if is_link_exe:
-                        linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist,
-                                                 version=cc.linker.version, **extra_args)
-                    else:
-                        linker = type(cc.linker)(compiler, for_machine, cc.LINKER_PREFIX,
-                                                 always_args=always_args, version=cc.linker.version,
-                                                 **extra_args)
-                elif 'link' in override[0]:
-                    linker = self._guess_win_linker(
-                        override, RustCompiler, for_machine, use_linker_prefix=False)
-                    linker.direct = True
-                else:
-                    # We're creating a new type of "C" compiler, that has rust
-                    # as it's language. This is gross, but I can't figure out
-                    # another way to handle this, because rustc is actually
-                    # invoking the c compiler as it's linker.
-                    b = type('b', (type(cc), ), {})
-                    b.language = RustCompiler.language
-                    linker = self._guess_nix_linker(cc.exelist, b, for_machine)
-
-                    # Of course, we're not going to use any of that, we just
-                    # need it to get the proper arguments to pass to rustc
-                    c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0]
-                    compiler.extend(['-C', 'linker={}'.format(c)])
-                    compiler.extend(['-C', 'link-args={}'.format(' '.join(cc.use_linker_args(override[0])))])
-
-                self.coredata.add_lang_args(RustCompiler.language, RustCompiler, for_machine, self)
-                return RustCompiler(
-                    compiler, version, for_machine, is_cross, info, exe_wrap,
-                    linker=linker)
-
-        self._handle_exceptions(popen_exceptions, compilers)
-
-    def detect_d_compiler(self, for_machine: MachineChoice):
-        info = self.machines[for_machine]
-
-        # Detect the target architecture, required for proper architecture handling on Windows.
-        # MSVC compiler is required for correct platform detection.
-        c_compiler = {'c': self.detect_c_compiler(for_machine)}
-        is_msvc = isinstance(c_compiler['c'], VisualStudioCCompiler)
-        if not is_msvc:
-            c_compiler = {}
-
-        arch = detect_cpu_family(c_compiler)
-        if is_msvc and arch == 'x86':
-            arch = 'x86_mscoff'
-
-        popen_exceptions = {}
-        is_cross = not self.machines.matches_build_machine(for_machine)
-        results, ccache, exe_wrap = self._get_compilers('d', for_machine)
-        for exelist in results:
-            # Search for a D compiler.
-            # We prefer LDC over GDC unless overridden with the DC
-            # environment variable because LDC has a much more
-            # up to date language version at time (2016).
-            if not isinstance(exelist, list):
-                exelist = [exelist]
-            if os.path.basename(exelist[-1]).startswith(('ldmd', 'gdmd')):
-                raise EnvironmentException(
-                    'Meson does not support {} as it is only a DMD frontend for another compiler.'
-                    'Please provide a valid value for DC or unset it so that Meson can resolve the compiler by itself.'.format(exelist[-1]))
-            try:
-                p, out = Popen_safe(exelist + ['--version'])[0:2]
-            except OSError as e:
-                popen_exceptions[' '.join(exelist + ['--version'])] = e
-                continue
-            version = search_version(out)
-            full_version = out.split('\n', 1)[0]
-
-            if 'LLVM D compiler' in out:
-                # LDC seems to require a file
-                if info.is_windows() or info.is_cygwin():
-                    # Getting LDC on windows to give useful linker output when
-                    # not doing real work is painfully hard. It ships with a
-                    # version of lld-link, so unless we think the user wants
-                    # link.exe, just assume that we're going to use lld-link
-                    # with it.
-                    linker = self._guess_win_linker(
-                        ['link' if is_msvc else 'lld-link'],
-                        compilers.LLVMDCompiler, for_machine, use_linker_prefix=False)
-                else:
-                    with tempfile.NamedTemporaryFile(suffix='.d') as f:
-                        # LDC writes an object file to the current working directory.
-                        # Clean it up.
-                        objectfile = os.path.basename(f.name)[:-1] + 'o'
-                        linker = self._guess_nix_linker(
-                            exelist, compilers.LLVMDCompiler, for_machine,
-                            extra_args=[f.name])
-                        try:
-                            os.unlink(objectfile)
-                        except Exception:
-                            # Thank you Windows file system semantics and virus scanners.
-                            pass
-                return compilers.LLVMDCompiler(
-                    exelist, version, for_machine, info, arch,
-                    full_version=full_version, linker=linker)
-            elif 'gdc' in out:
-                linker = self._guess_nix_linker(exelist, compilers.GnuDCompiler, for_machine)
-                return compilers.GnuDCompiler(
-                    exelist, version, for_machine, info, arch, is_cross, exe_wrap,
-                    full_version=full_version, linker=linker)
-            elif 'The D Language Foundation' in out or 'Digital Mars' in out:
-                # DMD seems to require a file
-                if info.is_windows() or info.is_cygwin():
-                    if is_msvc:
-                        linker_cmd = ['link']
-                    elif arch == 'x86':
-                        linker_cmd = ['optlink']
-                    else:
-                        linker_cmd = ['lld-link']
-                    linker = self._guess_win_linker(linker_cmd, compilers.DmdDCompiler, for_machine,
-                                                    use_linker_prefix=False)
-                else:
-                    with tempfile.NamedTemporaryFile(suffix='.d') as f:
-                        linker = self._guess_nix_linker(
-                            exelist, compilers.DmdDCompiler, for_machine,
-                            extra_args=[f.name])
-                return compilers.DmdDCompiler(
-                    exelist, version, for_machine, info, arch,
-                    full_version=full_version, linker=linker)
-            raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
-        self._handle_exceptions(popen_exceptions, compilers)
-
-    def detect_swift_compiler(self, for_machine):
-        exelist = self.binaries.host.lookup_entry('swift')
-        is_cross = not self.machines.matches_build_machine(for_machine)
-        info = self.machines[for_machine]
-        if exelist is None:
-            # TODO support fallback
-            exelist = [self.default_swift[0]]
-
-        try:
-            p, _, err = Popen_safe(exelist + ['-v'])
-        except OSError:
-            raise EnvironmentException('Could not execute Swift compiler "%s"' % ' '.join(exelist))
-        version = search_version(err)
-        if 'Swift' in err:
-            # As for 5.0.1 swiftc *requires* a file to check the linker:
-            with tempfile.NamedTemporaryFile(suffix='.swift') as f:
-                linker = self._guess_nix_linker(
-                    exelist, compilers.SwiftCompiler, for_machine,
-                    extra_args=[f.name])
-            return compilers.SwiftCompiler(
-                exelist, version, for_machine, info, is_cross, linker=linker)
-
-        raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
-    def compiler_from_language(self, lang: str, for_machine: MachineChoice):
-        if lang == 'c':
-            comp = self.detect_c_compiler(for_machine)
-        elif lang == 'cpp':
-            comp = self.detect_cpp_compiler(for_machine)
-        elif lang == 'objc':
-            comp = self.detect_objc_compiler(for_machine)
-        elif lang == 'cuda':
-            comp = self.detect_cuda_compiler(for_machine)
-        elif lang == 'objcpp':
-            comp = self.detect_objcpp_compiler(for_machine)
-        elif lang == 'java':
-            comp = self.detect_java_compiler(for_machine)
-        elif lang == 'cs':
-            comp = self.detect_cs_compiler(for_machine)
-        elif lang == 'vala':
-            comp = self.detect_vala_compiler(for_machine)
-        elif lang == 'd':
-            comp = self.detect_d_compiler(for_machine)
-        elif lang == 'rust':
-            comp = self.detect_rust_compiler(for_machine)
-        elif lang == 'fortran':
-            comp = self.detect_fortran_compiler(for_machine)
-        elif lang == 'swift':
-            comp = self.detect_swift_compiler(for_machine)
-        else:
-            comp = None
-        return comp
-
-    def detect_compiler_for(self, lang: str, for_machine: MachineChoice):
-        comp = self.compiler_from_language(lang, for_machine)
-        if comp is not None:
-            assert comp.for_machine == for_machine
-            self.coredata.process_new_compiler(lang, comp, self)
-        return comp
-
-    def detect_static_linker(self, compiler):
-        linker = self.binaries[compiler.for_machine].lookup_entry('ar')
-        if linker is not None:
-            linkers = [linker]
-        else:
-            evar = 'AR'
-            defaults = [[l] for l in self.default_static_linker]
-            if isinstance(compiler, compilers.CudaCompiler):
-                linkers = [self.cuda_static_linker] + defaults
-            elif evar in os.environ:
-                linkers = [split_args(os.environ[evar])]
-            elif isinstance(compiler, compilers.VisualStudioLikeCompiler):
-                linkers = [self.vs_static_linker, self.clang_cl_static_linker]
-            elif isinstance(compiler, compilers.GnuCompiler):
-                # Use gcc-ar if available; needed for LTO
-                linkers = [self.gcc_static_linker] + defaults
-            elif isinstance(compiler, compilers.ClangCompiler):
-                # Use llvm-ar if available; needed for LTO
-                linkers = [self.clang_static_linker] + defaults
-            elif isinstance(compiler, compilers.DCompiler):
-                # Prefer static linkers over linkers used by D compilers
-                if mesonlib.is_windows():
-                    linkers = [self.vs_static_linker, self.clang_cl_static_linker, compiler.get_linker_exelist()]
-                else:
-                    linkers = defaults
-            elif isinstance(compiler, IntelClCCompiler):
-                # Intel has it's own linker that acts like microsoft's lib
-                linkers = ['xilib']
-            elif isinstance(compiler, (PGICCompiler, PGIFortranCompiler)) and mesonlib.is_windows():
-                linkers = [['ar']]  # For PGI on Windows, "ar" is just a wrapper calling link/lib.
-            else:
-                linkers = defaults
-        popen_exceptions = {}
-        for linker in linkers:
-            if not {'lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe', 'xilib', 'xilib.exe'}.isdisjoint(linker):
-                arg = '/?'
-            else:
-                arg = '--version'
-            try:
-                p, out, err = Popen_safe(linker + [arg])
-            except OSError as e:
-                popen_exceptions[' '.join(linker + [arg])] = e
-                continue
-            if "xilib: executing 'lib'" in err:
-                return IntelVisualStudioLinker(linker, getattr(compiler, 'machine', None))
-            if '/OUT:' in out.upper() or '/OUT:' in err.upper():
-                return VisualStudioLinker(linker, getattr(compiler, 'machine', None))
-            if 'ar-Error-Unknown switch: --version' in err:
-                return PGIStaticLinker(linker)
-            if p.returncode == 0 and ('armar' in linker or 'armar.exe' in linker):
-                return ArmarLinker(linker)
-            if 'DMD32 D Compiler' in out or 'DMD64 D Compiler' in out:
-                return DLinker(linker, compiler.arch)
-            if 'LDC - the LLVM D compiler' in out:
-                return DLinker(linker, compiler.arch)
-            if 'GDC' in out and ' based on D ' in out:
-                return DLinker(linker, compiler.arch)
-            if err.startswith('Renesas') and ('rlink' in linker or 'rlink.exe' in linker):
-                return CcrxLinker(linker)
-            if p.returncode == 0:
-                return ArLinker(linker)
-            if p.returncode == 1 and err.startswith('usage'): # OSX
-                return ArLinker(linker)
-            if p.returncode == 1 and err.startswith('Usage'): # AIX
-                return ArLinker(linker)
-            if p.returncode == 1 and err.startswith('ar: bad option: --'): # Solaris
-                return ArLinker(linker)
-        self._handle_exceptions(popen_exceptions, linkers, 'linker')
-        raise EnvironmentException('Unknown static linker "%s"' % ' '.join(linkers))
-
-    def get_source_dir(self):
+    def get_source_dir(self) -> str:
         return self.source_dir
 
-    def get_build_dir(self):
+    def get_build_dir(self) -> str:
         return self.build_dir
 
     def get_import_lib_dir(self) -> str:
@@ -1687,25 +819,25 @@
         return self.get_libdir()
 
     def get_prefix(self) -> str:
-        return self.coredata.get_builtin_option('prefix')
+        return self.coredata.get_option(OptionKey('prefix'))
 
     def get_libdir(self) -> str:
-        return self.coredata.get_builtin_option('libdir')
+        return self.coredata.get_option(OptionKey('libdir'))
 
     def get_libexecdir(self) -> str:
-        return self.coredata.get_builtin_option('libexecdir')
+        return self.coredata.get_option(OptionKey('libexecdir'))
 
     def get_bindir(self) -> str:
-        return self.coredata.get_builtin_option('bindir')
+        return self.coredata.get_option(OptionKey('bindir'))
 
     def get_includedir(self) -> str:
-        return self.coredata.get_builtin_option('includedir')
+        return self.coredata.get_option(OptionKey('includedir'))
 
     def get_mandir(self) -> str:
-        return self.coredata.get_builtin_option('mandir')
+        return self.coredata.get_option(OptionKey('mandir'))
 
     def get_datadir(self) -> str:
-        return self.coredata.get_builtin_option('datadir')
+        return self.coredata.get_option(OptionKey('datadir'))
 
     def get_compiler_system_dirs(self, for_machine: MachineChoice):
         for comp in self.coredata.compilers[for_machine].values():
@@ -1732,8 +864,7 @@
             return value
         return not machine_info_can_run(self.machines[for_machine])
 
-    def get_exe_wrapper(self):
+    def get_exe_wrapper(self) -> ExternalProgram:
         if not self.need_exe_wrapper():
-            from .dependencies import EmptyExternalProgram
             return EmptyExternalProgram()
         return self.exe_wrapper
diff -Nru meson-0.53.2/mesonbuild/interpreter/compiler.py meson-0.61.2/mesonbuild/interpreter/compiler.py
--- meson-0.53.2/mesonbuild/interpreter/compiler.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/compiler.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,745 @@
+# SPDX-Licnese-Identifier: Apache-2.0
+# Copyright 2012-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+import enum
+import functools
+import typing as T
+
+from .. import build
+from .. import coredata
+from .. import dependencies
+from .. import mesonlib
+from .. import mlog
+from ..compilers import SUFFIX_TO_LANG
+from ..compilers.compilers import CompileCheckMode
+from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs,
+                               FeatureNew, disablerIfNotFound,
+                               InterpreterException)
+from ..interpreterbase.decorators import ContainerTypeInfo, typed_kwargs, KwargInfo, typed_pos_args
+from .interpreterobjects import (extract_required_kwarg, extract_search_dirs)
+from .type_checking import REQUIRED_KW, in_set_validator, NoneType
+
+if T.TYPE_CHECKING:
+    from ..interpreter import Interpreter
+    from ..compilers import Compiler, RunResult
+    from ..interpreterbase import TYPE_var, TYPE_kwargs
+    from .kwargs import ExtractRequired, ExtractSearchDirs
+
+    from typing_extensions import TypedDict, Literal
+
+    class GetSupportedArgumentKw(TypedDict):
+
+        checked: Literal['warn', 'require', 'off']
+
+    class AlignmentKw(TypedDict):
+
+        prefix: str
+        args: T.List[str]
+        dependencies: T.List[dependencies.Dependency]
+
+    class CompileKW(TypedDict):
+
+        name: str
+        no_builtin_args: bool
+        include_directories: T.List[build.IncludeDirs]
+        args: T.List[str]
+        dependencies: T.List[dependencies.Dependency]
+
+    class CommonKW(TypedDict):
+
+        prefix: str
+        no_builtin_args: bool
+        include_directories: T.List[build.IncludeDirs]
+        args: T.List[str]
+        dependencies: T.List[dependencies.Dependency]
+
+    class CompupteIntKW(CommonKW):
+
+        guess: T.Optional[int]
+        high: T.Optional[int]
+        low: T.Optional[int]
+
+    class HeaderKW(CommonKW, ExtractRequired):
+        pass
+
+    class FindLibraryKW(ExtractRequired, ExtractSearchDirs):
+
+        disabler: bool
+        has_headers: T.List[str]
+        static: bool
+
+        # This list must be all of the `HeaderKW` values with `header_`
+        # prepended to the key
+        header_args: T.List[str]
+        header_dependencies: T.List[dependencies.Dependency]
+        header_include_directories: T.List[build.IncludeDirs]
+        header_no_builtin_args: bool
+        header_prefix: str
+        header_required: T.Union[bool, coredata.UserFeatureOption]
+
+
+class _TestMode(enum.Enum):
+
+    """Whether we're doing a compiler or linker check."""
+
+    COMPILER = 0
+    LINKER = 1
+
+
+class TryRunResultHolder(ObjectHolder['RunResult']):
+    def __init__(self, res: 'RunResult', interpreter: 'Interpreter'):
+        super().__init__(res, interpreter)
+        self.methods.update({'returncode': self.returncode_method,
+                             'compiled': self.compiled_method,
+                             'stdout': self.stdout_method,
+                             'stderr': self.stderr_method,
+                             })
+
+    @noPosargs
+    @noKwargs
+    def returncode_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> int:
+        return self.held_object.returncode
+
+    @noPosargs
+    @noKwargs
+    def compiled_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        return self.held_object.compiled
+
+    @noPosargs
+    @noKwargs
+    def stdout_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.held_object.stdout
+
+    @noPosargs
+    @noKwargs
+    def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.held_object.stderr
+
+
+_ARGS_KW: KwargInfo[T.List[str]] = KwargInfo(
+    'args',
+    ContainerTypeInfo(list, str),
+    listify=True,
+    default=[],
+)
+_DEPENDENCIES_KW: KwargInfo[T.List['dependencies.Dependency']] = KwargInfo(
+    'dependencies',
+    ContainerTypeInfo(list, dependencies.Dependency),
+    listify=True,
+    default=[],
+)
+_INCLUDE_DIRS_KW: KwargInfo[T.List[build.IncludeDirs]] = KwargInfo(
+    'include_directories',
+    ContainerTypeInfo(list, build.IncludeDirs),
+    default=[],
+    listify=True,
+)
+_PREFIX_KW = KwargInfo('prefix', str, default='')
+_NO_BUILTIN_ARGS_KW = KwargInfo('no_builtin_args', bool, default=False)
+_NAME_KW = KwargInfo('name', str, default='')
+
+# Many of the compiler methods take this kwarg signature exactly, this allows
+# simplifying the `typed_kwargs` calls
+_COMMON_KWS: T.List[KwargInfo] = [_ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _PREFIX_KW, _NO_BUILTIN_ARGS_KW]
+
+# Common methods of compiles, links, runs, and similar
+_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW]
+
+_HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS]
+
+class CompilerHolder(ObjectHolder['Compiler']):
+    def __init__(self, compiler: 'Compiler', interpreter: 'Interpreter'):
+        super().__init__(compiler, interpreter)
+        self.environment = self.env
+        self.methods.update({'compiles': self.compiles_method,
+                             'links': self.links_method,
+                             'get_id': self.get_id_method,
+                             'get_linker_id': self.get_linker_id_method,
+                             'compute_int': self.compute_int_method,
+                             'sizeof': self.sizeof_method,
+                             'get_define': self.get_define_method,
+                             'check_header': self.check_header_method,
+                             'has_header': self.has_header_method,
+                             'has_header_symbol': self.has_header_symbol_method,
+                             'run': self.run_method,
+                             'has_function': self.has_function_method,
+                             'has_member': self.has_member_method,
+                             'has_members': self.has_members_method,
+                             'has_type': self.has_type_method,
+                             'alignment': self.alignment_method,
+                             'version': self.version_method,
+                             'cmd_array': self.cmd_array_method,
+                             'find_library': self.find_library_method,
+                             'has_argument': self.has_argument_method,
+                             'has_function_attribute': self.has_func_attribute_method,
+                             'get_supported_function_attributes': self.get_supported_function_attributes_method,
+                             'has_multi_arguments': self.has_multi_arguments_method,
+                             'get_supported_arguments': self.get_supported_arguments_method,
+                             'first_supported_argument': self.first_supported_argument_method,
+                             'has_link_argument': self.has_link_argument_method,
+                             'has_multi_link_arguments': self.has_multi_link_arguments_method,
+                             'get_supported_link_arguments': self.get_supported_link_arguments_method,
+                             'first_supported_link_argument': self.first_supported_link_argument_method,
+                             'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method,
+                             'get_argument_syntax': self.get_argument_syntax_method,
+                             })
+
+    @property
+    def compiler(self) -> 'Compiler':
+        return self.held_object
+
+    def _dep_msg(self, deps: T.List['dependencies.Dependency'], endl: str) -> str:
+        msg_single = 'with dependency {}'
+        msg_many = 'with dependencies {}'
+        if not deps:
+            return endl
+        if endl is None:
+            endl = ''
+        names = []
+        for d in deps:
+            if isinstance(d, dependencies.InternalDependency):
+                FeatureNew.single_use('compiler method "dependencies" kwarg with internal dep', '0.57.0', self.subproject,
+                                      location=self.current_node)
+                continue
+            if isinstance(d, dependencies.ExternalLibrary):
+                name = '-l' + d.name
+            else:
+                name = d.name
+            names.append(name)
+        if not names:
+            return None
+        tpl = msg_many if len(names) > 1 else msg_single
+        return tpl.format(', '.join(names)) + endl
+
+    @noPosargs
+    @noKwargs
+    def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.compiler.version
+
+    @noPosargs
+    @noKwargs
+    def cmd_array_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]:
+        return self.compiler.exelist
+
+    def _determine_args(self, nobuiltins: bool,
+                       incdirs: T.List[build.IncludeDirs],
+                       extra_args: T.List[str],
+                       mode: CompileCheckMode = CompileCheckMode.LINK) -> T.List[str]:
+        args: T.List[str] = []
+        for i in incdirs:
+            for idir in i.to_string_list(self.environment.get_source_dir()):
+                args.extend(self.compiler.get_include_args(idir, False))
+        if not nobuiltins:
+            opts = self.environment.coredata.options
+            args += self.compiler.get_option_compile_args(opts)
+            if mode is CompileCheckMode.LINK:
+                args.extend(self.compiler.get_option_link_args(opts))
+        args.extend(extra_args)
+        return args
+
+    def _determine_dependencies(self, deps: T.List['dependencies.Dependency'], endl: str = ':') -> T.Tuple[T.List['dependencies.Dependency'], str]:
+        if deps:
+            final_deps = []
+            while deps:
+                next_deps = []
+                for d in mesonlib.listify(deps):
+                    if not isinstance(d, dependencies.Dependency) or d.is_built():
+                        raise InterpreterException('Dependencies must be external dependencies')
+                    final_deps.append(d)
+                    next_deps.extend(d.ext_deps)
+                deps = next_deps
+            deps = final_deps
+        else:
+            # Ensure that we always return a new instance
+            deps = deps.copy()
+        return deps, self._dep_msg(deps, endl)
+
+    @typed_pos_args('compiler.alignment', str)
+    @typed_kwargs(
+        'compiler.alignment',
+        _PREFIX_KW,
+        _ARGS_KW,
+        _DEPENDENCIES_KW,
+    )
+    def alignment_method(self, args: T.Tuple[str], kwargs: 'AlignmentKw') -> int:
+        typename = args[0]
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        result = self.compiler.alignment(typename, kwargs['prefix'], self.environment,
+                                         extra_args=kwargs['args'],
+                                         dependencies=deps)
+        mlog.log('Checking for alignment of', mlog.bold(typename, True), msg, result)
+        return result
+
+    @typed_pos_args('compiler.run', (str, mesonlib.File))
+    @typed_kwargs('compiler.run', *_COMPILES_KWS)
+    def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> 'RunResult':
+        code = args[0]
+        if isinstance(code, mesonlib.File):
+            self.interpreter.add_build_def_file(code)
+            code = mesonlib.File.from_absolute_file(
+                code.rel_to_builddir(self.environment.source_dir))
+        testname = kwargs['name']
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None)
+        result = self.compiler.run(code, self.environment, extra_args=extra_args,
+                                   dependencies=deps)
+        if testname:
+            if not result.compiled:
+                h = mlog.red('DID NOT COMPILE')
+            elif result.returncode == 0:
+                h = mlog.green('YES')
+            else:
+                h = mlog.red(f'NO ({result.returncode})')
+            mlog.log('Checking if', mlog.bold(testname, True), msg, 'runs:', h)
+        return result
+
+    @noPosargs
+    @noKwargs
+    def get_id_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.compiler.get_id()
+
+    @noPosargs
+    @noKwargs
+    @FeatureNew('compiler.get_linker_id', '0.53.0')
+    def get_linker_id_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.compiler.get_linker_id()
+
+    @noPosargs
+    @noKwargs
+    def symbols_have_underscore_prefix_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        '''
+        Check if the compiler prefixes _ (underscore) to global C symbols
+        See: https://en.wikipedia.org/wiki/Name_mangling#C
+        '''
+        return self.compiler.symbols_have_underscore_prefix(self.environment)
+
+    @typed_pos_args('compiler.has_member', str, str)
+    @typed_kwargs('compiler.has_member', *_COMMON_KWS)
+    def has_member_method(self, args: T.Tuple[str, str], kwargs: 'CommonKW') -> bool:
+        typename, membername = args
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        had, cached = self.compiler.has_members(typename, [membername], kwargs['prefix'],
+                                                self.environment,
+                                                extra_args=extra_args,
+                                                dependencies=deps)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        if had:
+            hadtxt = mlog.green('YES')
+        else:
+            hadtxt = mlog.red('NO')
+        mlog.log('Checking whether type', mlog.bold(typename, True),
+                 'has member', mlog.bold(membername, True), msg, hadtxt, cached_msg)
+        return had
+
+    @typed_pos_args('compiler.has_members', str, varargs=str, min_varargs=1)
+    @typed_kwargs('compiler.has_members', *_COMMON_KWS)
+    def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'CommonKW') -> bool:
+        typename, membernames = args
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        had, cached = self.compiler.has_members(typename, membernames, kwargs['prefix'],
+                                                self.environment,
+                                                extra_args=extra_args,
+                                                dependencies=deps)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        if had:
+            hadtxt = mlog.green('YES')
+        else:
+            hadtxt = mlog.red('NO')
+        members = mlog.bold(', '.join([f'"{m}"' for m in membernames]))
+        mlog.log('Checking whether type', mlog.bold(typename, True),
+                 'has members', members, msg, hadtxt, cached_msg)
+        return had
+
+    @typed_pos_args('compiler.has_function', str)
+    @typed_kwargs('compiler.has_function', *_COMMON_KWS)
+    def has_function_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool:
+        funcname = args[0]
+        extra_args = self._determine_args(kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        had, cached = self.compiler.has_function(funcname, kwargs['prefix'], self.environment,
+                                                 extra_args=extra_args,
+                                                 dependencies=deps)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        if had:
+            hadtxt = mlog.green('YES')
+        else:
+            hadtxt = mlog.red('NO')
+        mlog.log('Checking for function', mlog.bold(funcname, True), msg, hadtxt, cached_msg)
+        return had
+
+    @typed_pos_args('compiler.has_type', str)
+    @typed_kwargs('compiler.has_type', *_COMMON_KWS)
+    def has_type_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool:
+        typename = args[0]
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        had, cached = self.compiler.has_type(typename, kwargs['prefix'], self.environment,
+                                             extra_args=extra_args, dependencies=deps)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        if had:
+            hadtxt = mlog.green('YES')
+        else:
+            hadtxt = mlog.red('NO')
+        mlog.log('Checking for type', mlog.bold(typename, True), msg, hadtxt, cached_msg)
+        return had
+
+    @FeatureNew('compiler.compute_int', '0.40.0')
+    @typed_pos_args('compiler.compute_int', str)
+    @typed_kwargs(
+        'compiler.compute_int',
+        KwargInfo('low', (int, NoneType)),
+        KwargInfo('high', (int, NoneType)),
+        KwargInfo('guess', (int, NoneType)),
+        *_COMMON_KWS,
+    )
+    def compute_int_method(self, args: T.Tuple[str], kwargs: 'CompupteIntKW') -> int:
+        expression = args[0]
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        res = self.compiler.compute_int(expression, kwargs['low'], kwargs['high'],
+                                        kwargs['guess'], kwargs['prefix'],
+                                        self.environment, extra_args=extra_args,
+                                        dependencies=deps)
+        mlog.log('Computing int of', mlog.bold(expression, True), msg, res)
+        return res
+
+    @typed_pos_args('compiler.sizeof', str)
+    @typed_kwargs('compiler.sizeof', *_COMMON_KWS)
+    def sizeof_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> int:
+        element = args[0]
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        esize = self.compiler.sizeof(element, kwargs['prefix'], self.environment,
+                                     extra_args=extra_args, dependencies=deps)
+        mlog.log('Checking for size of', mlog.bold(element, True), msg, esize)
+        return esize
+
+    @FeatureNew('compiler.get_define', '0.40.0')
+    @typed_pos_args('compiler.get_define', str)
+    @typed_kwargs('compiler.get_define', *_COMMON_KWS)
+    def get_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> str:
+        element = args[0]
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        value, cached = self.compiler.get_define(element, kwargs['prefix'], self.environment,
+                                                 extra_args=extra_args,
+                                                 dependencies=deps)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        mlog.log('Fetching value of define', mlog.bold(element, True), msg, value, cached_msg)
+        return value
+
+    @typed_pos_args('compiler.compiles', (str, mesonlib.File))
+    @typed_kwargs('compiler.compiles', *_COMPILES_KWS)
+    def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
+        code = args[0]
+        if isinstance(code, mesonlib.File):
+            self.interpreter.add_build_def_file(code)
+            code = mesonlib.File.from_absolute_file(
+                code.rel_to_builddir(self.environment.source_dir))
+        testname = kwargs['name']
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None)
+        result, cached = self.compiler.compiles(code, self.environment,
+                                                extra_args=extra_args,
+                                                dependencies=deps)
+        if testname:
+            if result:
+                h = mlog.green('YES')
+            else:
+                h = mlog.red('NO')
+            cached_msg = mlog.blue('(cached)') if cached else ''
+            mlog.log('Checking if', mlog.bold(testname, True), msg, 'compiles:', h, cached_msg)
+        return result
+
+    @typed_pos_args('compiler.links', (str, mesonlib.File))
+    @typed_kwargs('compiler.links', *_COMPILES_KWS)
+    def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
+        code = args[0]
+        compiler = None
+        if isinstance(code, mesonlib.File):
+            self.interpreter.add_build_def_file(code)
+            code = mesonlib.File.from_absolute_file(
+                code.rel_to_builddir(self.environment.source_dir))
+            suffix = code.suffix
+            if suffix not in self.compiler.file_suffixes:
+                for_machine = self.compiler.for_machine
+                clist = self.interpreter.coredata.compilers[for_machine]
+                if suffix not in SUFFIX_TO_LANG:
+                    # just pass it to the compiler driver
+                    mlog.warning(f'Unknown suffix for test file {code}')
+                elif SUFFIX_TO_LANG[suffix] not in clist:
+                    mlog.warning(f'Passed {SUFFIX_TO_LANG[suffix]} source to links method, not specified for {for_machine.get_lower_case_name()} machine.')
+                else:
+                    compiler = clist[SUFFIX_TO_LANG[suffix]]
+
+        testname = kwargs['name']
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        result, cached = self.compiler.links(code, self.environment,
+                                             compiler=compiler,
+                                             extra_args=extra_args,
+                                             dependencies=deps)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        if testname:
+            if result:
+                h = mlog.green('YES')
+            else:
+                h = mlog.red('NO')
+            mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h, cached_msg)
+        return result
+
+    @FeatureNew('compiler.check_header', '0.47.0')
+    @typed_pos_args('compiler.check_header', str)
+    @typed_kwargs('compiler.check_header', *_HEADER_KWS)
+    def check_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool:
+        hname = args[0]
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+        if disabled:
+            mlog.log('Check usable header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled')
+            return False
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        haz, cached = self.compiler.check_header(hname, kwargs['prefix'], self.environment,
+                                                 extra_args=extra_args,
+                                                 dependencies=deps)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        if required and not haz:
+            raise InterpreterException(f'{self.compiler.get_display_language()} header {hname!r} not usable')
+        elif haz:
+            h = mlog.green('YES')
+        else:
+            h = mlog.red('NO')
+        mlog.log('Check usable header', mlog.bold(hname, True), msg, h, cached_msg)
+        return haz
+
+    def _has_header_impl(self, hname: str, kwargs: 'HeaderKW') -> bool:
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+        if disabled:
+            mlog.log('Has header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled')
+            return False
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        haz, cached = self.compiler.has_header(hname, kwargs['prefix'], self.environment,
+                                               extra_args=extra_args, dependencies=deps)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        if required and not haz:
+            raise InterpreterException(f'{self.compiler.get_display_language()} header {hname!r} not found')
+        elif haz:
+            h = mlog.green('YES')
+        else:
+            h = mlog.red('NO')
+        mlog.log('Has header', mlog.bold(hname, True), msg, h, cached_msg)
+        return haz
+
+    @typed_pos_args('compiler.has_header', str)
+    @typed_kwargs('compiler.has_header', *_HEADER_KWS)
+    def has_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool:
+        return self._has_header_impl(args[0], kwargs)
+
+    @typed_pos_args('compiler.has_header_symbol', str, str)
+    @typed_kwargs('compiler.has_header_symbol', *_HEADER_KWS)
+    def has_header_symbol_method(self, args: T.Tuple[str, str], kwargs: 'HeaderKW') -> bool:
+        hname, symbol = args
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+        if disabled:
+            mlog.log(f'Header <{hname}> has symbol', mlog.bold(symbol, True), 'skipped: feature', mlog.bold(feature), 'disabled')
+            return False
+        extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
+        deps, msg = self._determine_dependencies(kwargs['dependencies'])
+        haz, cached = self.compiler.has_header_symbol(hname, symbol, kwargs['prefix'], self.environment,
+                                                      extra_args=extra_args,
+                                                      dependencies=deps)
+        if required and not haz:
+            raise InterpreterException(f'{self.compiler.get_display_language()} symbol {symbol} not found in header {hname}')
+        elif haz:
+            h = mlog.green('YES')
+        else:
+            h = mlog.red('NO')
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        mlog.log(f'Header <{hname}> has symbol', mlog.bold(symbol, True), msg, h, cached_msg)
+        return haz
+
+    def notfound_library(self, libname: str) -> 'dependencies.ExternalLibrary':
+        lib = dependencies.ExternalLibrary(libname, None,
+                                           self.environment,
+                                           self.compiler.language,
+                                           silent=True)
+        return lib
+
+    @disablerIfNotFound
+    @typed_pos_args('compiler.find_library', str)
+    @typed_kwargs(
+        'compiler.find_library',
+        KwargInfo('required', (bool, coredata.UserFeatureOption), default=True),
+        KwargInfo('has_headers', ContainerTypeInfo(list, str), listify=True, default=[], since='0.50.0'),
+        KwargInfo('static', (bool, NoneType), since='0.51.0'),
+        KwargInfo('disabler', bool, default=False, since='0.49.0'),
+        KwargInfo('dirs', ContainerTypeInfo(list, str), listify=True, default=[]),
+        *(k.evolve(name=f'header_{k.name}') for k in _HEADER_KWS)
+    )
+    def find_library_method(self, args: T.Tuple[str], kwargs: 'FindLibraryKW') -> 'dependencies.ExternalLibrary':
+        # TODO add dependencies support?
+        libname = args[0]
+
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
+        if disabled:
+            mlog.log('Library', mlog.bold(libname), 'skipped: feature', mlog.bold(feature), 'disabled')
+            return self.notfound_library(libname)
+
+        # This could be done with a comprehension, but that confuses the type
+        # checker, and having it check this seems valuable
+        has_header_kwargs: 'HeaderKW' = {
+            'required': required,
+            'args': kwargs['header_args'],
+            'dependencies': kwargs['header_dependencies'],
+            'include_directories': kwargs['header_include_directories'],
+            'prefix': kwargs['header_prefix'],
+            'no_builtin_args': kwargs['header_no_builtin_args'],
+        }
+        for h in kwargs['has_headers']:
+            if not self._has_header_impl(h, has_header_kwargs):
+                return self.notfound_library(libname)
+
+        search_dirs = extract_search_dirs(kwargs)
+
+        if kwargs['static'] is True:
+            libtype = mesonlib.LibType.STATIC
+        elif kwargs['static'] is False:
+            libtype = mesonlib.LibType.SHARED
+        else:
+            libtype = mesonlib.LibType.PREFER_SHARED
+        linkargs = self.compiler.find_library(libname, self.environment, search_dirs, libtype)
+        if required and not linkargs:
+            if libtype == mesonlib.LibType.PREFER_SHARED:
+                libtype_s = 'shared or static'
+            else:
+                libtype_s = libtype.name.lower()
+            raise InterpreterException('{} {} library {!r} not found'
+                                       .format(self.compiler.get_display_language(),
+                                               libtype_s, libname))
+        lib = dependencies.ExternalLibrary(libname, linkargs, self.environment,
+                                           self.compiler.language)
+        return lib
+
+    def _has_argument_impl(self, arguments: T.Union[str, T.List[str]],
+                           mode: _TestMode = _TestMode.COMPILER) -> bool:
+        """Shared implementation for methods checking compiler and linker arguments."""
+        # This simplifies the callers
+        if isinstance(arguments, str):
+            arguments = [arguments]
+        test = self.compiler.has_multi_link_arguments if mode is _TestMode.LINKER else self.compiler.has_multi_arguments
+        result, cached = test(arguments, self.environment)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        mlog.log(
+            'Compiler for',
+            self.compiler.get_display_language(),
+            'supports{}'.format(' link' if mode is _TestMode.LINKER else ''),
+            'arguments {}:'.format(' '.join(arguments)),
+            mlog.green('YES') if result else mlog.red('NO'),
+            cached_msg)
+        return result
+
+    @noKwargs
+    @typed_pos_args('compiler.has_argument', str)
+    def has_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
+        return self._has_argument_impl([args[0]])
+
+    @noKwargs
+    @typed_pos_args('compiler.has_multi_arguments', varargs=str)
+    @FeatureNew('compiler.has_multi_arguments', '0.37.0')
+    def has_multi_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool:
+        return self._has_argument_impl(args[0])
+
+    @FeatureNew('compiler.get_supported_arguments', '0.43.0')
+    @typed_pos_args('compiler.get_supported_arguments', varargs=str)
+    @typed_kwargs(
+        'compiler.get_supported_arguments',
+        KwargInfo('checked', str, default='off', since='0.59.0',
+                  validator=in_set_validator({'warn', 'require', 'off'})),
+    )
+    def get_supported_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'GetSupportedArgumentKw') -> T.List[str]:
+        supported_args: T.List[str] = []
+        checked = kwargs['checked']
+
+        for arg in args[0]:
+            if not self._has_argument_impl([arg]):
+                msg = f'Compiler for {self.compiler.get_display_language()} does not support "{arg}"'
+                if checked == 'warn':
+                    mlog.warning(msg)
+                elif checked == 'require':
+                    raise mesonlib.MesonException(msg)
+            else:
+                supported_args.append(arg)
+        return supported_args
+
+    @noKwargs
+    @typed_pos_args('compiler.first_supported_argument', varargs=str)
+    def first_supported_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
+        for arg in args[0]:
+            if self._has_argument_impl([arg]):
+                mlog.log('First supported argument:', mlog.bold(arg))
+                return [arg]
+        mlog.log('First supported argument:', mlog.red('None'))
+        return []
+
+    @FeatureNew('compiler.has_link_argument', '0.46.0')
+    @noKwargs
+    @typed_pos_args('compiler.has_link_argument', str)
+    def has_link_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
+        return self._has_argument_impl([args[0]], mode=_TestMode.LINKER)
+
+    @FeatureNew('compiler.has_multi_link_argument', '0.46.0')
+    @noKwargs
+    @typed_pos_args('compiler.has_multi_link_argument', varargs=str)
+    def has_multi_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool:
+        return self._has_argument_impl(args[0], mode=_TestMode.LINKER)
+
+    @FeatureNew('compiler.get_supported_link_arguments', '0.46.0')
+    @noKwargs
+    @typed_pos_args('compiler.get_supported_link_arguments', varargs=str)
+    def get_supported_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
+        supported_args: T.List[str] = []
+        for arg in args[0]:
+            if self._has_argument_impl([arg], mode=_TestMode.LINKER):
+                supported_args.append(arg)
+        return supported_args
+
+    @FeatureNew('compiler.first_supported_link_argument_method', '0.46.0')
+    @noKwargs
+    @typed_pos_args('compiler.first_supported_link_argument', varargs=str)
+    def first_supported_link_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
+        for arg in args[0]:
+            if self._has_argument_impl([arg], mode=_TestMode.LINKER):
+                mlog.log('First supported link argument:', mlog.bold(arg))
+                return [arg]
+        mlog.log('First supported link argument:', mlog.red('None'))
+        return []
+
+    def _has_function_attribute_impl(self, attr: str) -> bool:
+        """Common helper for function attribute testing."""
+        result, cached = self.compiler.has_func_attribute(attr, self.environment)
+        cached_msg = mlog.blue('(cached)') if cached else ''
+        h = mlog.green('YES') if result else mlog.red('NO')
+        mlog.log(f'Compiler for {self.compiler.get_display_language()} supports function attribute {attr}:', h, cached_msg)
+        return result
+
+    @FeatureNew('compiler.has_function_attribute', '0.48.0')
+    @noKwargs
+    @typed_pos_args('compiler.has_function_attribute', str)
+    def has_func_attribute_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
+        return self._has_function_attribute_impl(args[0])
+
+    @FeatureNew('compiler.get_supported_function_attributes', '0.48.0')
+    @noKwargs
+    @typed_pos_args('compiler.get_supported_function_attributes', varargs=str)
+    def get_supported_function_attributes_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
+        return [a for a in args[0] if self._has_function_attribute_impl(a)]
+
+    @FeatureNew('compiler.get_argument_syntax_method', '0.49.0')
+    @noPosargs
+    @noKwargs
+    def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.compiler.get_argument_syntax()
diff -Nru meson-0.53.2/mesonbuild/interpreter/dependencyfallbacks.py meson-0.61.2/mesonbuild/interpreter/dependencyfallbacks.py
--- meson-0.53.2/mesonbuild/interpreter/dependencyfallbacks.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/dependencyfallbacks.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,366 @@
+from .interpreterobjects import SubprojectHolder, extract_required_kwarg
+
+from .. import mlog
+from .. import dependencies
+from .. import build
+from ..wrap import WrapMode
+from ..mesonlib import OptionKey, extract_as_list, stringlistify, version_compare_many
+from ..dependencies import Dependency, DependencyException, NotFoundDependency
+from ..interpreterbase import (MesonInterpreterObject, FeatureNew,
+                               InterpreterException, InvalidArguments,
+                               TYPE_nkwargs, TYPE_nvar)
+
+import typing as T
+if T.TYPE_CHECKING:
+    from .interpreter import Interpreter
+
+
+class DependencyFallbacksHolder(MesonInterpreterObject):
+    def __init__(self, interpreter: 'Interpreter', names: T.List[str], allow_fallback: T.Optional[bool] = None,
+                 default_options: T.Optional[T.List[str]] = None) -> None:
+        super().__init__(subproject=interpreter.subproject)
+        self.interpreter = interpreter
+        self.subproject = interpreter.subproject
+        self.coredata = interpreter.coredata
+        self.build = interpreter.build
+        self.environment = interpreter.environment
+        self.wrap_resolver = interpreter.environment.wrap_resolver
+        self.allow_fallback = allow_fallback
+        self.subproject_name = None
+        self.subproject_varname = None
+        self.subproject_kwargs = {'default_options': default_options or []}
+        self.names: T.List[str] = []
+        for name in names:
+            if not name:
+                raise InterpreterException('dependency_fallbacks empty name \'\' is not allowed')
+            if '<' in name or '>' in name or '=' in name:
+                raise InvalidArguments('Characters <, > and = are forbidden in dependency names. To specify'
+                                       'version\n requirements use the \'version\' keyword argument instead.')
+            if name in self.names:
+                raise InterpreterException('dependency_fallbacks name {name!r} is duplicated')
+            self.names.append(name)
+
+    def set_fallback(self, fbinfo: T.Optional[T.Union[T.List[str], str]]) -> None:
+        # Legacy: This converts dependency()'s fallback kwargs.
+        if fbinfo is None:
+            return
+        if self.allow_fallback is not None:
+            raise InvalidArguments('"fallback" and "allow_fallback" arguments are mutually exclusive')
+        fbinfo = stringlistify(fbinfo)
+        if len(fbinfo) == 0:
+            # dependency('foo', fallback: []) is the same as dependency('foo', allow_fallback: false)
+            self.allow_fallback = False
+            return
+        if len(fbinfo) == 1:
+            FeatureNew.single_use('Fallback without variable name', '0.53.0', self.subproject)
+            subp_name, varname = fbinfo[0], None
+        elif len(fbinfo) == 2:
+            subp_name, varname = fbinfo
+        else:
+            raise InterpreterException('Fallback info must have one or two items.')
+        self._subproject_impl(subp_name, varname)
+
+    def _subproject_impl(self, subp_name: str, varname: str) -> None:
+        if not varname:
+            # If no variable name is specified, check if the wrap file has one.
+            # If the wrap file has a variable name, better use it because the
+            # subproject most probably is not using meson.override_dependency().
+            for name in self.names:
+                varname = self.wrap_resolver.get_varname(subp_name, name)
+                if varname:
+                    break
+        assert self.subproject_name is None
+        self.subproject_name = subp_name
+        self.subproject_varname = varname
+
+    def _do_dependency_cache(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
+        name = func_args[0]
+        cached_dep = self._get_cached_dep(name, kwargs)
+        if cached_dep:
+            self._verify_fallback_consistency(cached_dep)
+        return cached_dep
+
+    def _do_dependency(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
+        # Note that there is no df.dependency() method, this is called for names
+        # given as positional arguments to dependency_fallbacks(name1, ...).
+        # We use kwargs from the dependency() function, for things like version,
+        # module, etc.
+        name = func_args[0]
+        self._handle_featurenew_dependencies(name)
+        dep = dependencies.find_external_dependency(name, self.environment, kwargs)
+        if dep.found():
+            for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
+            identifier = dependencies.get_dep_identifier(name, kwargs)
+            self.coredata.deps[for_machine].put(identifier, dep)
+            return dep
+        return None
+
+    def _do_existing_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
+        subp_name = func_args[0]
+        varname = self.subproject_varname
+        if subp_name and self._get_subproject(subp_name):
+            return self._get_subproject_dep(subp_name, varname, kwargs)
+        return None
+
+    def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
+        if self.forcefallback:
+            mlog.log('Looking for a fallback subproject for the dependency',
+                     mlog.bold(self.display_name), 'because:\nUse of fallback dependencies is forced.')
+        elif self.nofallback:
+            mlog.log('Not looking for a fallback subproject for the dependency',
+                     mlog.bold(self.display_name), 'because:\nUse of fallback dependencies is disabled.')
+            return None
+        else:
+            mlog.log('Looking for a fallback subproject for the dependency',
+                     mlog.bold(self.display_name))
+
+        # dependency('foo', static: true) should implicitly add
+        # default_options: ['default_library=static']
+        static = kwargs.get('static')
+        default_options = stringlistify(func_kwargs.get('default_options', []))
+        if static is not None and not any('default_library' in i for i in default_options):
+            default_library = 'static' if static else 'shared'
+            opt = f'default_library={default_library}'
+            mlog.log(f'Building fallback subproject with {opt}')
+            default_options.append(opt)
+            func_kwargs['default_options'] = default_options
+
+        # Configure the subproject
+        subp_name = self.subproject_name
+        varname = self.subproject_varname
+        self.interpreter.do_subproject(subp_name, 'meson', func_kwargs)
+        return self._get_subproject_dep(subp_name, varname, kwargs)
+
+    def _get_subproject(self, subp_name: str) -> T.Optional[SubprojectHolder]:
+        sub = self.interpreter.subprojects.get(subp_name)
+        if sub and sub.found():
+            return sub
+        return None
+
+    def _get_subproject_dep(self, subp_name: str, varname: str, kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
+        # Verify the subproject is found
+        subproject = self._get_subproject(subp_name)
+        if not subproject:
+            mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
+                     mlog.bold(subp_name), 'found:', mlog.red('NO'),
+                     mlog.blue('(subproject failed to configure)'))
+            return None
+
+        # The subproject has been configured. If for any reason the dependency
+        # cannot be found in this subproject we have to return not-found object
+        # instead of None, because we don't want to continue the lookup on the
+        # system.
+
+        # Check if the subproject overridden at least one of the names we got.
+        cached_dep = None
+        for name in self.names:
+            cached_dep = self._get_cached_dep(name, kwargs)
+            if cached_dep:
+                break
+
+        # If we have cached_dep we did all the checks and logging already in
+        # self._get_cached_dep().
+        if cached_dep:
+            self._verify_fallback_consistency(cached_dep)
+            return cached_dep
+
+        # Legacy: Use the variable name if provided instead of relying on the
+        # subproject to override one of our dependency names
+        if not varname:
+            mlog.warning(f'Subproject {subp_name!r} did not override {self.display_name!r} dependency and no variable name specified')
+            mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
+                     mlog.bold(subproject.subdir), 'found:', mlog.red('NO'))
+            return self._notfound_dependency()
+
+        var_dep = self._get_subproject_variable(subproject, varname) or self._notfound_dependency()
+        if not var_dep.found():
+            mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
+                     mlog.bold(subproject.subdir), 'found:', mlog.red('NO'))
+            return var_dep
+
+        wanted = stringlistify(kwargs.get('version', []))
+        found = var_dep.get_version()
+        if not self._check_version(wanted, found):
+            mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
+                     mlog.bold(subproject.subdir), 'found:', mlog.red('NO'),
+                     'found', mlog.normal_cyan(found), 'but need:',
+                     mlog.bold(', '.join([f"'{e}'" for e in wanted])))
+            return self._notfound_dependency()
+
+        mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
+                 mlog.bold(subproject.subdir), 'found:', mlog.green('YES'),
+                 mlog.normal_cyan(found) if found else None)
+        return var_dep
+
+    def _get_cached_dep(self, name: str, kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
+        # Unlike other methods, this one returns not-found dependency instead
+        # of None in the case the dependency is cached as not-found, or if cached
+        # version does not match. In that case we don't want to continue with
+        # other candidates.
+        for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
+        identifier = dependencies.get_dep_identifier(name, kwargs)
+        wanted_vers = stringlistify(kwargs.get('version', []))
+
+        override = self.build.dependency_overrides[for_machine].get(identifier)
+        if override:
+            info = [mlog.blue('(overridden)' if override.explicit else '(cached)')]
+            cached_dep = override.dep
+            # We don't implicitly override not-found dependencies, but user could
+            # have explicitly called meson.override_dependency() with a not-found
+            # dep.
+            if not cached_dep.found():
+                mlog.log('Dependency', mlog.bold(self.display_name),
+                         'found:', mlog.red('NO'), *info)
+                return cached_dep
+        else:
+            info = [mlog.blue('(cached)')]
+            cached_dep = self.coredata.deps[for_machine].get(identifier)
+
+        if cached_dep:
+            found_vers = cached_dep.get_version()
+            if not self._check_version(wanted_vers, found_vers):
+                if not override:
+                    # We cached this dependency on disk from a previous run,
+                    # but it could got updated on the system in the meantime.
+                    return None
+                mlog.log('Dependency', mlog.bold(name),
+                         'found:', mlog.red('NO'),
+                         'found', mlog.normal_cyan(found_vers), 'but need:',
+                         mlog.bold(', '.join([f"'{e}'" for e in wanted_vers])),
+                         *info)
+                return self._notfound_dependency()
+            if found_vers:
+                info = [mlog.normal_cyan(found_vers), *info]
+            mlog.log('Dependency', mlog.bold(self.display_name),
+                     'found:', mlog.green('YES'), *info)
+            return cached_dep
+        return None
+
+    def _get_subproject_variable(self, subproject: SubprojectHolder, varname: str) -> T.Optional[Dependency]:
+        try:
+            var_dep = subproject.get_variable_method([varname], {})
+        except InvalidArguments:
+            var_dep = None
+        if not isinstance(var_dep, Dependency):
+            mlog.warning(f'Variable {varname!r} in the subproject {subproject.subdir!r} is',
+                         'not found' if var_dep is None else 'not a dependency object')
+            return None
+        return var_dep
+
+    def _verify_fallback_consistency(self, cached_dep: Dependency):
+        subp_name = self.subproject_name
+        varname = self.subproject_varname
+        subproject = self._get_subproject(subp_name)
+        if subproject and varname:
+            var_dep = self._get_subproject_variable(subproject, varname)
+            if var_dep and cached_dep.found() and var_dep != cached_dep:
+                mlog.warning(f'Inconsistency: Subproject has overridden the dependency with another variable than {varname!r}')
+
+    def _handle_featurenew_dependencies(self, name: str) -> None:
+        'Do a feature check on dependencies used by this subproject'
+        if name == 'mpi':
+            FeatureNew.single_use('MPI Dependency', '0.42.0', self.subproject)
+        elif name == 'pcap':
+            FeatureNew.single_use('Pcap Dependency', '0.42.0', self.subproject)
+        elif name == 'vulkan':
+            FeatureNew.single_use('Vulkan Dependency', '0.42.0', self.subproject)
+        elif name == 'libwmf':
+            FeatureNew.single_use('LibWMF Dependency', '0.44.0', self.subproject)
+        elif name == 'openmp':
+            FeatureNew.single_use('OpenMP Dependency', '0.46.0', self.subproject)
+
+    def _notfound_dependency(self) -> NotFoundDependency:
+        return NotFoundDependency(self.names[0] if self.names else '', self.environment)
+
+    @staticmethod
+    def _check_version(wanted: T.Optional[str], found: str) -> bool:
+        if not wanted:
+            return True
+        if found == 'undefined' or not version_compare_many(found, wanted)[0]:
+            return False
+        return True
+
+    def _get_candidates(self) -> T.List[T.Tuple[T.Callable[[TYPE_nkwargs, TYPE_nvar, TYPE_nkwargs], T.Optional[Dependency]], TYPE_nvar, TYPE_nkwargs]]:
+        candidates = []
+        # 1. check if any of the names is cached already.
+        for name in self.names:
+            candidates.append((self._do_dependency_cache, [name], {}))
+        # 2. check if the subproject fallback has already been configured.
+        if self.subproject_name:
+            candidates.append((self._do_existing_subproject, [self.subproject_name], self.subproject_kwargs))
+        # 3. check external dependency if we are not forced to use subproject
+        if not self.forcefallback or not self.subproject_name:
+            for name in self.names:
+                candidates.append((self._do_dependency, [name], {}))
+        # 4. configure the subproject
+        if self.subproject_name:
+            candidates.append((self._do_subproject, [self.subproject_name], self.subproject_kwargs))
+        return candidates
+
+    def lookup(self, kwargs: TYPE_nkwargs, force_fallback: bool = False) -> Dependency:
+        self.display_name = self.names[0] if self.names else '(anonymous)'
+        mods = extract_as_list(kwargs, 'modules')
+        if mods:
+            self.display_name += ' (modules: {})'.format(', '.join(str(i) for i in mods))
+
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
+        if disabled:
+            mlog.log('Dependency', mlog.bold(self.display_name), 'skipped: feature', mlog.bold(feature), 'disabled')
+            return self._notfound_dependency()
+
+        # Check if usage of the subproject fallback is forced
+        wrap_mode = self.coredata.get_option(OptionKey('wrap_mode'))
+        force_fallback_for = self.coredata.get_option(OptionKey('force_fallback_for'))
+        self.nofallback = wrap_mode == WrapMode.nofallback
+        self.forcefallback = (force_fallback or
+                              wrap_mode == WrapMode.forcefallback or
+                              any(name in force_fallback_for for name in self.names) or
+                              self.subproject_name in force_fallback_for)
+
+        # Add an implicit subproject fallback if none has been set explicitly,
+        # unless implicit fallback is not allowed.
+        # Legacy: self.allow_fallback can be None when that kwarg is not defined
+        # in dependency('name'). In that case we don't want to use implicit
+        # fallback when required is false because user will typically fallback
+        # manually using cc.find_library() for example.
+        if not self.subproject_name and self.allow_fallback is not False:
+            for name in self.names:
+                subp_name, varname = self.wrap_resolver.find_dep_provider(name)
+                if subp_name:
+                    self.forcefallback |= subp_name in force_fallback_for
+                    if self.forcefallback or self.allow_fallback is True or required or self._get_subproject(subp_name):
+                        self._subproject_impl(subp_name, varname)
+                    break
+
+        candidates = self._get_candidates()
+
+        # writing just "dependency('')" is an error, because it can only fail
+        if not candidates and required:
+            raise InvalidArguments('Dependency is required but has no candidates.')
+
+        # Try all candidates, only the last one is really required.
+        last = len(candidates) - 1
+        for i, item in enumerate(candidates):
+            func, func_args, func_kwargs = item
+            func_kwargs['required'] = required and (i == last)
+            kwargs['required'] = required and (i == last)
+            dep = func(kwargs, func_args, func_kwargs)
+            if dep and dep.found():
+                # Override this dependency to have consistent results in subsequent
+                # dependency lookups.
+                for name in self.names:
+                    for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
+                    identifier = dependencies.get_dep_identifier(name, kwargs)
+                    if identifier not in self.build.dependency_overrides[for_machine]:
+                        self.build.dependency_overrides[for_machine][identifier] = \
+                            build.DependencyOverride(dep, self.interpreter.current_node, explicit=False)
+                return dep
+            elif required and (dep or i == last):
+                # This was the last candidate or the dependency has been cached
+                # as not-found, or cached dependency version does not match,
+                # otherwise func() would have returned None instead.
+                raise DependencyException(f'Dependency {self.display_name!r} is required but not found.')
+            elif dep:
+                # Same as above, but the dependency is not required.
+                return dep
+        return self._notfound_dependency()
diff -Nru meson-0.53.2/mesonbuild/interpreter/__init__.py meson-0.61.2/mesonbuild/interpreter/__init__.py
--- meson-0.53.2/mesonbuild/interpreter/__init__.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/__init__.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,59 @@
+# SPDX-license-identifier: Apache-2.0
+# Copyright 2012-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+# 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.
+
+"""Meson interpreter."""
+
+__all__ = [
+    'Interpreter',
+    'permitted_dependency_kwargs',
+
+    'CompilerHolder',
+
+    'ExecutableHolder',
+    'BuildTargetHolder',
+    'CustomTargetHolder',
+    'CustomTargetIndexHolder',
+    'MachineHolder',
+    'Test',
+    'ConfigurationDataObject',
+    'SubprojectHolder',
+    'DependencyHolder',
+    'GeneratedListHolder',
+    'ExternalProgramHolder',
+    'extract_required_kwarg',
+
+    'ArrayHolder',
+    'BooleanHolder',
+    'DictHolder',
+    'IntegerHolder',
+    'StringHolder',
+]
+
+from .interpreter import Interpreter, permitted_dependency_kwargs
+from .compiler import CompilerHolder
+from .interpreterobjects import (ExecutableHolder, BuildTargetHolder, CustomTargetHolder,
+                                 CustomTargetIndexHolder, MachineHolder, Test,
+                                 ConfigurationDataObject, SubprojectHolder, DependencyHolder,
+                                 GeneratedListHolder, ExternalProgramHolder,
+                                 extract_required_kwarg)
+
+from .primitives import (
+    ArrayHolder,
+    BooleanHolder,
+    DictHolder,
+    IntegerHolder,
+    StringHolder,
+)
diff -Nru meson-0.53.2/mesonbuild/interpreter/interpreterobjects.py meson-0.61.2/mesonbuild/interpreter/interpreterobjects.py
--- meson-0.53.2/mesonbuild/interpreter/interpreterobjects.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/interpreterobjects.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,995 @@
+import os
+import shlex
+import subprocess
+import copy
+import textwrap
+
+from pathlib import Path, PurePath
+
+from .. import mesonlib
+from .. import coredata
+from .. import build
+from .. import mlog
+
+from ..modules import ModuleReturnValue, ModuleObject, ModuleState, ExtensionModule
+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,
+                               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
+from ..dependencies import Dependency, ExternalLibrary, InternalDependency
+from ..programs import ExternalProgram
+from ..mesonlib import HoldableObject, MesonException, OptionKey, listify, Popen_safe
+
+import typing as T
+
+if T.TYPE_CHECKING:
+    from . import kwargs
+    from .interpreter import Interpreter
+    from ..envconfig import MachineInfo
+
+    from typing_extensions import TypedDict
+
+    class EnvironmentSeparatorKW(TypedDict):
+
+        separator: str
+
+
+def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired',
+                           subproject: str,
+                           feature_check: T.Optional[FeatureCheckBase] = None,
+                           default: bool = True) -> T.Tuple[bool, bool, T.Optional[str]]:
+    val = kwargs.get('required', default)
+    disabled = False
+    required = False
+    feature: T.Optional[str] = None
+    if isinstance(val, coredata.UserFeatureOption):
+        if not feature_check:
+            feature_check = FeatureNew('User option "feature"', '0.47.0')
+        feature_check.use(subproject)
+        feature = val.name
+        if val.is_disabled():
+            disabled = True
+        elif val.is_enabled():
+            required = True
+    elif isinstance(val, bool):
+        required = val
+    else:
+        raise InterpreterException('required keyword argument must be boolean or a feature option')
+
+    # Keep boolean value in kwargs to simplify other places where this kwarg is
+    # checked.
+    # TODO: this should be removed, and those callers should learn about FeatureOptions
+    kwargs['required'] = required
+
+    return disabled, required, feature
+
+def extract_search_dirs(kwargs: 'kwargs.ExtractSearchDirs') -> T.List[str]:
+    search_dirs_str = mesonlib.stringlistify(kwargs.get('dirs', []))
+    search_dirs = [Path(d).expanduser() for d in search_dirs_str]
+    for d in search_dirs:
+        if mesonlib.is_windows() and d.root.startswith('\\'):
+            # a Unix-path starting with `/` that is not absolute on Windows.
+            # discard without failing for end-user ease of cross-platform directory arrays
+            continue
+        if not d.is_absolute():
+            raise InvalidCode(f'Search directory {d} is not an absolute path.')
+    return list(map(str, search_dirs))
+
+class FeatureOptionHolder(ObjectHolder[coredata.UserFeatureOption]):
+    def __init__(self, option: coredata.UserFeatureOption, interpreter: 'Interpreter'):
+        super().__init__(option, interpreter)
+        if option and option.is_auto():
+            # TODO: we need to case here because options is not a TypedDict
+            self.held_object = T.cast(coredata.UserFeatureOption, self.env.coredata.options[OptionKey('auto_features')])
+            self.held_object.name = option.name
+        self.methods.update({'enabled': self.enabled_method,
+                             'disabled': self.disabled_method,
+                             'allowed': self.allowed_method,
+                             'auto': self.auto_method,
+                             'require': self.require_method,
+                             'disable_auto_if': self.disable_auto_if_method,
+                             })
+
+    @property
+    def value(self) -> str:
+        return 'disabled' if not self.held_object else self.held_object.value
+
+    def as_disabled(self) -> coredata.UserFeatureOption:
+        disabled = copy.deepcopy(self.held_object)
+        disabled.value = 'disabled'
+        return disabled
+
+    @noPosargs
+    @noKwargs
+    def enabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return self.value == 'enabled'
+
+    @noPosargs
+    @noKwargs
+    def disabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return self.value == 'disabled'
+
+    @noPosargs
+    @noKwargs
+    @FeatureNew('feature_option.allowed()', '0.59.0')
+    def allowed_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return self.value != 'disabled'
+
+    @noPosargs
+    @noKwargs
+    def auto_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return self.value == 'auto'
+
+    @FeatureNew('feature_option.require()', '0.59.0')
+    @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.")
+        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)
+        return self.as_disabled()
+
+    @FeatureNew('feature_option.disable_auto_if()', '0.59.0')
+    @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.')
+        return copy.deepcopy(self.held_object) if self.value != 'auto' or not args[0] else self.as_disabled()
+
+
+class RunProcess(MesonInterpreterObject):
+
+    def __init__(self,
+                 cmd: ExternalProgram,
+                 args: T.List[str],
+                 env: build.EnvironmentVariables,
+                 source_dir: str,
+                 build_dir: str,
+                 subdir: str,
+                 mesonintrospect: T.List[str],
+                 in_builddir: bool = False,
+                 check: bool = False,
+                 capture: bool = True) -> None:
+        super().__init__()
+        if not isinstance(cmd, ExternalProgram):
+            raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
+        self.capture = capture
+        self.returncode, self.stdout, self.stderr = self.run_command(cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
+        self.methods.update({'returncode': self.returncode_method,
+                             'stdout': self.stdout_method,
+                             'stderr': self.stderr_method,
+                             })
+
+    def run_command(self,
+                    cmd: ExternalProgram,
+                    args: T.List[str],
+                    env: build.EnvironmentVariables,
+                    source_dir: str,
+                    build_dir: str,
+                    subdir: str,
+                    mesonintrospect: T.List[str],
+                    in_builddir: bool,
+                    check: bool = False) -> T.Tuple[int, str, str]:
+        command_array = cmd.get_command() + args
+        menv = {'MESON_SOURCE_ROOT': source_dir,
+                'MESON_BUILD_ROOT': build_dir,
+                'MESON_SUBDIR': subdir,
+                'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]),
+                }
+        if in_builddir:
+            cwd = os.path.join(build_dir, subdir)
+        else:
+            cwd = os.path.join(source_dir, subdir)
+        child_env = os.environ.copy()
+        child_env.update(menv)
+        child_env = env.get_env(child_env)
+        stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL
+        mlog.debug('Running command:', ' '.join(command_array))
+        try:
+            p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd)
+            if self.capture:
+                mlog.debug('--- stdout ---')
+                mlog.debug(o)
+            else:
+                o = ''
+                mlog.debug('--- stdout disabled ---')
+            mlog.debug('--- stderr ---')
+            mlog.debug(e)
+            mlog.debug('')
+
+            if check and p.returncode != 0:
+                raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
+
+            return p.returncode, o, e
+        except FileNotFoundError:
+            raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
+
+    @noPosargs
+    @noKwargs
+    def returncode_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
+        return self.returncode
+
+    @noPosargs
+    @noKwargs
+    def stdout_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.stdout
+
+    @noPosargs
+    @noKwargs
+    def stderr_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.stderr
+
+
+_ENV_SEPARATOR_KW = KwargInfo('separator', str, default=os.pathsep)
+
+
+class EnvironmentVariablesHolder(ObjectHolder[build.EnvironmentVariables], MutableInterpreterObject):
+
+    def __init__(self, obj: build.EnvironmentVariables, interpreter: 'Interpreter'):
+        super().__init__(obj, interpreter)
+        self.methods.update({'set': self.set_method,
+                             'append': self.append_method,
+                             'prepend': self.prepend_method,
+                             })
+
+    def __repr__(self) -> str:
+        repr_str = "<{0}: {1}>"
+        return repr_str.format(self.__class__.__name__, self.held_object.envvars)
+
+    def __deepcopy__(self, memo: T.Dict[str, object]) -> 'EnvironmentVariablesHolder':
+        # Avoid trying to copy the interpreter
+        return EnvironmentVariablesHolder(copy.deepcopy(self.held_object), self.interpreter)
+
+    def warn_if_has_name(self, name: str) -> None:
+        # Multiple append/prepend operations was not supported until 0.58.0.
+        if self.held_object.has_name(name):
+            m = f'Overriding previous value of environment variable {name!r} with a new one'
+            FeatureNew(m, '0.58.0', location=self.current_node).use(self.subproject)
+
+    @typed_pos_args('environment.set', str, varargs=str, min_varargs=1)
+    @typed_kwargs('environment.set', _ENV_SEPARATOR_KW)
+    def set_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
+        name, values = args
+        self.held_object.set(name, values, kwargs['separator'])
+
+    @typed_pos_args('environment.append', str, varargs=str, min_varargs=1)
+    @typed_kwargs('environment.append', _ENV_SEPARATOR_KW)
+    def append_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
+        name, values = args
+        self.warn_if_has_name(name)
+        self.held_object.append(name, values, kwargs['separator'])
+
+    @typed_pos_args('environment.prepend', str, varargs=str, min_varargs=1)
+    @typed_kwargs('environment.prepend', _ENV_SEPARATOR_KW)
+    def prepend_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
+        name, values = args
+        self.warn_if_has_name(name)
+        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()
+        self.methods.update({'set': self.set_method,
+                             'set10': self.set10_method,
+                             'set_quoted': self.set_quoted_method,
+                             'has': self.has_method,
+                             'get': self.get_method,
+                             'keys': self.keys_method,
+                             'get_unquoted': self.get_unquoted_method,
+                             'merge_from': self.merge_from_method,
+                             })
+        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 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
+
+    @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 has_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return args[0] in self.conf_data.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.')
+        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])
+        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.')
+        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))
+            val = args[1]
+        else:
+            raise InterpreterException(f'Entry {name} not in configuration data.')
+        if isinstance(val, str) and val[0] == '"' and val[-1] == '"':
+            return val[1:-1]
+        return val
+
+    def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]:
+        return self.conf_data.values[name]
+
+    @FeatureNew('configuration_data.keys()', '0.57.0')
+    @noPosargs
+    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())
+
+    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
+
+
+_PARTIAL_DEP_KWARGS = [
+    KwargInfo('compile_args', bool, default=False),
+    KwargInfo('link_args',    bool, default=False),
+    KwargInfo('links',        bool, default=False),
+    KwargInfo('includes',     bool, default=False),
+    KwargInfo('sources',      bool, default=False),
+]
+
+class DependencyHolder(ObjectHolder[Dependency]):
+    def __init__(self, dep: Dependency, interpreter: 'Interpreter'):
+        super().__init__(dep, interpreter)
+        self.methods.update({'found': self.found_method,
+                             'type_name': self.type_name_method,
+                             'version': self.version_method,
+                             'name': self.name_method,
+                             'get_pkgconfig_variable': self.pkgconfig_method,
+                             'get_configtool_variable': self.configtool_method,
+                             'get_variable': self.variable_method,
+                             'partial_dependency': self.partial_dependency_method,
+                             'include_type': self.include_type_method,
+                             'as_system': self.as_system_method,
+                             'as_link_whole': self.as_link_whole_method,
+                             })
+
+    def found(self) -> bool:
+        return self.found_method([], {})
+
+    @noPosargs
+    @noKwargs
+    def type_name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.type_name
+
+    @noPosargs
+    @noKwargs
+    def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        if self.held_object.type_name == 'internal':
+            return True
+        return self.held_object.found()
+
+    @noPosargs
+    @noKwargs
+    def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.get_version()
+
+    @noPosargs
+    @noKwargs
+    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)
+
+    @FeatureNew('dep.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)
+
+    @FeatureNew('dep.partial_dependency', '0.46.0')
+    @noPosargs
+    @typed_kwargs('dep.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]]:
+        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('dep.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('dep.as_link_whole', '0.56.0')
+    @noKwargs
+    @noPosargs
+    def as_link_whole_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> Dependency:
+        if not isinstance(self.held_object, InternalDependency):
+            raise InterpreterException('as_link_whole method is only supported on declare_dependency() objects')
+        new_dep = self.held_object.generate_link_whole_dependency()
+        return new_dep
+
+class ExternalProgramHolder(ObjectHolder[ExternalProgram]):
+    def __init__(self, ep: ExternalProgram, interpreter: 'Interpreter') -> None:
+        super().__init__(ep, interpreter)
+        self.methods.update({'found': self.found_method,
+                             'path': self.path_method,
+                             'full_path': self.full_path_method})
+
+    @noPosargs
+    @noKwargs
+    def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return self.found()
+
+    @noPosargs
+    @noKwargs
+    @FeatureDeprecated('ExternalProgram.path', '0.55.0',
+                       'use ExternalProgram.full_path() instead')
+    def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self._full_path()
+
+    @noPosargs
+    @noKwargs
+    @FeatureNew('ExternalProgram.full_path', '0.55.0')
+    def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self._full_path()
+
+    def _full_path(self) -> str:
+        if not self.found():
+            raise InterpreterException('Unable to get the path of a not-found external program')
+        path = self.held_object.get_path()
+        assert path is not None
+        return path
+
+    def found(self) -> bool:
+        return self.held_object.found()
+
+class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]):
+    def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'):
+        super().__init__(el, interpreter)
+        self.methods.update({'found': self.found_method,
+                             'type_name': self.type_name_method,
+                             'partial_dependency': self.partial_dependency_method,
+                             })
+
+    @noPosargs
+    @noKwargs
+    def type_name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.type_name
+
+    @noPosargs
+    @noKwargs
+    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')
+    @noPosargs
+    @typed_kwargs('dep.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
+
+# A machine that's statically known from the cross file
+class MachineHolder(ObjectHolder['MachineInfo']):
+    def __init__(self, machine_info: 'MachineInfo', interpreter: 'Interpreter'):
+        super().__init__(machine_info, interpreter)
+        self.methods.update({'system': self.system_method,
+                             'cpu': self.cpu_method,
+                             'cpu_family': self.cpu_family_method,
+                             'endian': self.endian_method,
+                             })
+
+    @noPosargs
+    @noKwargs
+    def cpu_family_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.cpu_family
+
+    @noPosargs
+    @noKwargs
+    def cpu_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.cpu
+
+    @noPosargs
+    @noKwargs
+    def system_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.system
+
+    @noPosargs
+    @noKwargs
+    def endian_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.endian
+
+class IncludeDirsHolder(ObjectHolder[build.IncludeDirs]):
+    pass
+
+class FileHolder(ObjectHolder[mesonlib.File]):
+    pass
+
+class HeadersHolder(ObjectHolder[build.Headers]):
+    pass
+
+class DataHolder(ObjectHolder[build.Data]):
+    pass
+
+class SymlinkDataHolder(ObjectHolder[build.SymlinkData]):
+    pass
+
+class InstallDirHolder(ObjectHolder[build.InstallDir]):
+    pass
+
+class ManHolder(ObjectHolder[build.Man]):
+    pass
+
+class EmptyDirHolder(ObjectHolder[build.EmptyDir]):
+    pass
+
+class GeneratedObjectsHolder(ObjectHolder[build.ExtractedObjects]):
+    pass
+
+class Test(MesonInterpreterObject):
+    def __init__(self, name: str, project: str, suite: T.List[str],
+                 exe: T.Union[ExternalProgram, build.Executable, build.CustomTarget],
+                 depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]],
+                 is_parallel: bool,
+                 cmd_args: T.List[T.Union[str, mesonlib.File, build.Target]],
+                 env: build.EnvironmentVariables,
+                 should_fail: bool, timeout: int, workdir: T.Optional[str], protocol: str,
+                 priority: int):
+        super().__init__()
+        self.name = name
+        self.suite = listify(suite)
+        self.project_name = project
+        self.exe = exe
+        self.depends = depends
+        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.protocol = TestProtocol.from_str(protocol)
+        self.priority = priority
+
+    def get_exe(self) -> T.Union[ExternalProgram, build.Executable, build.CustomTarget]:
+        return self.exe
+
+    def get_name(self) -> str:
+        return self.name
+
+class NullSubprojectInterpreter(HoldableObject):
+    pass
+
+# TODO: This should really be an `ObjectHolder`, but the additional stuff in this
+#       class prevents this. Thus, this class should be split into a pure
+#       `ObjectHolder` and a class specifically for storing in `Interpreter`.
+class SubprojectHolder(MesonInterpreterObject):
+
+    def __init__(self, subinterpreter: T.Union['Interpreter', NullSubprojectInterpreter],
+                 subdir: str,
+                 warnings: int = 0,
+                 disabled_feature: T.Optional[str] = None,
+                 exception: T.Optional[MesonException] = None) -> None:
+        super().__init__()
+        self.held_object = subinterpreter
+        self.warnings = warnings
+        self.disabled_feature = disabled_feature
+        self.exception = exception
+        self.subdir = PurePath(subdir).as_posix()
+        self.methods.update({'get_variable': self.get_variable_method,
+                             'found': self.found_method,
+                             })
+
+    @noPosargs
+    @noKwargs
+    def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return self.found()
+
+    def found(self) -> bool:
+        return not isinstance(self.held_object, NullSubprojectInterpreter)
+
+    @noKwargs
+    @noArgsFlattening
+    @unholder_return
+    def get_variable_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Union[TYPE_var, InterpreterObject]:
+        if len(args) < 1 or len(args) > 2:
+            raise InterpreterException('Get_variable takes one or two arguments.')
+        if isinstance(self.held_object, NullSubprojectInterpreter):  # == not self.found()
+            raise InterpreterException(f'Subproject "{self.subdir}" disabled can\'t get_variable on it.')
+        varname = args[0]
+        if not isinstance(varname, str):
+            raise InterpreterException('Get_variable first argument must be a string.')
+        try:
+            return self.held_object.variables[varname]
+        except KeyError:
+            pass
+
+        if len(args) == 2:
+            return self.held_object._holderify(args[1])
+
+        raise InvalidArguments(f'Requested variable "{varname}" not found.')
+
+class ModuleObjectHolder(ObjectHolder[ModuleObject]):
+    def method_call(self, method_name: str, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> TYPE_var:
+        modobj = self.held_object
+        method = modobj.methods.get(method_name)
+        if not method:
+            raise InvalidCode(f'Unknown method {method_name!r} in object.')
+        if not getattr(method, 'no-args-flattening', False):
+            args = flatten(args)
+        if not getattr(method, 'no-second-level-holder-flattening', False):
+            args, kwargs = resolve_second_level_holders(args, kwargs)
+        state = ModuleState(self.interpreter)
+        # Many modules do for example self.interpreter.find_program_impl(),
+        # so we have to ensure they use the current interpreter and not the one
+        # that first imported that module, otherwise it will use outdated
+        # overrides.
+        if isinstance(modobj, ExtensionModule):
+            modobj.interpreter = self.interpreter
+        ret = method(state, args, kwargs)
+        if isinstance(ret, ModuleReturnValue):
+            self.interpreter.process_new_values(ret.new_objects)
+            ret = ret.return_value
+        return ret
+
+class MutableModuleObjectHolder(ModuleObjectHolder, MutableInterpreterObject):
+    def __deepcopy__(self, memo: T.Dict[int, T.Any]) -> 'MutableModuleObjectHolder':
+        # Deepcopy only held object, not interpreter
+        modobj = copy.deepcopy(self.held_object, memo)
+        return MutableModuleObjectHolder(modobj, self.interpreter)
+
+
+_BuildTarget = T.TypeVar('_BuildTarget', bound=T.Union[build.BuildTarget, build.BothLibraries])
+
+class BuildTargetHolder(ObjectHolder[_BuildTarget]):
+    def __init__(self, target: _BuildTarget, interp: 'Interpreter'):
+        super().__init__(target, interp)
+        self.methods.update({'extract_objects': self.extract_objects_method,
+                             'extract_all_objects': self.extract_all_objects_method,
+                             'name': self.name_method,
+                             'get_id': self.get_id_method,
+                             'outdir': self.outdir_method,
+                             'full_path': self.full_path_method,
+                             'path': self.path_method,
+                             'found': self.found_method,
+                             'private_dir_include': self.private_dir_include_method,
+                             })
+
+    def __repr__(self) -> str:
+        r = '<{} {}: {}>'
+        h = self.held_object
+        assert isinstance(h, build.BuildTarget)
+        return r.format(self.__class__.__name__, h.get_id(), h.filename)
+
+    @property
+    def _target_object(self) -> build.BuildTarget:
+        if isinstance(self.held_object, build.BothLibraries):
+            return self.held_object.get_default_object()
+        assert isinstance(self.held_object, build.BuildTarget)
+        return self.held_object
+
+    def is_cross(self) -> bool:
+        return not self._target_object.environment.machines.matches_build_machine(self._target_object.for_machine)
+
+    @noPosargs
+    @noKwargs
+    def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        if not (isinstance(self.held_object, build.Executable) and self.held_object.was_returned_by_find_program):
+            FeatureNew.single_use('BuildTarget.found', '0.59.0', subproject=self.held_object.subproject)
+        return True
+
+    @noPosargs
+    @noKwargs
+    def private_dir_include_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.IncludeDirs:
+        return build.IncludeDirs('', [], False, [self.interpreter.backend.get_target_private_dir(self._target_object)])
+
+    @noPosargs
+    @noKwargs
+    def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.interpreter.backend.get_target_filename_abs(self._target_object)
+
+    @noPosargs
+    @noKwargs
+    @FeatureDeprecated('BuildTarget.path', '0.55.0', 'Use BuildTarget.full_path instead')
+    def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.interpreter.backend.get_target_filename_abs(self._target_object)
+
+    @noPosargs
+    @noKwargs
+    def outdir_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.interpreter.backend.get_target_dir(self._target_object)
+
+    @noKwargs
+    @typed_pos_args('extract_objects', varargs=(mesonlib.File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList))
+    def extract_objects_method(self, args: T.Tuple[T.List[T.Union[mesonlib.FileOrString, 'build.GeneratedTypes']]], kwargs: TYPE_nkwargs) -> build.ExtractedObjects:
+        return self._target_object.extract_objects(args[0])
+
+    @noPosargs
+    @typed_kwargs(
+        'extract_all_objects',
+        KwargInfo(
+            'recursive', bool, default=False, since='0.46.0',
+            not_set_warning=textwrap.dedent('''\
+                extract_all_objects called without setting recursive
+                keyword argument. Meson currently defaults to
+                non-recursive to maintain backward compatibility but
+                the default will be changed in the future.
+            ''')
+        )
+    )
+    def extract_all_objects_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.BuildTargeMethodExtractAllObjects') -> build.ExtractedObjects:
+        return self._target_object.extract_all_objects(kwargs['recursive'])
+
+    @noPosargs
+    @noKwargs
+    def get_id_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self._target_object.get_id()
+
+    @FeatureNew('name', '0.54.0')
+    @noPosargs
+    @noKwargs
+    def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self._target_object.name
+
+class ExecutableHolder(BuildTargetHolder[build.Executable]):
+    pass
+
+class StaticLibraryHolder(BuildTargetHolder[build.StaticLibrary]):
+    pass
+
+class SharedLibraryHolder(BuildTargetHolder[build.SharedLibrary]):
+    pass
+
+class BothLibrariesHolder(BuildTargetHolder[build.BothLibraries]):
+    def __init__(self, libs: build.BothLibraries, interp: 'Interpreter'):
+        # FIXME: This build target always represents the shared library, but
+        # that should be configurable.
+        super().__init__(libs, interp)
+        self.methods.update({'get_shared_lib': self.get_shared_lib_method,
+                             'get_static_lib': self.get_static_lib_method,
+                             })
+
+    def __repr__(self) -> str:
+        r = '<{} {}: {}, {}: {}>'
+        h1 = self.held_object.shared
+        h2 = self.held_object.static
+        return r.format(self.__class__.__name__, h1.get_id(), h1.filename, h2.get_id(), h2.filename)
+
+    @noPosargs
+    @noKwargs
+    def get_shared_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.SharedLibrary:
+        return self.held_object.shared
+
+    @noPosargs
+    @noKwargs
+    def get_static_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.StaticLibrary:
+        return self.held_object.static
+
+class SharedModuleHolder(BuildTargetHolder[build.SharedModule]):
+    pass
+
+class JarHolder(BuildTargetHolder[build.Jar]):
+    pass
+
+class CustomTargetIndexHolder(ObjectHolder[build.CustomTargetIndex]):
+    def __init__(self, target: build.CustomTargetIndex, interp: 'Interpreter'):
+        super().__init__(target, interp)
+        self.methods.update({'full_path': self.full_path_method,
+                             })
+
+    @FeatureNew('custom_target[i].full_path', '0.54.0')
+    @noPosargs
+    @noKwargs
+    def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        assert self.interpreter.backend is not None
+        return self.interpreter.backend.get_target_filename_abs(self.held_object)
+
+class CustomTargetHolder(ObjectHolder[build.CustomTarget]):
+    def __init__(self, target: 'build.CustomTarget', interp: 'Interpreter'):
+        super().__init__(target, interp)
+        self.methods.update({'full_path': self.full_path_method,
+                             'to_list': self.to_list_method,
+                             })
+
+        self.operators.update({
+            MesonOperator.INDEX: self.op_index,
+        })
+
+    def __repr__(self) -> str:
+        r = '<{} {}: {}>'
+        h = self.held_object
+        return r.format(self.__class__.__name__, h.get_id(), h.command)
+
+    @noPosargs
+    @noKwargs
+    def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.interpreter.backend.get_target_filename_abs(self.held_object)
+
+    @FeatureNew('custom_target.to_list', '0.54.0')
+    @noPosargs
+    @noKwargs
+    def to_list_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[build.CustomTargetIndex]:
+        result = []
+        for i in self.held_object:
+            result.append(i)
+        return result
+
+    @noKwargs
+    @typed_operator(MesonOperator.INDEX, int)
+    def op_index(self, other: int) -> build.CustomTargetIndex:
+        try:
+            return self.held_object[other]
+        except IndexError:
+            raise InvalidArguments(f'Index {other} out of bounds of custom target {self.held_object.name} output of size {len(self.held_object)}.')
+
+class RunTargetHolder(ObjectHolder[build.RunTarget]):
+    pass
+
+class AliasTargetHolder(ObjectHolder[build.AliasTarget]):
+    pass
+
+class GeneratedListHolder(ObjectHolder[build.GeneratedList]):
+    pass
+
+class GeneratorHolder(ObjectHolder[build.Generator]):
+    def __init__(self, gen: build.Generator, interpreter: 'Interpreter'):
+        super().__init__(gen, interpreter)
+        self.methods.update({'process': self.process_method})
+
+    @typed_pos_args('generator.process', min_varargs=1, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList))
+    @typed_kwargs(
+        'generator.process',
+        KwargInfo('preserve_path_from', (str, NoneType), since='0.45.0'),
+        KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
+    )
+    def process_method(self,
+                       args: T.Tuple[T.List[T.Union[str, mesonlib.File, 'build.GeneratedTypes']]],
+                       kwargs: 'kwargs.GeneratorProcess') -> build.GeneratedList:
+        preserve_path_from = kwargs['preserve_path_from']
+        if preserve_path_from is not None:
+            preserve_path_from = os.path.normpath(preserve_path_from)
+            if not os.path.isabs(preserve_path_from):
+                # This is a bit of a hack. Fix properly before merging.
+                raise InvalidArguments('Preserve_path_from must be an absolute path for now. Sorry.')
+
+        if any(isinstance(a, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for a in args[0]):
+            FeatureNew.single_use(
+                'Calling generator.process with CustomTarget or Index of CustomTarget.',
+                '0.57.0', self.interpreter.subproject)
+
+        gl = self.held_object.process_files(args[0], self.interpreter,
+                                            preserve_path_from, extra_args=kwargs['extra_args'])
+
+        return gl
diff -Nru meson-0.53.2/mesonbuild/interpreter/interpreter.py meson-0.61.2/mesonbuild/interpreter/interpreter.py
--- meson-0.53.2/mesonbuild/interpreter/interpreter.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/interpreter.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,2887 @@
+# Copyright 2012-2021 The Meson development team
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .. import mparser
+from .. import environment
+from .. import coredata
+from .. import dependencies
+from .. import mlog
+from .. import build
+from .. import optinterpreter
+from .. import compilers
+from .. import envconfig
+from ..wrap import wrap, WrapMode
+from .. import mesonlib
+from ..mesonlib import MesonBugException, HoldableObject, FileMode, MachineChoice, OptionKey, listify, extract_as_list, has_path_sep
+from ..programs import ExternalProgram, NonExistingExternalProgram
+from ..dependencies import Dependency
+from ..depfile import DepFile
+from ..interpreterbase import ContainerTypeInfo, InterpreterBase, KwargInfo, typed_kwargs, typed_pos_args
+from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, noArgsFlattening, noSecondLevelHolderResolving, unholder_return
+from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
+from ..interpreterbase import Disabler, disablerIfNotFound
+from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs, FeatureDeprecatedKwargs
+from ..interpreterbase import ObjectHolder
+from ..interpreterbase.baseobjects import TYPE_var, TYPE_kwargs
+from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule
+from ..cmake import CMakeInterpreter
+from ..backend.backends import Backend, ExecutableSerialisation
+
+from . import interpreterobjects as OBJ
+from . import compiler as compilerOBJ
+from .mesonmain import MesonMain
+from .dependencyfallbacks import DependencyFallbacksHolder
+from .interpreterobjects import (
+    SubprojectHolder,
+    ConfigurationDataObject,
+    Test,
+    RunProcess,
+    extract_required_kwarg,
+    extract_search_dirs,
+    NullSubprojectInterpreter,
+)
+from .type_checking import (
+    COMMAND_KW, CT_BUILD_ALWAYS, CT_BUILD_ALWAYS_STALE,
+    CT_BUILD_BY_DEFAULT,
+    CT_INPUT_KW,
+    CT_INSTALL_DIR_KW,
+    CT_OUTPUT_KW,
+    DEFAULT_OPTIONS,
+    DEPENDS_KW,
+    DEPEND_FILES_KW,
+    DEPFILE_KW,
+    DISABLER_KW,
+    ENV_KW,
+    INSTALL_KW,
+    INSTALL_MODE_KW,
+    CT_INSTALL_TAG_KW,
+    LANGUAGE_KW,
+    NATIVE_KW, OVERRIDE_OPTIONS_KW,
+    REQUIRED_KW,
+    NoneType,
+    in_set_validator,
+)
+from . import primitives as P_OBJ
+
+from pathlib import Path
+import os
+import shutil
+import uuid
+import re
+import stat
+import collections
+import typing as T
+import textwrap
+import importlib
+
+if T.TYPE_CHECKING:
+    import argparse
+
+    from . import kwargs
+    from ..programs import OverrideProgram
+
+    # Input source types passed to Targets
+    SourceInputs = T.Union[mesonlib.File, build.GeneratedList, build.BuildTarget, build.BothLibraries,
+                           build.CustomTargetIndex, build.CustomTarget, build.GeneratedList,
+                           build.ExtractedObjects, str]
+    # Input source types passed to the build.Target classes
+    SourceOutputs = T.Union[mesonlib.File, build.GeneratedList,
+                            build.BuildTarget, build.CustomTargetIndex, build.CustomTarget,
+                            build.ExtractedObjects, build.GeneratedList]
+
+
+def _project_version_validator(value: T.Union[T.List, str, mesonlib.File, None]) -> T.Optional[str]:
+    if isinstance(value, list):
+        if len(value) != 1:
+            return 'when passed as array must have a length of 1'
+        elif not isinstance(value[0], (str, mesonlib.File)):
+            return 'when passed as array must contain a string or File'
+    return None
+
+
+def stringifyUserArguments(args, quote=False):
+    if isinstance(args, list):
+        return '[%s]' % ', '.join([stringifyUserArguments(x, True) for x in args])
+    elif isinstance(args, dict):
+        return '{%s}' % ', '.join(['{} : {}'.format(stringifyUserArguments(k, True), stringifyUserArguments(v, True)) for k, v in args.items()])
+    elif isinstance(args, bool):
+        return 'true' if args else 'false'
+    elif isinstance(args, int):
+        return str(args)
+    elif isinstance(args, str):
+        return f"'{args}'" if quote else args
+    raise InvalidArguments('Function accepts only strings, integers, bools, lists, dictionaries and lists thereof.')
+
+class Summary:
+    def __init__(self, project_name: str, project_version: str):
+        self.project_name = project_name
+        self.project_version = project_version
+        self.sections = collections.defaultdict(dict)
+        self.max_key_len = 0
+
+    def add_section(self, section: str, values: T.Dict[str, T.Any], bool_yn: bool,
+                    list_sep: T.Optional[str], subproject: str) -> None:
+        for k, v in values.items():
+            if k in self.sections[section]:
+                raise InterpreterException(f'Summary section {section!r} already have key {k!r}')
+            formatted_values = []
+            for i in listify(v):
+                if isinstance(i, bool) and bool_yn:
+                    formatted_values.append(mlog.green('YES') if i else mlog.red('NO'))
+                elif isinstance(i, (str, int, bool)):
+                    formatted_values.append(str(i))
+                elif isinstance(i, (ExternalProgram, Dependency)):
+                    FeatureNew.single_use('dependency or external program in summary', '0.57.0', subproject)
+                    formatted_values.append(i.summary_value())
+                elif isinstance(i, coredata.UserOption):
+                    FeatureNew.single_use('feature option in summary', '0.58.0', subproject)
+                    formatted_values.append(i.printable_value())
+                else:
+                    m = 'Summary value in section {!r}, key {!r}, must be string, integer, boolean, dependency or external program'
+                    raise InterpreterException(m.format(section, k))
+            self.sections[section][k] = (formatted_values, list_sep)
+            self.max_key_len = max(self.max_key_len, len(k))
+
+    def dump(self):
+        mlog.log(self.project_name, mlog.normal_cyan(self.project_version))
+        for section, values in self.sections.items():
+            mlog.log('')  # newline
+            if section:
+                mlog.log(' ', mlog.bold(section))
+            for k, v in values.items():
+                v, list_sep = v
+                padding = self.max_key_len - len(k)
+                end = ' ' if v else ''
+                mlog.log(' ' * 3, k + ' ' * padding + ':', end=end)
+                indent = self.max_key_len + 6
+                self.dump_value(v, list_sep, indent)
+        mlog.log('')  # newline
+
+    def dump_value(self, arr, list_sep, indent):
+        lines_sep = '\n' + ' ' * indent
+        if list_sep is None:
+            mlog.log(*arr, sep=lines_sep)
+            return
+        max_len = shutil.get_terminal_size().columns
+        line = []
+        line_len = indent
+        lines_sep = list_sep.rstrip() + lines_sep
+        for v in arr:
+            v_len = len(v) + len(list_sep)
+            if line and line_len + v_len > max_len:
+                mlog.log(*line, sep=list_sep, end=lines_sep)
+                line_len = indent
+                line = []
+            line.append(v)
+            line_len += v_len
+        mlog.log(*line, sep=list_sep)
+
+known_library_kwargs = (
+    build.known_shlib_kwargs |
+    build.known_stlib_kwargs
+)
+
+known_build_target_kwargs = (
+    known_library_kwargs |
+    build.known_exe_kwargs |
+    build.known_jar_kwargs |
+    {'target_type'}
+)
+
+TEST_KWARGS: T.List[KwargInfo] = [
+    KwargInfo('args', ContainerTypeInfo(list, (str, mesonlib.File, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex)),
+              listify=True, default=[]),
+    KwargInfo('should_fail', bool, default=False),
+    KwargInfo('timeout', int, default=30),
+    KwargInfo('workdir', (str, NoneType), default=None,
+              validator=lambda x: 'must be an absolute path' if not os.path.isabs(x) else None),
+    KwargInfo('protocol', str,
+              default='exitcode',
+              validator=in_set_validator({'exitcode', 'tap', 'gtest', 'rust'}),
+              since_values={'gtest': '0.55.0', 'rust': '0.57.0'}),
+    KwargInfo('priority', int, default=0, since='0.52.0'),
+    # TODO: env needs reworks of the way the environment variable holder itself works probably
+    ENV_KW,
+    DEPENDS_KW.evolve(since='0.46.0'),
+    KwargInfo('suite', ContainerTypeInfo(list, str), listify=True, default=['']),  # yes, a list of empty string
+]
+
+permitted_dependency_kwargs = {
+    'allow_fallback',
+    'cmake_args',
+    'cmake_module_path',
+    'cmake_package_version',
+    'components',
+    'default_options',
+    'fallback',
+    'include_type',
+    'language',
+    'main',
+    'method',
+    'modules',
+    'native',
+    'not_found_message',
+    'optional_modules',
+    'private_headers',
+    'required',
+    'static',
+    'version',
+}
+
+implicit_check_false_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"""
+class Interpreter(InterpreterBase, HoldableObject):
+
+    def __init__(
+                self,
+                _build: build.Build,
+                backend: T.Optional[Backend] = None,
+                subproject: str = '',
+                subdir: str = '',
+                subproject_dir: str = 'subprojects',
+                default_project_options: T.Optional[T.Dict[str, str]] = None,
+                mock: bool = False,
+                ast: T.Optional[mparser.CodeBlockNode] = None,
+                is_translated: bool = False,
+                user_defined_options: T.Optional['argparse.Namespace'] = None,
+            ) -> None:
+        super().__init__(_build.environment.get_source_dir(), subdir, subproject)
+        self.active_projectname = ''
+        self.build = _build
+        self.environment = self.build.environment
+        self.coredata = self.environment.get_coredata()
+        self.backend = backend
+        self.summary: T.Dict[str, 'Summary'] = {}
+        self.modules = {}
+        # Subproject directory is usually the name of the subproject, but can
+        # be different for dependencies provided by wrap files.
+        self.subproject_directory_name = subdir.split(os.path.sep)[-1]
+        self.subproject_dir = subproject_dir
+        self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt')
+        if not mock and ast is None:
+            self.load_root_meson_file()
+            self.sanity_check_ast()
+        elif ast is not None:
+            self.ast = ast
+            self.sanity_check_ast()
+        self.builtin.update({'meson': MesonMain(self.build, self)})
+        self.generators: T.List[build.Generator] = []
+        self.processed_buildfiles = set() # type: T.Set[str]
+        self.project_args_frozen = False
+        self.global_args_frozen = False  # implies self.project_args_frozen
+        self.subprojects: T.Dict[str, SubprojectHolder] = {}
+        self.subproject_stack = []
+        self.configure_file_outputs = {}
+        # Passed from the outside, only used in subprojects.
+        if default_project_options:
+            self.default_project_options = default_project_options.copy()
+        else:
+            self.default_project_options = {}
+        self.project_default_options = {}
+        self.build_func_dict()
+        self.build_holder_map()
+        self.user_defined_options = user_defined_options
+
+        # build_def_files needs to be defined before parse_project is called
+        #
+        # For non-meson subprojects, we'll be using the ast. Even if it does
+        # exist we don't want to add a dependency on it, it's autogenerated
+        # from the actual build files, and is just for reference.
+        self.build_def_files = []
+        build_filename = os.path.join(self.subdir, environment.build_filename)
+        if not is_translated:
+            self.build_def_files.append(build_filename)
+        if not mock:
+            self.parse_project()
+        self._redetect_machines()
+
+    def __getnewargs_ex__(self) -> T.Tuple[T.Tuple[object], T.Dict[str, object]]:
+        raise MesonBugException('This class is unpicklable')
+
+    def _redetect_machines(self):
+        # Re-initialize machine descriptions. We can do a better job now because we
+        # have the compilers needed to gain more knowledge, so wipe out old
+        # inference and start over.
+        machines = self.build.environment.machines.miss_defaulting()
+        machines.build = environment.detect_machine_info(self.coredata.compilers.build)
+        self.build.environment.machines = machines.default_missing()
+        assert self.build.environment.machines.build.cpu is not None
+        assert self.build.environment.machines.host.cpu is not None
+        assert self.build.environment.machines.target.cpu is not None
+
+        self.builtin['build_machine'] = \
+            OBJ.MachineHolder(self.build.environment.machines.build, self)
+        self.builtin['host_machine'] = \
+            OBJ.MachineHolder(self.build.environment.machines.host, self)
+        self.builtin['target_machine'] = \
+            OBJ.MachineHolder(self.build.environment.machines.target, self)
+
+    def build_func_dict(self):
+        self.funcs.update({'add_global_arguments': self.func_add_global_arguments,
+                           'add_global_link_arguments': self.func_add_global_link_arguments,
+                           'add_languages': self.func_add_languages,
+                           'add_project_arguments': self.func_add_project_arguments,
+                           'add_project_link_arguments': self.func_add_project_link_arguments,
+                           'add_test_setup': self.func_add_test_setup,
+                           'alias_target': self.func_alias_target,
+                           'assert': self.func_assert,
+                           'benchmark': self.func_benchmark,
+                           'both_libraries': self.func_both_lib,
+                           'build_target': self.func_build_target,
+                           'configuration_data': self.func_configuration_data,
+                           'configure_file': self.func_configure_file,
+                           'custom_target': self.func_custom_target,
+                           'declare_dependency': self.func_declare_dependency,
+                           'dependency': self.func_dependency,
+                           'disabler': self.func_disabler,
+                           'environment': self.func_environment,
+                           'error': self.func_error,
+                           'executable': self.func_executable,
+                           'files': self.func_files,
+                           'find_library': self.func_find_library,
+                           'find_program': self.func_find_program,
+                           'generator': self.func_generator,
+                           'get_option': self.func_get_option,
+                           'get_variable': self.func_get_variable,
+                           'gettext': self.func_gettext,
+                           'import': self.func_import,
+                           'include_directories': self.func_include_directories,
+                           'install_data': self.func_install_data,
+                           'install_emptydir': self.func_install_emptydir,
+                           'install_headers': self.func_install_headers,
+                           'install_man': self.func_install_man,
+                           'install_subdir': self.func_install_subdir,
+                           'install_symlink': self.func_install_symlink,
+                           'is_disabler': self.func_is_disabler,
+                           'is_variable': self.func_is_variable,
+                           'jar': self.func_jar,
+                           'join_paths': self.func_join_paths,
+                           'library': self.func_library,
+                           'message': self.func_message,
+                           'option': self.func_option,
+                           'project': self.func_project,
+                           'range': self.func_range,
+                           'run_command': self.func_run_command,
+                           'run_target': self.func_run_target,
+                           'set_variable': self.func_set_variable,
+                           'subdir': self.func_subdir,
+                           'shared_library': self.func_shared_lib,
+                           'shared_module': self.func_shared_module,
+                           'static_library': self.func_static_lib,
+                           'subdir_done': self.func_subdir_done,
+                           'subproject': self.func_subproject,
+                           'summary': self.func_summary,
+                           'test': self.func_test,
+                           'unset_variable': self.func_unset_variable,
+                           'vcs_tag': self.func_vcs_tag,
+                           'warning': self.func_warning,
+                           })
+        if 'MESON_UNIT_TEST' in os.environ:
+            self.funcs.update({'exception': self.func_exception})
+
+    def build_holder_map(self) -> None:
+        '''
+            Build a mapping of `HoldableObject` types to their corresponding
+            `ObjectHolder`s. This mapping is used in `InterpreterBase` to automatically
+            holderify all returned values from methods and functions.
+        '''
+        self.holder_map.update({
+            # Primitives
+            list: P_OBJ.ArrayHolder,
+            dict: P_OBJ.DictHolder,
+            int: P_OBJ.IntegerHolder,
+            bool: P_OBJ.BooleanHolder,
+            str: P_OBJ.StringHolder,
+            P_OBJ.MesonVersionString: P_OBJ.MesonVersionStringHolder,
+
+            # Meson types
+            mesonlib.File: OBJ.FileHolder,
+            build.SharedLibrary: OBJ.SharedLibraryHolder,
+            build.StaticLibrary: OBJ.StaticLibraryHolder,
+            build.BothLibraries: OBJ.BothLibrariesHolder,
+            build.SharedModule: OBJ.SharedModuleHolder,
+            build.Executable: OBJ.ExecutableHolder,
+            build.Jar: OBJ.JarHolder,
+            build.CustomTarget: OBJ.CustomTargetHolder,
+            build.CustomTargetIndex: OBJ.CustomTargetIndexHolder,
+            build.Generator: OBJ.GeneratorHolder,
+            build.GeneratedList: OBJ.GeneratedListHolder,
+            build.ExtractedObjects: OBJ.GeneratedObjectsHolder,
+            build.RunTarget: OBJ.RunTargetHolder,
+            build.AliasTarget: OBJ.AliasTargetHolder,
+            build.Headers: OBJ.HeadersHolder,
+            build.Man: OBJ.ManHolder,
+            build.EmptyDir: OBJ.EmptyDirHolder,
+            build.Data: OBJ.DataHolder,
+            build.SymlinkData: OBJ.SymlinkDataHolder,
+            build.InstallDir: OBJ.InstallDirHolder,
+            build.IncludeDirs: OBJ.IncludeDirsHolder,
+            build.EnvironmentVariables: OBJ.EnvironmentVariablesHolder,
+            compilers.RunResult: compilerOBJ.TryRunResultHolder,
+            dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder,
+            coredata.UserFeatureOption: OBJ.FeatureOptionHolder,
+            envconfig.MachineInfo: OBJ.MachineHolder,
+        })
+
+        '''
+            Build a mapping of `HoldableObject` base classes to their
+            corresponding `ObjectHolder`s. The difference to `self.holder_map`
+            is that the keys here define an upper bound instead of requiring an
+            exact match.
+
+            The mappings defined here are only used when there was no direct hit
+            found in `self.holder_map`.
+        '''
+        self.bound_holder_map.update({
+            dependencies.Dependency: OBJ.DependencyHolder,
+            ExternalProgram: OBJ.ExternalProgramHolder,
+            compilers.Compiler: compilerOBJ.CompilerHolder,
+            ModuleObject: OBJ.ModuleObjectHolder,
+            MutableModuleObject: OBJ.MutableModuleObjectHolder,
+        })
+
+    def append_holder_map(self, held_type: T.Type[mesonlib.HoldableObject], holder_type: T.Type[ObjectHolder]) -> None:
+        '''
+            Adds one additional mapping to the `holder_map`.
+
+            The intended use for this function is in the `initialize` method of
+            modules to register custom object holders.
+        '''
+        self.holder_map.update({
+            held_type: holder_type
+        })
+
+    def process_new_values(self, invalues: T.List[T.Union[TYPE_var, ExecutableSerialisation]]) -> None:
+        invalues = listify(invalues)
+        for v in invalues:
+            if isinstance(v, ObjectHolder):
+                raise InterpreterException('Modules must not return ObjectHolders')
+            if isinstance(v, (build.BuildTarget, build.CustomTarget, build.RunTarget)):
+                self.add_target(v.name, v)
+            elif isinstance(v, list):
+                self.process_new_values(v)
+            elif isinstance(v, ExecutableSerialisation):
+                v.subproject = self.subproject
+                self.build.install_scripts.append(v)
+            elif isinstance(v, build.Data):
+                self.build.data.append(v)
+            elif isinstance(v, build.SymlinkData):
+                self.build.symlinks.append(v)
+            elif isinstance(v, dependencies.InternalDependency):
+                # FIXME: This is special cased and not ideal:
+                # The first source is our new VapiTarget, the rest are deps
+                self.process_new_values(v.sources[0])
+            elif isinstance(v, build.InstallDir):
+                self.build.install_dirs.append(v)
+            elif isinstance(v, Test):
+                self.build.tests.append(v)
+            elif isinstance(v, (int, str, bool, Disabler, ObjectHolder, build.GeneratedList,
+                                ExternalProgram)):
+                pass
+            else:
+                raise InterpreterException(f'Module returned a value of unknown type {v!r}.')
+
+    def get_build_def_files(self) -> T.List[str]:
+        return self.build_def_files
+
+    def add_build_def_file(self, f: mesonlib.FileOrString) -> None:
+        # Use relative path for files within source directory, and absolute path
+        # for system files. Skip files within build directory. Also skip not regular
+        # files (e.g. /dev/stdout) Normalize the path to avoid duplicates, this
+        # is especially important to convert '/' to '\' on Windows.
+        if isinstance(f, mesonlib.File):
+            if f.is_built:
+                return
+            f = os.path.normpath(f.relative_name())
+        elif os.path.isfile(f) and not f.startswith('/dev'):
+            srcdir = Path(self.environment.get_source_dir())
+            builddir = Path(self.environment.get_build_dir())
+            try:
+                f = Path(f).resolve()
+            except OSError:
+                f = Path(f)
+                s = f.stat()
+                if (hasattr(s, 'st_file_attributes') and
+                        s.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT != 0 and
+                        s.st_reparse_tag == stat.IO_REPARSE_TAG_APPEXECLINK):
+                    # This is a Windows Store link which we can't
+                    # resolve, so just do our best otherwise.
+                    f = f.parent.resolve() / f.name
+                else:
+                    raise
+            if builddir in f.parents:
+                return
+            if srcdir in f.parents:
+                f = f.relative_to(srcdir)
+            f = str(f)
+        else:
+            return
+        if f not in self.build_def_files:
+            self.build_def_files.append(f)
+
+    def get_variables(self):
+        return self.variables
+
+    def check_stdlibs(self):
+        machine_choices = [MachineChoice.HOST]
+        if self.coredata.is_cross_build():
+            machine_choices.append(MachineChoice.BUILD)
+        for for_machine in machine_choices:
+            props = self.build.environment.properties[for_machine]
+            for l in self.coredata.compilers[for_machine].keys():
+                try:
+                    di = mesonlib.stringlistify(props.get_stdlib(l))
+                except KeyError:
+                    continue
+                if len(di) == 1:
+                    FeatureNew.single_use('stdlib without variable name', '0.56.0', self.subproject, location=self.current_node)
+                kwargs = {'native': for_machine is MachineChoice.BUILD,
+                          }
+                name = l + '_stdlib'
+                df = DependencyFallbacksHolder(self, [name])
+                df.set_fallback(di)
+                dep = df.lookup(kwargs, force_fallback=True)
+                self.build.stdlibs[for_machine][l] = dep
+
+    def _import_module(self, modname: str, required: bool) -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]:
+        if modname in self.modules:
+            return self.modules[modname]
+        try:
+            module = importlib.import_module('mesonbuild.modules.' + modname)
+        except ImportError:
+            if required:
+                raise InvalidArguments(f'Module "{modname}" does not exist')
+            ext_module = NotFoundExtensionModule()
+        else:
+            ext_module = module.initialize(self)
+            assert isinstance(ext_module, (ExtensionModule, NewExtensionModule))
+            self.build.modules.append(modname)
+        self.modules[modname] = ext_module
+        return ext_module
+
+    @typed_pos_args('import', str)
+    @typed_kwargs(
+        'import',
+        REQUIRED_KW.evolve(since='0.59.0'),
+        DISABLER_KW.evolve(since='0.59.0'),
+    )
+    @disablerIfNotFound
+    def func_import(self, node: mparser.BaseNode, args: T.Tuple[str],
+                    kwargs: 'kwargs.FuncImportModule') -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]:
+        modname = args[0]
+        disabled, required, _ = extract_required_kwarg(kwargs, self.subproject)
+        if disabled:
+            return NotFoundExtensionModule()
+
+        if modname.startswith('unstable-'):
+            plainname = modname.split('-', 1)[1]
+            try:
+                # check if stable module exists
+                mod = self._import_module(plainname, required)
+                # XXX: this is actually not helpful, since it doesn't do a version check
+                mlog.warning(f'Module {modname} is now stable, please use the {plainname} module instead.')
+                return mod
+            except InvalidArguments:
+                mlog.warning(f'Module {modname} has no backwards or forwards compatibility and might not exist in future releases.', location=node)
+                modname = 'unstable_' + plainname
+        return self._import_module(modname, required)
+
+    @typed_pos_args('files', varargs=str)
+    @noKwargs
+    def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[mesonlib.File]:
+        return [mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, fname) for fname in args[0]]
+
+    # Used by declare_dependency() and pkgconfig.generate()
+    def extract_variables(self, kwargs, argname='variables', list_new=False, dict_new=False):
+        variables = kwargs.get(argname, {})
+        if isinstance(variables, dict):
+            if dict_new and variables:
+                FeatureNew.single_use(f'{argname} as dictionary', '0.56.0', self.subproject, location=self.current_node)
+        else:
+            varlist = mesonlib.stringlistify(variables)
+            if list_new:
+                FeatureNew.single_use(f'{argname} as list of strings', '0.56.0', self.subproject, location=self.current_node)
+            variables = collections.OrderedDict()
+            for v in varlist:
+                try:
+                    (key, value) = v.split('=', 1)
+                except ValueError:
+                    raise InterpreterException(f'Variable {v!r} must have a value separated by equals sign.')
+                variables[key.strip()] = value.strip()
+        for k, v in variables.items():
+            if not k or not v:
+                raise InterpreterException('Empty variable name or value')
+            if any(c.isspace() for c in k):
+                raise InterpreterException(f'Invalid whitespace in variable name "{k}"')
+            if not isinstance(v, str):
+                raise InterpreterException('variables values must be strings.')
+        return variables
+
+    @FeatureNewKwargs('declare_dependency', '0.46.0', ['link_whole'])
+    @FeatureNewKwargs('declare_dependency', '0.54.0', ['variables'])
+    @permittedKwargs({'include_directories', 'link_with', 'sources', 'dependencies',
+                      'compile_args', 'link_args', 'link_whole', 'version',
+                      'variables'})
+    @noPosargs
+    def func_declare_dependency(self, node, args, kwargs):
+        version = kwargs.get('version', self.project_version)
+        if not isinstance(version, str):
+            raise InterpreterException('Version must be a string.')
+        incs = self.extract_incdirs(kwargs)
+        libs = extract_as_list(kwargs, 'link_with')
+        libs_whole = extract_as_list(kwargs, 'link_whole')
+        sources = extract_as_list(kwargs, 'sources')
+        sources = listify(self.source_strings_to_files(sources))
+        deps = extract_as_list(kwargs, 'dependencies')
+        compile_args = mesonlib.stringlistify(kwargs.get('compile_args', []))
+        link_args = mesonlib.stringlistify(kwargs.get('link_args', []))
+        variables = self.extract_variables(kwargs, list_new=True)
+        final_deps = []
+        for d in deps:
+            if not isinstance(d, (dependencies.Dependency, dependencies.ExternalLibrary, dependencies.InternalDependency)):
+                raise InterpreterException('Dependencies must be external deps')
+            final_deps.append(d)
+        for l in libs:
+            if isinstance(l, dependencies.Dependency):
+                raise InterpreterException('''Entries in "link_with" may only be self-built targets,
+external dependencies (including libraries) must go to "dependencies".''')
+        dep = dependencies.InternalDependency(version, incs, compile_args,
+                                              link_args, libs, libs_whole, sources, final_deps,
+                                              variables)
+        return dep
+
+    @typed_pos_args('assert', bool, optargs=[str])
+    @noKwargs
+    def func_assert(self, node: mparser.FunctionNode, args: T.Tuple[bool, T.Optional[str]],
+                    kwargs: 'TYPE_kwargs') -> None:
+        value, message = args
+        if message is None:
+            FeatureNew.single_use('assert function without message argument', '0.53.0', self.subproject, location=node)
+
+        if not value:
+            if message is None:
+                from ..ast import AstPrinter
+                printer = AstPrinter()
+                node.args.arguments[0].accept(printer)
+                message = printer.result
+            raise InterpreterException('Assert failed: ' + message)
+
+    def validate_arguments(self, args, argcount, arg_types):
+        if argcount is not None:
+            if argcount != len(args):
+                raise InvalidArguments(f'Expected {argcount} arguments, got {len(args)}.')
+        for actual, wanted in zip(args, arg_types):
+            if wanted is not None:
+                if not isinstance(actual, wanted):
+                    raise InvalidArguments('Incorrect argument type.')
+
+    # Executables aren't actually accepted, but we allow them here to allow for
+    # better error messages when overridden
+    @typed_pos_args(
+        'run_command',
+        (build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str),
+        varargs=(build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str))
+    @typed_kwargs(
+        'run_command',
+        KwargInfo('check', (bool, NoneType), since='0.47.0'),
+        KwargInfo('capture', bool, default=True, since='0.47.0'),
+        ENV_KW.evolve(since='0.50.0'),
+    )
+    def func_run_command(self, node: mparser.BaseNode,
+                         args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str],
+                                               T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str]]],
+                         kwargs: 'kwargs.RunCommand') -> RunProcess:
+        return self.run_command_impl(node, args, kwargs)
+
+    def run_command_impl(self,
+                         node: mparser.BaseNode,
+                         args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str],
+                                               T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str]]],
+                         kwargs: 'kwargs.RunCommand',
+                         in_builddir: bool = False) -> RunProcess:
+        cmd, cargs = args
+        capture = kwargs['capture']
+        env = kwargs['env']
+        srcdir = self.environment.get_source_dir()
+        builddir = self.environment.get_build_dir()
+
+        check = kwargs['check']
+        if check is None:
+            mlog.warning(implicit_check_false_warning, once=True)
+            check = False
+
+        m = 'must be a string, or the output of find_program(), files() '\
+            'or configure_file(), or a compiler object; not {!r}'
+        overridden_msg = ('Program {!r} was overridden with the compiled '
+                          'executable {!r} and therefore cannot be used during '
+                          'configuration')
+        expanded_args: T.List[str] = []
+        if isinstance(cmd, build.Executable):
+            progname = node.args.arguments[0].value
+            raise InterpreterException(overridden_msg.format(progname, cmd.description()))
+        if isinstance(cmd, ExternalProgram):
+            if not cmd.found():
+                raise InterpreterException(f'command {cmd.get_name()!r} not found or not executable')
+        elif isinstance(cmd, compilers.Compiler):
+            exelist = cmd.get_exelist()
+            cmd = exelist[0]
+            prog = ExternalProgram(cmd, silent=True)
+            if not prog.found():
+                raise InterpreterException(f'Program {cmd!r} not found or not executable')
+            cmd = prog
+            expanded_args = exelist[1:]
+        else:
+            if isinstance(cmd, mesonlib.File):
+                cmd = cmd.absolute_path(srcdir, builddir)
+            # FIXME: This case can only be reached through configure_file, delete once that is typesafe
+            elif not isinstance(cmd, str):
+                raise InterpreterException('First argument ' + m.format(cmd))
+            # Prefer scripts in the current source directory
+            search_dir = os.path.join(srcdir, self.subdir)
+            prog = ExternalProgram(cmd, silent=True, search_dir=search_dir)
+            if not prog.found():
+                raise InterpreterException(f'Program or command {cmd!r} not found or not executable')
+            cmd = prog
+        for a in cargs:
+            if isinstance(a, str):
+                expanded_args.append(a)
+            elif isinstance(a, mesonlib.File):
+                expanded_args.append(a.absolute_path(srcdir, builddir))
+            elif isinstance(a, ExternalProgram):
+                expanded_args.append(a.get_path())
+            elif isinstance(a, compilers.Compiler):
+                FeatureNew.single_use('Compiler object as a variadic argument to `run_command`', '0.61.0', self.subproject, location=node)
+                prog = ExternalProgram(a.exelist[0], silent=True)
+                if not prog.found():
+                    raise InterpreterException(f'Program {cmd!r} not found or not executable')
+                expanded_args.append(prog.get_path())
+            else:
+                raise InterpreterException(overridden_msg.format(a.name, cmd.description()))
+
+        # If any file that was used as an argument to the command
+        # changes, we must re-run the configuration step.
+        self.add_build_def_file(cmd.get_path())
+        for a in expanded_args:
+            if not os.path.isabs(a):
+                a = os.path.join(builddir if in_builddir else srcdir, self.subdir, a)
+            self.add_build_def_file(a)
+
+        return RunProcess(cmd, expanded_args, env, srcdir, builddir, self.subdir,
+                          self.environment.get_build_command() + ['introspect'],
+                          in_builddir=in_builddir, check=check, capture=capture)
+
+    def func_gettext(self, nodes, args, kwargs):
+        raise InterpreterException('Gettext() function has been moved to module i18n. Import it and use i18n.gettext() instead')
+
+    def func_option(self, nodes, args, kwargs):
+        raise InterpreterException('Tried to call option() in build description file. All options must be in the option file.')
+
+    @FeatureNewKwargs('subproject', '0.38.0', ['default_options'])
+    @permittedKwargs({'version', 'default_options', 'required'})
+    @typed_pos_args('subproject', str)
+    def func_subproject(self, nodes: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> SubprojectHolder:
+        return self.do_subproject(args[0], 'meson', kwargs)
+
+    def disabled_subproject(self, subp_name, disabled_feature=None, exception=None):
+        sub = SubprojectHolder(NullSubprojectInterpreter(), os.path.join(self.subproject_dir, subp_name),
+                               disabled_feature=disabled_feature, exception=exception)
+        self.subprojects[subp_name] = sub
+        self.coredata.initialized_subprojects.add(subp_name)
+        return sub
+
+    def do_subproject(self, subp_name: str, method: str, kwargs):
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
+        if disabled:
+            mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled')
+            return self.disabled_subproject(subp_name, disabled_feature=feature)
+
+        default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
+        default_options = coredata.create_options_dict(default_options, subp_name)
+
+        if subp_name == '':
+            raise InterpreterException('Subproject name must not be empty.')
+        if subp_name[0] == '.':
+            raise InterpreterException('Subproject name must not start with a period.')
+        if '..' in subp_name:
+            raise InterpreterException('Subproject name must not contain a ".." path segment.')
+        if os.path.isabs(subp_name):
+            raise InterpreterException('Subproject name must not be an absolute path.')
+        if has_path_sep(subp_name):
+            mlog.warning('Subproject name has a path separator. This may cause unexpected behaviour.',
+                         location=self.current_node)
+        if subp_name in self.subproject_stack:
+            fullstack = self.subproject_stack + [subp_name]
+            incpath = ' => '.join(fullstack)
+            raise InvalidCode(f'Recursive include of subprojects: {incpath}.')
+        if subp_name in self.subprojects:
+            subproject = self.subprojects[subp_name]
+            if required and not subproject.found():
+                raise InterpreterException(f'Subproject "{subproject.subdir}" required but not found.')
+            return subproject
+
+        r = self.environment.wrap_resolver
+        try:
+            subdir = r.resolve(subp_name, method)
+        except wrap.WrapException as e:
+            if not required:
+                mlog.log(e)
+                mlog.log('Subproject ', mlog.bold(subp_name), 'is buildable:', mlog.red('NO'), '(disabling)')
+                return self.disabled_subproject(subp_name, exception=e)
+            raise e
+
+        subdir_abs = os.path.join(self.environment.get_source_dir(), subdir)
+        os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True)
+        self.global_args_frozen = True
+
+        stack = ':'.join(self.subproject_stack + [subp_name])
+        m = ['\nExecuting subproject', mlog.bold(stack)]
+        if method != 'meson':
+            m += ['method', mlog.bold(method)]
+        mlog.log(*m, '\n', nested=False)
+
+        try:
+            if method == 'meson':
+                return self._do_subproject_meson(subp_name, subdir, default_options, kwargs)
+            elif method == 'cmake':
+                return self._do_subproject_cmake(subp_name, subdir, subdir_abs, default_options, kwargs)
+            else:
+                raise mesonlib.MesonBugException(f'The method {method} is invalid for the subproject {subp_name}')
+        # Invalid code is always an error
+        except InvalidCode:
+            raise
+        except Exception as e:
+            if not required:
+                with mlog.nested(subp_name):
+                    # Suppress the 'ERROR:' prefix because this exception is not
+                    # fatal and VS CI treat any logs with "ERROR:" as fatal.
+                    mlog.exception(e, prefix=mlog.yellow('Exception:'))
+                mlog.log('\nSubproject', mlog.bold(subdir), 'is buildable:', mlog.red('NO'), '(disabling)')
+                return self.disabled_subproject(subp_name, exception=e)
+            raise e
+
+    def _do_subproject_meson(self, subp_name: str, subdir: str, default_options, kwargs,
+                             ast: T.Optional[mparser.CodeBlockNode] = None,
+                             build_def_files: T.Optional[T.List[str]] = None,
+                             is_translated: bool = False) -> SubprojectHolder:
+        with mlog.nested(subp_name):
+            new_build = self.build.copy()
+            subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir,
+                               default_options, ast=ast, is_translated=is_translated)
+            # Those lists are shared by all interpreters. That means that
+            # even if the subproject fails, any modification that the subproject
+            # made to those lists will affect the parent project.
+            subi.subprojects = self.subprojects
+            subi.modules = self.modules
+            subi.holder_map = self.holder_map
+            subi.bound_holder_map = self.bound_holder_map
+            subi.summary = self.summary
+
+            subi.subproject_stack = self.subproject_stack + [subp_name]
+            current_active = self.active_projectname
+            current_warnings_counter = mlog.log_warnings_counter
+            mlog.log_warnings_counter = 0
+            subi.run()
+            subi_warnings = mlog.log_warnings_counter
+            mlog.log_warnings_counter = current_warnings_counter
+
+            mlog.log('Subproject', mlog.bold(subp_name), 'finished.')
+
+        mlog.log()
+
+        if 'version' in kwargs:
+            pv = subi.project_version
+            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.')
+        self.active_projectname = current_active
+        self.subprojects.update(subi.subprojects)
+        self.subprojects[subp_name] = SubprojectHolder(subi, subdir, warnings=subi_warnings)
+        # Duplicates are possible when subproject uses files from project root
+        if build_def_files:
+            self.build_def_files = list(set(self.build_def_files + build_def_files))
+        # We always need the subi.build_def_files, to propgate sub-sub-projects
+        self.build_def_files = list(set(self.build_def_files + subi.build_def_files))
+        self.build.merge(subi.build)
+        self.build.subprojects[subp_name] = subi.project_version
+        self.coredata.initialized_subprojects.add(subp_name)
+        return self.subprojects[subp_name]
+
+    def _do_subproject_cmake(self, subp_name, subdir, subdir_abs, default_options, kwargs):
+        with mlog.nested(subp_name):
+            new_build = self.build.copy()
+            prefix = self.coredata.options[OptionKey('prefix')].value
+
+            from ..modules.cmake import CMakeSubprojectOptions
+            options = kwargs.get('options', CMakeSubprojectOptions())
+            if not isinstance(options, CMakeSubprojectOptions):
+                raise InterpreterException('"options" kwarg must be CMakeSubprojectOptions'
+                                           ' object (created by cmake.subproject_options())')
+
+            cmake_options = mesonlib.stringlistify(kwargs.get('cmake_options', []))
+            cmake_options += options.cmake_options
+            cm_int = CMakeInterpreter(new_build, Path(subdir), Path(subdir_abs), Path(prefix), new_build.environment, self.backend)
+            cm_int.initialise(cmake_options)
+            cm_int.analyse()
+
+            # Generate a meson ast and execute it with the normal do_subproject_meson
+            ast = cm_int.pretend_to_be_meson(options.target_options)
+
+            mlog.log()
+            with mlog.nested('cmake-ast'):
+                mlog.log('Processing generated meson AST')
+
+                # Debug print the generated meson file
+                from ..ast import AstIndentationGenerator, AstPrinter
+                printer = AstPrinter()
+                ast.accept(AstIndentationGenerator())
+                ast.accept(printer)
+                printer.post_process()
+                meson_filename = os.path.join(self.build.environment.get_build_dir(), subdir, 'meson.build')
+                with open(meson_filename, "w", encoding='utf-8') as f:
+                    f.write(printer.result)
+
+                mlog.log('Build file:', meson_filename)
+                mlog.cmd_ci_include(meson_filename)
+                mlog.log()
+
+            result = self._do_subproject_meson(subp_name, subdir, default_options, kwargs, ast, cm_int.bs_files, is_translated=True)
+            result.cm_interpreter = cm_int
+
+        mlog.log()
+        return result
+
+    def get_option_internal(self, optname: str):
+        key = OptionKey.from_string(optname).evolve(subproject=self.subproject)
+
+        if not key.is_project():
+            for opts in [self.coredata.options, compilers.base_options]:
+                v = opts.get(key)
+                if v is None or v.yielding:
+                    v = opts.get(key.as_root())
+                if v is not None:
+                    return v
+
+        try:
+            opt = self.coredata.options[key]
+            if opt.yielding and key.subproject and key.as_root() in self.coredata.options:
+                popt = self.coredata.options[key.as_root()]
+                if type(opt) is type(popt):
+                    opt = popt
+                else:
+                    # Get class name, then option type as a string
+                    opt_type = opt.__class__.__name__[4:][:-6].lower()
+                    popt_type = popt.__class__.__name__[4:][:-6].lower()
+                    # This is not a hard error to avoid dependency hell, the workaround
+                    # when this happens is to simply set the subproject's option directly.
+                    mlog.warning('Option {0!r} of type {1!r} in subproject {2!r} cannot yield '
+                                 'to parent option of type {3!r}, ignoring parent value. '
+                                 'Use -D{2}:{0}=value to set the value for this option manually'
+                                 '.'.format(optname, opt_type, self.subproject, popt_type),
+                                 location=self.current_node)
+            return opt
+        except KeyError:
+            pass
+
+        raise InterpreterException(f'Tried to access unknown option {optname!r}.')
+
+    @typed_pos_args('get_option', str)
+    @noKwargs
+    def func_get_option(self, nodes: mparser.BaseNode, args: T.Tuple[str],
+                        kwargs: 'TYPE_kwargs') -> T.Union[coredata.UserOption, 'TYPE_var']:
+        optname = args[0]
+        if ':' in optname:
+            raise InterpreterException('Having a colon in option name is forbidden, '
+                                       'projects are not allowed to directly access '
+                                       'options of other subprojects.')
+        opt = self.get_option_internal(optname)
+        if isinstance(opt, coredata.UserFeatureOption):
+            opt.name = optname
+            return opt
+        elif isinstance(opt, coredata.UserOption):
+            return opt.value
+        return opt
+
+    @typed_pos_args('configuration_data', optargs=[dict])
+    @noKwargs
+    def func_configuration_data(self, node: mparser.BaseNode, args: T.Optional[dict], kwargs: 'TYPE_kwargs') -> ConfigurationDataObject:
+        initial_values = args[0]
+        if initial_values is not None:
+            FeatureNew.single_use('configuration_data dictionary', '0.49.0', self.subproject, location=node)
+        else:
+            initial_values = {}
+        return ConfigurationDataObject(self.subproject, initial_values)
+
+    def set_backend(self):
+        # The backend is already set when parsing subprojects
+        if self.backend is not None:
+            return
+        backend = self.coredata.get_option(OptionKey('backend'))
+        from ..backend import backends
+        self.backend = backends.get_backend_from_name(backend, self.build, self)
+
+        if self.backend is None:
+            raise InterpreterException(f'Unknown backend "{backend}".')
+        if backend != self.backend.name:
+            if self.backend.name.startswith('vs'):
+                mlog.log('Auto detected Visual Studio backend:', mlog.bold(self.backend.name))
+            self.coredata.set_option(OptionKey('backend'), self.backend.name)
+
+        # Only init backend options on first invocation otherwise it would
+        # override values previously set from command line.
+        if self.environment.first_invocation:
+            self.coredata.init_backend_options(backend)
+
+        options = {k: v for k, v in self.environment.options.items() if k.is_backend()}
+        self.coredata.set_options(options)
+
+    @typed_pos_args('project', str, varargs=str)
+    @typed_kwargs(
+        'project',
+        DEFAULT_OPTIONS,
+        KwargInfo('meson_version', (str, NoneType)),
+        KwargInfo(
+            'version',
+            (str, mesonlib.File, NoneType, list),
+            default='undefined',
+            validator=_project_version_validator,
+            convertor=lambda x: x[0] if isinstance(x, list) else x,
+        ),
+        KwargInfo('license', ContainerTypeInfo(list, str), default=['unknown'], listify=True),
+        KwargInfo('subproject_dir', str, default='subprojects'),
+    )
+    def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str]], kwargs: 'kwargs.Project') -> None:
+        proj_name, proj_langs = args
+        if ':' in proj_name:
+            raise InvalidArguments(f"Project name {proj_name!r} must not contain ':'")
+
+        # This needs to be evaluated as early as possible, as meson uses this
+        # for things like deprecation testing.
+        if kwargs['meson_version']:
+            cv = coredata.version
+            pv = kwargs['meson_version']
+            if not mesonlib.version_compare(cv, pv):
+                raise InterpreterException(f'Meson version is {cv} but project requires {pv}')
+            mesonlib.project_meson_versions[self.subproject] = kwargs['meson_version']
+
+        if os.path.exists(self.option_file):
+            oi = optinterpreter.OptionInterpreter(self.subproject)
+            oi.process(self.option_file)
+            self.coredata.update_project_options(oi.options)
+            self.add_build_def_file(self.option_file)
+
+        # Do not set default_options on reconfigure otherwise it would override
+        # values previously set from command line. That means that changing
+        # default_options in a project will trigger a reconfigure but won't
+        # have any effect.
+        self.project_default_options = coredata.create_options_dict(
+            kwargs['default_options'], self.subproject)
+
+        # If this is the first invocation we always need to initialize
+        # builtins, if this is a subproject that is new in a re-invocation we
+        # need to initialize builtins for that
+        if self.environment.first_invocation or (self.subproject != '' and self.subproject not in self.coredata.initialized_subprojects):
+            default_options = self.project_default_options.copy()
+            default_options.update(self.default_project_options)
+            self.coredata.init_builtins(self.subproject)
+        else:
+            default_options = {}
+        self.coredata.set_default_options(default_options, self.subproject, self.environment)
+
+        if not self.is_subproject():
+            self.build.project_name = proj_name
+        self.active_projectname = proj_name
+
+        version = kwargs['version']
+        if isinstance(version, mesonlib.File):
+            FeatureNew.single_use('version from file', '0.57.0', self.subproject, location=node)
+            self.add_build_def_file(version)
+            ifname = version.absolute_path(self.environment.source_dir,
+                                           self.environment.build_dir)
+            try:
+                ver_data = Path(ifname).read_text(encoding='utf-8').split('\n')
+            except FileNotFoundError:
+                raise InterpreterException('Version file not found.')
+            if len(ver_data) == 2 and ver_data[1] == '':
+                ver_data = ver_data[0:1]
+            if len(ver_data) != 1:
+                raise InterpreterException('Version file must contain exactly one line of text.')
+            self.project_version = ver_data[0]
+        else:
+            self.project_version = version
+
+        if self.build.project_version is None:
+            self.build.project_version = self.project_version
+        proj_license = kwargs['license']
+        self.build.dep_manifest[proj_name] = build.DepManifest(self.project_version, proj_license)
+        if self.subproject in self.build.projects:
+            raise InvalidCode('Second call to project().')
+
+        # spdirname is the subproject_dir for this project, relative to self.subdir.
+        # self.subproject_dir is the subproject_dir for the main project, relative to top source dir.
+        spdirname = kwargs['subproject_dir']
+        if not isinstance(spdirname, str):
+            raise InterpreterException('Subproject_dir must be a string')
+        if os.path.isabs(spdirname):
+            raise InterpreterException('Subproject_dir must not be an absolute path.')
+        if spdirname.startswith('.'):
+            raise InterpreterException('Subproject_dir must not begin with a period.')
+        if '..' in spdirname:
+            raise InterpreterException('Subproject_dir must not contain a ".." segment.')
+        if not self.is_subproject():
+            self.subproject_dir = spdirname
+        self.build.subproject_dir = self.subproject_dir
+
+        # Load wrap files from this (sub)project.
+        wrap_mode = self.coredata.get_option(OptionKey('wrap_mode'))
+        if not self.is_subproject() or wrap_mode != WrapMode.nopromote:
+            subdir = os.path.join(self.subdir, spdirname)
+            r = wrap.Resolver(self.environment.get_source_dir(), subdir, self.subproject, wrap_mode)
+            if self.is_subproject():
+                self.environment.wrap_resolver.merge_wraps(r)
+            else:
+                self.environment.wrap_resolver = r
+
+        self.build.projects[self.subproject] = proj_name
+        mlog.log('Project name:', mlog.bold(proj_name))
+        mlog.log('Project version:', mlog.bold(self.project_version))
+
+        if not self.is_subproject():
+            # We have to activate VS before adding languages and before calling
+            # self.set_backend() otherwise it wouldn't be able to detect which
+            # vs backend version we need. But after setting default_options in case
+            # the project sets vs backend by default.
+            backend = self.coredata.get_option(OptionKey('backend'))
+            force_vsenv = self.user_defined_options.vsenv or backend.startswith('vs')
+            if mesonlib.setup_vsenv(force_vsenv):
+                self.build.need_vsenv = True
+
+        self.add_languages(proj_langs, True, MachineChoice.HOST)
+        self.add_languages(proj_langs, False, MachineChoice.BUILD)
+
+        self.set_backend()
+        if not self.is_subproject():
+            self.check_stdlibs()
+
+    @typed_kwargs('add_languages', KwargInfo('native', (bool, NoneType), since='0.54.0'), REQUIRED_KW)
+    @typed_pos_args('add_languages', varargs=str)
+    def func_add_languages(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwargs.FuncAddLanguages') -> bool:
+        langs = args[0]
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
+        native = kwargs['native']
+
+        if disabled:
+            for lang in sorted(langs, key=compilers.sort_clink):
+                mlog.log('Compiler for language', mlog.bold(lang), 'skipped: feature', mlog.bold(feature), 'disabled')
+            return False
+        if native is not None:
+            return self.add_languages(langs, required, self.machine_from_native_kwarg(kwargs))
+        else:
+            # absent 'native' means 'both' for backwards compatibility
+            tv = FeatureNew.get_target_version(self.subproject)
+            if FeatureNew.check_version(tv, '0.54.0'):
+                mlog.warning('add_languages is missing native:, assuming languages are wanted for both host and build.',
+                             location=node)
+
+            success = self.add_languages(langs, False, MachineChoice.BUILD)
+            success &= self.add_languages(langs, required, MachineChoice.HOST)
+            return success
+
+    @noArgsFlattening
+    @noKwargs
+    def func_message(self, node, args, kwargs):
+        if len(args) > 1:
+            FeatureNew.single_use('message with more than one argument', '0.54.0', self.subproject, location=node)
+        args_str = [stringifyUserArguments(i) for i in args]
+        self.message_impl(args_str)
+
+    def message_impl(self, args):
+        mlog.log(mlog.bold('Message:'), *args)
+
+    @noArgsFlattening
+    @FeatureNew('summary', '0.53.0')
+    @typed_pos_args('summary', (str, dict), optargs=[object])
+    @typed_kwargs(
+        'summary',
+        KwargInfo('section', str, default=''),
+        KwargInfo('bool_yn', bool, default=False),
+        KwargInfo('list_sep', (str, NoneType), since='0.54.0')
+    )
+    def func_summary(self, node: mparser.BaseNode, args: T.Tuple[T.Union[str, T.Dict[str, T.Any]], T.Optional[T.Any]],
+                     kwargs: 'kwargs.Summary') -> None:
+        if args[1] is None:
+            if not isinstance(args[0], dict):
+                raise InterpreterException('Summary first argument must be dictionary.')
+            values = args[0]
+        else:
+            if not isinstance(args[0], str):
+                raise InterpreterException('Summary first argument must be string.')
+            values = {args[0]: args[1]}
+        self.summary_impl(kwargs['section'], values, kwargs)
+
+    def summary_impl(self, section: str, values, kwargs: 'kwargs.Summary') -> None:
+        if self.subproject not in self.summary:
+            self.summary[self.subproject] = Summary(self.active_projectname, self.project_version)
+        self.summary[self.subproject].add_section(
+            section, values, kwargs['bool_yn'], kwargs['list_sep'], self.subproject)
+
+    def _print_summary(self) -> None:
+        # Add automatic 'Supbrojects' section in main project.
+        all_subprojects = collections.OrderedDict()
+        for name, subp in sorted(self.subprojects.items()):
+            value = subp.found()
+            if subp.disabled_feature:
+                value = [value, f'Feature {subp.disabled_feature!r} disabled']
+            elif subp.exception:
+                value = [value, str(subp.exception)]
+            elif subp.warnings > 0:
+                value = [value, f'{subp.warnings} warnings']
+            all_subprojects[name] = value
+        if all_subprojects:
+            self.summary_impl('Subprojects', all_subprojects,
+                              {'bool_yn': True,
+                               'list_sep': ' ',
+                              })
+        # Add automatic section with all user defined options
+        if self.user_defined_options:
+            values = collections.OrderedDict()
+            if self.user_defined_options.cross_file:
+                values['Cross files'] = self.user_defined_options.cross_file
+            if self.user_defined_options.native_file:
+                values['Native files'] = self.user_defined_options.native_file
+            sorted_options = sorted(self.user_defined_options.cmd_line_options.items())
+            values.update({str(k): v for k, v in sorted_options})
+            if values:
+                self.summary_impl('User defined options', values, {'bool_yn': False, 'list_sep': None})
+        # Print all summaries, main project last.
+        mlog.log('')  # newline
+        main_summary = self.summary.pop('', None)
+        for subp_name, summary in sorted(self.summary.items()):
+            if self.subprojects[subp_name].found():
+                summary.dump()
+        if main_summary:
+            main_summary.dump()
+
+    @noArgsFlattening
+    @FeatureNew('warning', '0.44.0')
+    @noKwargs
+    def func_warning(self, node, args, kwargs):
+        if len(args) > 1:
+            FeatureNew.single_use('warning with more than one argument', '0.54.0', self.subproject, location=node)
+        args_str = [stringifyUserArguments(i) for i in args]
+        mlog.warning(*args_str, location=node)
+
+    @noArgsFlattening
+    @noKwargs
+    def func_error(self, node, args, kwargs):
+        if len(args) > 1:
+            FeatureNew.single_use('error with more than one argument', '0.58.0', self.subproject, location=node)
+        args_str = [stringifyUserArguments(i) for i in args]
+        raise InterpreterException('Problem encountered: ' + ' '.join(args_str))
+
+    @noKwargs
+    @noPosargs
+    def func_exception(self, node, args, kwargs):
+        raise Exception()
+
+    def add_languages(self, args: T.Sequence[str], required: bool, for_machine: MachineChoice) -> bool:
+        success = self.add_languages_for(args, required, for_machine)
+        if not self.coredata.is_cross_build():
+            self.coredata.copy_build_options_from_regular_ones()
+        self._redetect_machines()
+        return success
+
+    def should_skip_sanity_check(self, for_machine: MachineChoice) -> bool:
+        should = self.environment.properties.host.get('skip_sanity_check', False)
+        if not isinstance(should, bool):
+            raise InterpreterException('Option skip_sanity_check must be a boolean.')
+        if for_machine != MachineChoice.HOST and not should:
+            return False
+        if not self.environment.is_cross_build() and not should:
+            return False
+        return should
+
+    def add_languages_for(self, args: T.List[str], required: bool, for_machine: MachineChoice) -> None:
+        args = [a.lower() for a in args]
+        langs = set(self.coredata.compilers[for_machine].keys())
+        langs.update(args)
+        # We'd really like to add cython's default language here, but it can't
+        # actually be done because the cython compiler hasn't been initialized,
+        # so we can't actually get the option yet. Because we can't know what
+        # compiler to add by default, and we don't want to add unnecessary
+        # compilers we don't add anything for cython here, and instead do it
+        # When the first cython target using a particular language is used.
+        if 'vala' in langs and 'c' not in langs:
+            FeatureNew.single_use('Adding Vala language without C', '0.59.0', self.subproject, location=self.current_node)
+            args.append('c')
+
+        success = True
+        for lang in sorted(args, key=compilers.sort_clink):
+            clist = self.coredata.compilers[for_machine]
+            machine_name = for_machine.get_lower_case_name()
+            if lang in clist:
+                comp = clist[lang]
+            else:
+                try:
+                    comp = compilers.detect_compiler_for(self.environment, lang, for_machine)
+                    if comp is None:
+                        raise InvalidArguments(f'Tried to use unknown language "{lang}".')
+                    if self.should_skip_sanity_check(for_machine):
+                        mlog.log_once('Cross compiler sanity tests disabled via the cross file.')
+                    else:
+                        comp.sanity_check(self.environment.get_scratch_dir(), self.environment)
+                except Exception:
+                    if not required:
+                        mlog.log('Compiler for language',
+                                 mlog.bold(lang), 'for the', machine_name,
+                                 'machine not found.')
+                        success = False
+                        continue
+                    else:
+                        raise
+
+            if for_machine == MachineChoice.HOST or self.environment.is_cross_build():
+                logger_fun = mlog.log
+            else:
+                logger_fun = mlog.debug
+            logger_fun(comp.get_display_language(), 'compiler for the', machine_name, 'machine:',
+                       mlog.bold(' '.join(comp.get_exelist())), comp.get_version_string())
+            if comp.linker is not None:
+                logger_fun(comp.get_display_language(), 'linker for the', machine_name, 'machine:',
+                           mlog.bold(' '.join(comp.linker.get_exelist())), comp.linker.id, comp.linker.version)
+            self.build.ensure_static_linker(comp)
+
+        return success
+
+    def program_from_file_for(self, for_machine, prognames):
+        for p in prognames:
+            if isinstance(p, mesonlib.File):
+                continue # Always points to a local (i.e. self generated) file.
+            if not isinstance(p, str):
+                raise InterpreterException('Executable name must be a string')
+            prog = ExternalProgram.from_bin_list(self.environment, for_machine, p)
+            if prog.found():
+                return prog
+        return None
+
+    def program_from_system(self, args, search_dirs, extra_info):
+        # Search for scripts relative to current subdir.
+        # Do not cache found programs because find_program('foobar')
+        # might give different results when run from different source dirs.
+        source_dir = os.path.join(self.environment.get_source_dir(), self.subdir)
+        for exename in args:
+            if isinstance(exename, mesonlib.File):
+                if exename.is_built:
+                    search_dir = os.path.join(self.environment.get_build_dir(),
+                                              exename.subdir)
+                else:
+                    search_dir = os.path.join(self.environment.get_source_dir(),
+                                              exename.subdir)
+                exename = exename.fname
+                extra_search_dirs = []
+            elif isinstance(exename, str):
+                search_dir = source_dir
+                extra_search_dirs = search_dirs
+            else:
+                raise InvalidArguments(f'find_program only accepts strings and files, not {exename!r}')
+            extprog = ExternalProgram(exename, search_dir=search_dir,
+                                      extra_search_dirs=extra_search_dirs,
+                                      silent=True)
+            if extprog.found():
+                extra_info.append(f"({' '.join(extprog.get_command())})")
+                return extprog
+
+    def program_from_overrides(self, command_names: T.List[str], extra_info: T.List['mlog.TV_Loggable']) -> \
+            T.Optional[T.Union[ExternalProgram, 'OverrideProgram', 'build.Executable']]:
+        for name in command_names:
+            if not isinstance(name, str):
+                continue
+            if name in self.build.find_overrides:
+                exe = self.build.find_overrides[name]
+                extra_info.append(mlog.blue('(overridden)'))
+                return exe
+        return None
+
+    def store_name_lookups(self, command_names):
+        for name in command_names:
+            if isinstance(name, str):
+                self.build.searched_programs.add(name)
+
+    def add_find_program_override(self, name: str, exe: T.Union[build.Executable, ExternalProgram, 'OverrideProgram']) -> None:
+        if name in self.build.searched_programs:
+            raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.')
+        if name in self.build.find_overrides:
+            raise InterpreterException(f'Tried to override executable "{name}" which has already been overridden.')
+        self.build.find_overrides[name] = exe
+
+    def notfound_program(self, args):
+        return NonExistingExternalProgram(' '.join(args))
+
+    # TODO update modules to always pass `for_machine`. It is bad-form to assume
+    # the host machine.
+    def find_program_impl(self, args: T.List[mesonlib.FileOrString],
+                          for_machine: MachineChoice = MachineChoice.HOST,
+                          required: bool = True, silent: bool = True,
+                          wanted: T.Union[str, T.List[str]] = '',
+                          search_dirs: T.Optional[T.List[str]] = None,
+                          version_func: T.Optional[T.Callable[[T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']], str]] = None
+                          ) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']:
+        args = mesonlib.listify(args)
+
+        extra_info = []
+        progobj = self.program_lookup(args, for_machine, required, search_dirs, extra_info)
+        if progobj is None:
+            progobj = self.notfound_program(args)
+
+        if isinstance(progobj, ExternalProgram) and not progobj.found():
+            if not silent:
+                mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'))
+            if required:
+                m = 'Program {!r} not found or not executable'
+                raise InterpreterException(m.format(progobj.get_name()))
+            return progobj
+
+        if wanted:
+            if version_func:
+                version = version_func(progobj)
+            elif isinstance(progobj, build.Executable):
+                interp = self
+                if progobj.subproject:
+                    interp = self.subprojects[progobj.subproject].held_object
+                    assert isinstance(interp, Interpreter)
+                version = interp.project_version
+            else:
+                version = progobj.get_version(self)
+            is_found, not_found, found = mesonlib.version_compare_many(version, wanted)
+            if not is_found:
+                mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.red('NO'),
+                         'found', mlog.normal_cyan(version), 'but need:',
+                         mlog.bold(', '.join([f"'{e}'" for e in not_found])), *extra_info)
+                if required:
+                    m = 'Invalid version of program, need {!r} {!r} found {!r}.'
+                    raise InterpreterException(m.format(progobj.name, not_found, version))
+                return self.notfound_program(args)
+            extra_info.insert(0, mlog.normal_cyan(version))
+
+        # Only store successful lookups
+        self.store_name_lookups(args)
+        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
+
+    def program_lookup(self, args, for_machine, required, search_dirs, extra_info):
+        progobj = self.program_from_overrides(args, extra_info)
+        if progobj:
+            return progobj
+
+        fallback = None
+        wrap_mode = self.coredata.get_option(OptionKey('wrap_mode'))
+        if wrap_mode != WrapMode.nofallback and self.environment.wrap_resolver:
+            fallback = self.environment.wrap_resolver.find_program_provider(args)
+        if fallback and wrap_mode == WrapMode.forcefallback:
+            return self.find_program_fallback(fallback, args, required, extra_info)
+
+        progobj = self.program_from_file_for(for_machine, args)
+        if progobj is None:
+            progobj = self.program_from_system(args, search_dirs, extra_info)
+        if progobj is None and args[0].endswith('python3'):
+            prog = ExternalProgram('python3', mesonlib.python_command, silent=True)
+            progobj = prog if prog.found() else None
+        if progobj is None and fallback and required:
+            progobj = self.find_program_fallback(fallback, args, required, extra_info)
+
+        return progobj
+
+    def find_program_fallback(self, fallback, args, required, extra_info):
+        mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program',
+                 mlog.bold(' '.join(args)))
+        sp_kwargs = {'required': required}
+        self.do_subproject(fallback, 'meson', sp_kwargs)
+        return self.program_from_overrides(args, extra_info)
+
+    @typed_pos_args('find_program', varargs=(str, mesonlib.File), min_varargs=1)
+    @typed_kwargs(
+        'find_program',
+        DISABLER_KW.evolve(since='0.49.0'),
+        NATIVE_KW,
+        REQUIRED_KW,
+        KwargInfo('dirs', ContainerTypeInfo(list, str), default=[], listify=True, since='0.53.0'),
+        KwargInfo('version', ContainerTypeInfo(list, str), default=[], listify=True, since='0.52.0'),
+    )
+    @disablerIfNotFound
+    def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonlib.FileOrString]],
+                          kwargs: 'kwargs.FindProgram',
+                          ) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']:
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
+        if disabled:
+            mlog.log('Program', mlog.bold(' '.join(args[0])), 'skipped: feature', mlog.bold(feature), 'disabled')
+            return self.notfound_program(args[0])
+
+        search_dirs = extract_search_dirs(kwargs)
+        return self.find_program_impl(args[0], kwargs['native'], required=required,
+                                      silent=False, wanted=kwargs['version'],
+                                      search_dirs=search_dirs)
+
+    def func_find_library(self, node, args, kwargs):
+        raise InvalidCode('find_library() is removed, use meson.get_compiler(\'name\').find_library() instead.\n'
+                          'Look here for documentation: http://mesonbuild.com/Reference-manual.html#compiler-object\n'
+                          'Look here for example: http://mesonbuild.com/howtox.html#add-math-library-lm-portably\n'
+                          )
+
+    # When adding kwargs, please check if they make sense in dependencies.get_dep_identifier()
+    @FeatureNewKwargs('dependency', '0.57.0', ['cmake_package_version'])
+    @FeatureNewKwargs('dependency', '0.56.0', ['allow_fallback'])
+    @FeatureNewKwargs('dependency', '0.54.0', ['components'])
+    @FeatureNewKwargs('dependency', '0.52.0', ['include_type'])
+    @FeatureNewKwargs('dependency', '0.50.0', ['not_found_message', 'cmake_module_path', 'cmake_args'])
+    @FeatureNewKwargs('dependency', '0.49.0', ['disabler'])
+    @FeatureNewKwargs('dependency', '0.40.0', ['method'])
+    @FeatureNewKwargs('dependency', '0.38.0', ['default_options'])
+    @disablerIfNotFound
+    @permittedKwargs(permitted_dependency_kwargs)
+    @typed_pos_args('dependency', varargs=str, min_varargs=1)
+    def func_dependency(self, node, args, kwargs):
+        # Replace '' by empty list of names
+        names = [n for n in args[0] if n]
+        if len(names) > 1:
+            FeatureNew('dependency with more than one name', '0.60.0').use(self.subproject)
+        allow_fallback = kwargs.get('allow_fallback')
+        if allow_fallback is not None and not isinstance(allow_fallback, bool):
+            raise InvalidArguments('"allow_fallback" argument must be boolean')
+        fallback = kwargs.get('fallback')
+        default_options = kwargs.get('default_options')
+        df = DependencyFallbacksHolder(self, names, allow_fallback, default_options)
+        df.set_fallback(fallback)
+        not_found_message = kwargs.get('not_found_message', '')
+        if not isinstance(not_found_message, str):
+            raise InvalidArguments('The not_found_message must be a string.')
+        try:
+            d = df.lookup(kwargs)
+        except Exception:
+            if not_found_message:
+                self.message_impl([not_found_message])
+            raise
+        assert isinstance(d, Dependency)
+        if not d.found() and not_found_message:
+            self.message_impl([not_found_message])
+            self.message_impl([not_found_message])
+        # Ensure the correct include type
+        if 'include_type' in kwargs:
+            wanted = kwargs['include_type']
+            if not isinstance(wanted, str):
+                raise InvalidArguments('The `include_type` kwarg must be a string')
+            actual = d.get_include_type()
+            if wanted != actual:
+                mlog.debug(f'Current include type of {args[0]} is {actual}. Converting to requested {wanted}')
+                d = d.generate_system_dependency(wanted)
+        return d
+
+    @FeatureNew('disabler', '0.44.0')
+    @noKwargs
+    @noPosargs
+    def func_disabler(self, node, args, kwargs):
+        return Disabler()
+
+    @FeatureNewKwargs('executable', '0.42.0', ['implib'])
+    @FeatureNewKwargs('executable', '0.56.0', ['win_subsystem'])
+    @FeatureDeprecatedKwargs('executable', '0.56.0', ['gui_app'], extra_message="Use 'win_subsystem' instead.")
+    @permittedKwargs(build.known_exe_kwargs)
+    def func_executable(self, node, args, kwargs):
+        return self.build_target(node, args, kwargs, build.Executable)
+
+    @permittedKwargs(build.known_stlib_kwargs)
+    def func_static_lib(self, node, args, kwargs):
+        return self.build_target(node, args, kwargs, build.StaticLibrary)
+
+    @permittedKwargs(build.known_shlib_kwargs)
+    def func_shared_lib(self, node, args, kwargs):
+        holder = self.build_target(node, args, kwargs, build.SharedLibrary)
+        holder.shared_library_only = True
+        return holder
+
+    @permittedKwargs(known_library_kwargs)
+    def func_both_lib(self, node, args, kwargs):
+        return self.build_both_libraries(node, args, kwargs)
+
+    @FeatureNew('shared_module', '0.37.0')
+    @permittedKwargs(build.known_shmod_kwargs)
+    def func_shared_module(self, node, args, kwargs):
+        return self.build_target(node, args, kwargs, build.SharedModule)
+
+    @permittedKwargs(known_library_kwargs)
+    def func_library(self, node, args, kwargs):
+        return self.build_library(node, args, kwargs)
+
+    @permittedKwargs(build.known_jar_kwargs)
+    def func_jar(self, node, args, kwargs):
+        return self.build_target(node, args, kwargs, build.Jar)
+
+    @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options'])
+    @permittedKwargs(known_build_target_kwargs)
+    def func_build_target(self, node, args, kwargs):
+        if 'target_type' not in kwargs:
+            raise InterpreterException('Missing target_type keyword argument')
+        target_type = kwargs.pop('target_type')
+        if target_type == 'executable':
+            return self.build_target(node, args, kwargs, build.Executable)
+        elif target_type == 'shared_library':
+            return self.build_target(node, args, kwargs, build.SharedLibrary)
+        elif target_type == 'shared_module':
+            FeatureNew('build_target(target_type: \'shared_module\')',
+                       '0.51.0').use(self.subproject)
+            return self.build_target(node, args, kwargs, build.SharedModule)
+        elif target_type == 'static_library':
+            return self.build_target(node, args, kwargs, build.StaticLibrary)
+        elif target_type == 'both_libraries':
+            return self.build_both_libraries(node, args, kwargs)
+        elif target_type == 'library':
+            return self.build_library(node, args, kwargs)
+        elif target_type == 'jar':
+            return self.build_target(node, args, kwargs, build.Jar)
+        else:
+            raise InterpreterException('Unknown target_type.')
+
+    @permittedKwargs({'input', 'output', 'fallback', 'command', 'replace_string'})
+    @noPosargs
+    def func_vcs_tag(self, node, args, kwargs):
+        if 'input' not in kwargs or 'output' not in kwargs:
+            raise InterpreterException('Keyword arguments input and output must exist')
+        if 'fallback' not in kwargs:
+            FeatureNew.single_use('Optional fallback in vcs_tag', '0.41.0', self.subproject, location=node)
+        fallback = kwargs.pop('fallback', self.project_version)
+        if not isinstance(fallback, str):
+            raise InterpreterException('Keyword argument fallback must be a string.')
+        replace_string = kwargs.pop('replace_string', '@VCS_TAG@')
+        regex_selector = '(.*)' # default regex selector for custom command: use complete output
+        vcs_cmd = kwargs.get('command', None)
+        if vcs_cmd and not isinstance(vcs_cmd, list):
+            vcs_cmd = [vcs_cmd]
+        source_dir = os.path.normpath(os.path.join(self.environment.get_source_dir(), self.subdir))
+        if vcs_cmd:
+            # Is the command an executable in path or maybe a script in the source tree?
+            vcs_cmd[0] = shutil.which(vcs_cmd[0]) or os.path.join(source_dir, vcs_cmd[0])
+        else:
+            vcs = mesonlib.detect_vcs(source_dir)
+            if vcs:
+                mlog.log('Found {} repository at {}'.format(vcs['name'], vcs['wc_dir']))
+                vcs_cmd = vcs['get_rev'].split()
+                regex_selector = vcs['rev_regex']
+            else:
+                vcs_cmd = [' '] # executing this cmd will fail in vcstagger.py and force to use the fallback string
+        # vcstagger.py parameters: infile, outfile, fallback, source_dir, replace_string, regex_selector, command...
+        kwargs['command'] = self.environment.get_build_command() + \
+            ['--internal',
+             'vcstagger',
+             '@INPUT0@',
+             '@OUTPUT0@',
+             fallback,
+             source_dir,
+             replace_string,
+             regex_selector] + vcs_cmd
+        kwargs.setdefault('build_by_default', True)
+        kwargs.setdefault('build_always_stale', True)
+        return self._func_custom_target_impl(node, [kwargs['output']], kwargs)
+
+    @FeatureNew('subdir_done', '0.46.0')
+    @noPosargs
+    @noKwargs
+    def func_subdir_done(self, node, args, kwargs):
+        raise SubdirDoneRequest()
+
+    @typed_pos_args('custom_target', optargs=[str])
+    @typed_kwargs(
+        'custom_target',
+        COMMAND_KW,
+        CT_BUILD_ALWAYS,
+        CT_BUILD_ALWAYS_STALE,
+        CT_BUILD_BY_DEFAULT,
+        CT_INPUT_KW,
+        CT_INSTALL_DIR_KW,
+        CT_INSTALL_TAG_KW,
+        CT_OUTPUT_KW,
+        DEPENDS_KW,
+        DEPEND_FILES_KW,
+        DEPFILE_KW,
+        ENV_KW.evolve(since='0.57.0'),
+        INSTALL_KW,
+        INSTALL_MODE_KW.evolve(since='0.47.0'),
+        OVERRIDE_OPTIONS_KW,
+        KwargInfo('feed', bool, default=False, since='0.59.0'),
+        KwargInfo('capture', bool, default=False),
+        KwargInfo('console', bool, default=False, since='0.48.0'),
+    )
+    def func_custom_target(self, node: mparser.FunctionNode, args: T.Tuple[str],
+                           kwargs: 'kwargs.CustomTarget') -> build.CustomTarget:
+        if kwargs['depfile'] and ('@BASENAME@' in kwargs['depfile'] or '@PLAINNAME@' in kwargs['depfile']):
+            FeatureNew.single_use('substitutions in custom_target depfile', '0.47.0', self.subproject, location=node)
+
+        # Don't mutate the kwargs
+        kwargs = kwargs.copy()
+
+        # Remap build_always to build_by_default and build_always_stale
+        if kwargs['build_always'] is not None and kwargs['build_always_stale'] is not None:
+            raise InterpreterException('CustomTarget: "build_always" and "build_always_stale" are mutually exclusive')
+
+        if kwargs['build_by_default'] is None and kwargs['install']:
+            kwargs['build_by_default'] = True
+
+        elif kwargs['build_always'] is not None:
+            if kwargs['build_by_default'] is None:
+                kwargs['build_by_default'] = kwargs['build_always']
+            kwargs['build_always_stale'] = kwargs['build_by_default']
+
+            # Set this to None to satisfy process_kwargs
+            kwargs['build_always'] = None
+
+        # These are are nullaable so that we can know whether they're explicitly
+        # set or not. If they haven't been overwritten, set them to their true
+        # default
+        if kwargs['build_by_default'] is None:
+            kwargs['build_by_default'] = False
+        if kwargs['build_always_stale'] is None:
+            kwargs['build_always_stale'] = False
+
+        return self._func_custom_target_impl(node, args, kwargs)
+
+    def _func_custom_target_impl(self, node, args, kwargs):
+        'Implementation-only, without FeatureNew checks, for internal use'
+        name = args[0]
+        if name is None:
+            # name will default to first output, but we cannot do that yet because
+            # they could need substitutions (e.g. @BASENAME@) first. CustomTarget()
+            # will take care of setting a proper default but name must be an empty
+            # string in the meantime.
+            FeatureNew('custom_target() with no name argument', '0.60.0', location=node).use(self.subproject)
+            name = ''
+        kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs)
+        if 'input' in kwargs:
+            kwargs['input'] = self.source_strings_to_files(extract_as_list(kwargs, 'input'), strict=False)
+        kwargs['env'] = self.unpack_env_kwarg(kwargs)
+        if 'command' in kwargs and isinstance(kwargs['command'], list) and kwargs['command']:
+            if isinstance(kwargs['command'][0], str):
+                kwargs['command'][0] = self.find_program_impl([kwargs['command'][0]])
+        tg = build.CustomTarget(name, self.subdir, self.subproject, kwargs, backend=self.backend)
+        self.add_target(tg.name, tg)
+        return tg
+
+    @typed_pos_args('run_target', str)
+    @typed_kwargs(
+        'run_target',
+        COMMAND_KW,
+        DEPENDS_KW,
+        ENV_KW.evolve(since='0.57.0'),
+    )
+    def func_run_target(self, node: mparser.FunctionNode, args: T.Tuple[str],
+                        kwargs: 'kwargs.RunTarget') -> build.RunTarget:
+        all_args = kwargs['command'].copy()
+
+        for i in listify(all_args):
+            if isinstance(i, ExternalProgram) and not i.found():
+                raise InterpreterException(f'Tried to use non-existing executable {i.name!r}')
+        if isinstance(all_args[0], str):
+            all_args[0] = self.find_program_impl([all_args[0]])
+        name = args[0]
+        tg = build.RunTarget(name, all_args, kwargs['depends'], self.subdir, self.subproject, kwargs['env'])
+        self.add_target(name, tg)
+        full_name = (self.subproject, name)
+        assert full_name not in self.build.run_target_names
+        self.build.run_target_names.add(full_name)
+        return tg
+
+    @FeatureNew('alias_target', '0.52.0')
+    @typed_pos_args('alias_target', str, varargs=build.Target, min_varargs=1)
+    @noKwargs
+    def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[build.Target]],
+                          kwargs: 'TYPE_kwargs') -> build.AliasTarget:
+        name, deps = args
+        tg = build.AliasTarget(name, deps, self.subdir, self.subproject)
+        self.add_target(name, tg)
+        return tg
+
+    @typed_pos_args('generator', (build.Executable, ExternalProgram))
+    @typed_kwargs(
+        'generator',
+        KwargInfo('arguments', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True),
+        KwargInfo('output', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True),
+        DEPFILE_KW,
+        DEPENDS_KW,
+        KwargInfo('capture', bool, default=False, since='0.43.0'),
+    )
+    def func_generator(self, node: mparser.FunctionNode,
+                       args: T.Tuple[T.Union[build.Executable, ExternalProgram]],
+                       kwargs: 'kwargs.FuncGenerator') -> build.Generator:
+        for rule in kwargs['output']:
+            if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule:
+                raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.')
+            if has_path_sep(rule):
+                raise InvalidArguments('"output" must not contain a directory separator.')
+        if len(kwargs['output']) > 1:
+            for o in kwargs['output']:
+                if '@OUTPUT@' in o:
+                    raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.')
+
+        gen = build.Generator(args[0], **kwargs)
+        self.generators.append(gen)
+        return gen
+
+    @typed_pos_args('benchmark', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File))
+    @typed_kwargs('benchmark', *TEST_KWARGS)
+    def func_benchmark(self, node: mparser.BaseNode,
+                       args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]],
+                       kwargs: 'kwargs.FuncBenchmark') -> None:
+        self.add_test(node, args, kwargs, False)
+
+    @typed_pos_args('test', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File))
+    @typed_kwargs('test', *TEST_KWARGS, KwargInfo('is_parallel', bool, default=True))
+    def func_test(self, node: mparser.BaseNode,
+                  args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]],
+                  kwargs: 'kwargs.FuncTest') -> None:
+        self.add_test(node, args, kwargs, True)
+
+    def unpack_env_kwarg(self, kwargs: T.Union[build.EnvironmentVariables, T.Dict[str, 'TYPE_var'], T.List['TYPE_var'], str]) -> build.EnvironmentVariables:
+        envlist = kwargs.get('env')
+        if envlist is None:
+            return build.EnvironmentVariables()
+        msg = ENV_KW.validator(envlist)
+        if msg:
+            raise InvalidArguments(f'"env": {msg}')
+        return ENV_KW.convertor(envlist)
+
+    def make_test(self, node: mparser.BaseNode,
+                  args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]],
+                  kwargs: 'kwargs.BaseTest') -> Test:
+        name = args[0]
+        if ':' in name:
+            mlog.deprecation(f'":" is not allowed in test name "{name}", it has been replaced with "_"',
+                             location=node)
+            name = name.replace(':', '_')
+        exe = args[1]
+        if isinstance(exe, mesonlib.File):
+            exe = self.find_program_impl([exe])
+
+        env = self.unpack_env_kwarg(kwargs)
+
+        if kwargs['timeout'] <= 0:
+            FeatureNew.single_use('test() timeout <= 0', '0.57.0', self.subproject, location=node)
+
+        prj = self.subproject if self.is_subproject() else self.build.project_name
+
+        suite: T.List[str] = []
+        for s in kwargs['suite']:
+            if s:
+                s = ':' + s
+            suite.append(prj.replace(' ', '_').replace(':', '_') + s)
+
+        return Test(name,
+                    prj,
+                    suite,
+                    exe,
+                    kwargs['depends'],
+                    kwargs.get('is_parallel', False),
+                    kwargs['args'],
+                    env,
+                    kwargs['should_fail'],
+                    kwargs['timeout'],
+                    kwargs['workdir'],
+                    kwargs['protocol'],
+                    kwargs['priority'])
+
+    def add_test(self, node: mparser.BaseNode, args: T.List, kwargs: T.Dict[str, T.Any], is_base_test: bool):
+        t = self.make_test(node, args, kwargs)
+        if is_base_test:
+            self.build.tests.append(t)
+            mlog.debug('Adding test', mlog.bold(t.name, True))
+        else:
+            self.build.benchmarks.append(t)
+            mlog.debug('Adding benchmark', mlog.bold(t.name, True))
+
+    @typed_pos_args('install_headers', varargs=(str, mesonlib.File))
+    @typed_kwargs(
+        'install_headers',
+        KwargInfo('install_dir', (str, NoneType)),
+        KwargInfo('subdir', (str, NoneType)),
+        INSTALL_MODE_KW.evolve(since='0.47.0'),
+    )
+    def func_install_headers(self, node: mparser.BaseNode,
+                             args: T.Tuple[T.List['mesonlib.FileOrString']],
+                             kwargs: 'kwargs.FuncInstallHeaders') -> build.Headers:
+        source_files = self.source_strings_to_files(args[0])
+        install_subdir = kwargs['subdir']
+        if install_subdir is not None and os.path.isabs(install_subdir):
+            mlog.deprecation('Subdir keyword must not be an absolute path. This will be a hard error in the next release.')
+
+        h = build.Headers(source_files, install_subdir, kwargs['install_dir'],
+                          kwargs['install_mode'], self.subproject)
+        self.build.headers.append(h)
+
+        return h
+
+    @typed_pos_args('install_man', varargs=(str, mesonlib.File))
+    @typed_kwargs(
+        'install_man',
+        KwargInfo('install_dir', (str, NoneType)),
+        KwargInfo('locale', (str, NoneType), since='0.58.0'),
+        INSTALL_MODE_KW.evolve(since='0.47.0')
+    )
+    def func_install_man(self, node: mparser.BaseNode,
+                         args: T.Tuple[T.List['mesonlib.FileOrString']],
+                         kwargs: 'kwargs.FuncInstallMan') -> build.Man:
+        # We just need to narrow this, because the input is limited to files and
+        # Strings as inputs, so only Files will be returned
+        sources = self.source_strings_to_files(args[0])
+        for s in sources:
+            try:
+                num = int(s.rsplit('.', 1)[-1])
+            except (IndexError, ValueError):
+                num = 0
+            if not 1 <= num <= 9:
+                raise InvalidArguments('Man file must have a file extension of a number between 1 and 9')
+
+        m = build.Man(sources, kwargs['install_dir'], kwargs['install_mode'],
+                      self.subproject, kwargs['locale'])
+        self.build.man.append(m)
+
+        return m
+
+    @FeatureNew('install_emptydir', '0.60.0')
+    @typed_kwargs(
+        'install_emptydir',
+        INSTALL_MODE_KW
+    )
+    def func_install_emptydir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs) -> None:
+        d = build.EmptyDir(args[0], kwargs['install_mode'], self.subproject)
+        self.build.emptydir.append(d)
+
+        return d
+
+    @FeatureNew('install_symlink', '0.61.0')
+    @typed_pos_args('symlink_name', str)
+    @typed_kwargs(
+        'install_symlink',
+        KwargInfo('pointing_to', str, required=True),
+        KwargInfo('install_dir', str, required=True),
+        KwargInfo('install_tag', (str, NoneType)),
+    )
+    def func_install_symlink(self, node: mparser.BaseNode,
+                             args: T.Tuple[T.List[str]],
+                             kwargs) -> build.SymlinkData:
+        name = args[0] # Validation while creating the SymlinkData object
+        target = kwargs['pointing_to']
+        l = build.SymlinkData(target, name, kwargs['install_dir'],
+                              self.subproject, kwargs['install_tag'])
+        self.build.symlinks.append(l)
+        return l
+
+    @typed_pos_args('subdir', str)
+    @typed_kwargs(
+        'subdir',
+        KwargInfo(
+            'if_found',
+            ContainerTypeInfo(list, object),
+            validator=lambda a: 'Objects must have a found() method' if not all(hasattr(x, 'found') for x in a) else None,
+            since='0.44.0',
+            default=[],
+            listify=True,
+        ),
+    )
+    def func_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwargs.Subdir') -> None:
+        mesonlib.check_direntry_issues(args)
+        if '..' in args[0]:
+            raise InvalidArguments('Subdir contains ..')
+        if self.subdir == '' and args[0] == self.subproject_dir:
+            raise InvalidArguments('Must not go into subprojects dir with subdir(), use subproject() instead.')
+        if self.subdir == '' and args[0].startswith('meson-'):
+            raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().')
+        for i in kwargs['if_found']:
+            if not i.found():
+                return
+
+        prev_subdir = self.subdir
+        subdir = os.path.join(prev_subdir, args[0])
+        if os.path.isabs(subdir):
+            raise InvalidArguments('Subdir argument must be a relative path.')
+        absdir = os.path.join(self.environment.get_source_dir(), subdir)
+        symlinkless_dir = os.path.realpath(absdir)
+        build_file = os.path.join(symlinkless_dir, 'meson.build')
+        if build_file in self.processed_buildfiles:
+            raise InvalidArguments(f'Tried to enter directory "{subdir}", which has already been visited.')
+        self.processed_buildfiles.add(build_file)
+        self.subdir = subdir
+        os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True)
+        buildfilename = os.path.join(self.subdir, environment.build_filename)
+        self.build_def_files.append(buildfilename)
+        absname = os.path.join(self.environment.get_source_dir(), buildfilename)
+        if not os.path.isfile(absname):
+            self.subdir = prev_subdir
+            raise InterpreterException(f"Non-existent build file '{buildfilename!s}'")
+        with open(absname, encoding='utf-8') as f:
+            code = f.read()
+        assert isinstance(code, str)
+        try:
+            codeblock = mparser.Parser(code, absname).parse()
+        except mesonlib.MesonException as me:
+            me.file = absname
+            raise me
+        try:
+            self.evaluate_codeblock(codeblock)
+        except SubdirDoneRequest:
+            pass
+        self.subdir = prev_subdir
+
+    def _get_kwarg_install_mode(self, kwargs: T.Dict[str, T.Any]) -> T.Optional[FileMode]:
+        if kwargs.get('install_mode', None) is None:
+            return None
+        if isinstance(kwargs['install_mode'], FileMode):
+            return kwargs['install_mode']
+        install_mode: T.List[str] = []
+        mode = mesonlib.typeslistify(kwargs.get('install_mode', []), (str, int))
+        for m in mode:
+            # We skip any arguments that are set to `false`
+            if m is False:
+                m = None
+            install_mode.append(m)
+        if len(install_mode) > 3:
+            raise InvalidArguments('Keyword argument install_mode takes at '
+                                   'most 3 arguments.')
+        if len(install_mode) > 0 and install_mode[0] is not None and \
+           not isinstance(install_mode[0], str):
+            raise InvalidArguments('Keyword argument install_mode requires the '
+                                   'permissions arg to be a string or false')
+        return FileMode(*install_mode)
+
+    @typed_pos_args('install_data', varargs=(str, mesonlib.File))
+    @typed_kwargs(
+        'install_data',
+        KwargInfo('install_dir', (str, NoneType)),
+        KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File)), listify=True, default=[]),
+        KwargInfo('rename', ContainerTypeInfo(list, str), default=[], listify=True, since='0.46.0'),
+        INSTALL_MODE_KW.evolve(since='0.38.0'),
+        KwargInfo('install_tag', (str, NoneType), since='0.60.0'),
+    )
+    def func_install_data(self, node: mparser.BaseNode,
+                          args: T.Tuple[T.List['mesonlib.FileOrString']],
+                          kwargs: 'kwargs.FuncInstallData') -> build.Data:
+        sources = self.source_strings_to_files(args[0] + kwargs['sources'])
+        rename = kwargs['rename'] or None
+        if rename:
+            if len(rename) != len(sources):
+                raise InvalidArguments(
+                    '"rename" and "sources" argument lists must be the same length if "rename" is given. '
+                    f'Rename has {len(rename)} elements and sources has {len(sources)}.')
+
+        install_dir_name = kwargs['install_dir']
+        if install_dir_name:
+            if not os.path.isabs(install_dir_name):
+                install_dir_name = os.path.join('{datadir}', install_dir_name)
+        else:
+            install_dir_name = '{datadir}'
+        return self.install_data_impl(sources, kwargs['install_dir'], kwargs['install_mode'],
+                                      rename, kwargs['install_tag'], install_dir_name)
+
+    def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: str,
+                          install_mode: FileMode, rename: T.Optional[str],
+                          tag: T.Optional[str],
+                          install_dir_name: T.Optional[str] = None,
+                          install_data_type: T.Optional[str] = None) -> build.Data:
+
+        """Just the implementation with no validation."""
+        data = build.Data(sources, install_dir, install_dir_name or install_dir, install_mode,
+                          self.subproject, rename, tag, install_data_type)
+        self.build.data.append(data)
+        return data
+
+    @typed_pos_args('install_subdir', str)
+    @typed_kwargs(
+        'install_subdir',
+        KwargInfo('install_dir', str, required=True),
+        KwargInfo('install_tag', (str, NoneType), since='0.60.0'),
+        KwargInfo('strip_directory', bool, default=False),
+        KwargInfo('exclude_files', ContainerTypeInfo(list, str),
+                  default=[], listify=True, since='0.42.0',
+                  validator=lambda x: 'cannot be absolute' if any(os.path.isabs(d) for d in x) else None),
+        KwargInfo('exclude_directories', ContainerTypeInfo(list, str),
+                  default=[], listify=True, since='0.42.0',
+                  validator=lambda x: 'cannot be absolute' if any(os.path.isabs(d) for d in x) else None),
+        INSTALL_MODE_KW.evolve(since='0.38.0'),
+    )
+    def func_install_subdir(self, node: mparser.BaseNode, args: T.Tuple[str],
+                            kwargs: 'kwargs.FuncInstallSubdir') -> build.InstallDir:
+        exclude = (set(kwargs['exclude_files']), set(kwargs['exclude_directories']))
+        idir = build.InstallDir(
+            self.subdir,
+            args[0],
+            kwargs['install_dir'],
+            kwargs['install_mode'],
+            exclude,
+            kwargs['strip_directory'],
+            self.subproject,
+            install_tag=kwargs['install_tag'])
+        self.build.install_dirs.append(idir)
+        return idir
+
+    @FeatureNewKwargs('configure_file', '0.47.0', ['copy', 'output_format', 'install_mode', 'encoding'])
+    @FeatureNewKwargs('configure_file', '0.46.0', ['format'])
+    @FeatureNewKwargs('configure_file', '0.41.0', ['capture'])
+    @FeatureNewKwargs('configure_file', '0.50.0', ['install'])
+    @FeatureNewKwargs('configure_file', '0.52.0', ['depfile'])
+    @FeatureNewKwargs('configure_file', '0.60.0', ['install_tag'])
+    @permittedKwargs({'input', 'output', 'configuration', 'command', 'copy', 'depfile',
+                      'install_dir', 'install_mode', 'capture', 'install', 'format',
+                      'output_format', 'encoding', 'install_tag'})
+    @noPosargs
+    def func_configure_file(self, node, args, kwargs):
+        if 'output' not in kwargs:
+            raise InterpreterException('Required keyword argument "output" not defined.')
+        actions = {'configuration', 'command', 'copy'}.intersection(kwargs.keys())
+        if len(actions) == 0:
+            raise InterpreterException('Must specify an action with one of these '
+                                       'keyword arguments: \'configuration\', '
+                                       '\'command\', or \'copy\'.')
+        elif len(actions) == 2:
+            raise InterpreterException('Must not specify both {!r} and {!r} '
+                                       'keyword arguments since they are '
+                                       'mutually exclusive.'.format(*actions))
+        elif len(actions) == 3:
+            raise InterpreterException('Must specify one of {!r}, {!r}, and '
+                                       '{!r} keyword arguments since they are '
+                                       'mutually exclusive.'.format(*actions))
+        if 'capture' in kwargs:
+            if not isinstance(kwargs['capture'], bool):
+                raise InterpreterException('"capture" keyword must be a boolean.')
+            if 'command' not in kwargs:
+                raise InterpreterException('"capture" keyword requires "command" keyword.')
+
+        if 'format' in kwargs:
+            fmt = kwargs['format']
+            if not isinstance(fmt, str):
+                raise InterpreterException('"format" keyword must be a string.')
+        else:
+            fmt = 'meson'
+
+        if fmt not in ('meson', 'cmake', 'cmake@'):
+            raise InterpreterException('"format" possible values are "meson", "cmake" or "cmake@".')
+
+        if 'output_format' in kwargs:
+            output_format = kwargs['output_format']
+            if not isinstance(output_format, str):
+                raise InterpreterException('"output_format" keyword must be a string.')
+        else:
+            output_format = 'c'
+
+        if output_format not in ('c', 'nasm'):
+            raise InterpreterException('"format" possible values are "c" or "nasm".')
+
+        if 'depfile' in kwargs:
+            depfile = kwargs['depfile']
+            if not isinstance(depfile, str):
+                raise InterpreterException('depfile file name must be a string')
+        else:
+            depfile = None
+
+        # Validate input
+        inputs = self.source_strings_to_files(extract_as_list(kwargs, 'input'))
+        inputs_abs = []
+        for f in inputs:
+            if isinstance(f, mesonlib.File):
+                inputs_abs.append(f.absolute_path(self.environment.source_dir,
+                                                  self.environment.build_dir))
+                self.add_build_def_file(f)
+            else:
+                raise InterpreterException('Inputs can only be strings or file objects')
+        # Validate output
+        output = kwargs['output']
+        if not isinstance(output, str):
+            raise InterpreterException('Output file name must be a string')
+        if inputs_abs:
+            values = mesonlib.get_filenames_templates_dict(inputs_abs, None)
+            outputs = mesonlib.substitute_values([output], values)
+            output = outputs[0]
+            if depfile:
+                depfile = mesonlib.substitute_values([depfile], values)[0]
+        ofile_rpath = os.path.join(self.subdir, output)
+        if ofile_rpath in self.configure_file_outputs:
+            mesonbuildfile = os.path.join(self.subdir, 'meson.build')
+            current_call = f"{mesonbuildfile}:{self.current_lineno}"
+            first_call = "{}:{}".format(mesonbuildfile, self.configure_file_outputs[ofile_rpath])
+            mlog.warning('Output file', mlog.bold(ofile_rpath, True), 'for configure_file() at', current_call, 'overwrites configure_file() output at', first_call)
+        else:
+            self.configure_file_outputs[ofile_rpath] = self.current_lineno
+        if os.path.dirname(output) != '':
+            raise InterpreterException('Output file name must not contain a subdirectory.')
+        (ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output))
+        ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname)
+        # Perform the appropriate action
+        if 'configuration' in kwargs:
+            conf = kwargs['configuration']
+            if isinstance(conf, dict):
+                FeatureNew.single_use('configure_file.configuration dictionary', '0.49.0', self.subproject, location=node)
+                conf = ConfigurationDataObject(self.subproject, conf)
+            elif not isinstance(conf, ConfigurationDataObject):
+                raise InterpreterException('Argument "configuration" is not of type configuration_data')
+            mlog.log('Configuring', mlog.bold(output), 'using configuration')
+            if len(inputs) > 1:
+                raise InterpreterException('At most one input file can given in configuration mode')
+            if inputs:
+                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,
+                                          fmt, file_encoding)
+                if missing_variables:
+                    var_list = ", ".join(map(repr, sorted(missing_variables)))
+                    mlog.warning(
+                        f"The variable(s) {var_list} in the input file '{inputs[0]}' are not "
+                        "present in the given configuration data.", location=node)
+                if confdata_useless:
+                    ifbase = os.path.basename(inputs_abs[0])
+                    tv = FeatureNew.get_target_version(self.subproject)
+                    if FeatureNew.check_version(tv, '0.47.0'):
+                        mlog.warning('Got an empty configuration_data() object and found no '
+                                     f'substitutions in the input file {ifbase!r}. If you want to '
+                                     '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()
+        elif 'command' in kwargs:
+            if len(inputs) > 1:
+                FeatureNew.single_use('multiple inputs in configure_file()', '0.52.0', self.subproject, location=node)
+            # We use absolute paths for input and output here because the cwd
+            # that the command is run from is 'unspecified', so it could change.
+            # Currently it's builddir/subdir for in_builddir else srcdir/subdir.
+            values = mesonlib.get_filenames_templates_dict(inputs_abs, [ofile_abs])
+            if depfile:
+                depfile = os.path.join(self.environment.get_scratch_dir(), depfile)
+                values['@DEPFILE@'] = depfile
+            # Substitute @INPUT@, @OUTPUT@, etc here.
+            _cmd = mesonlib.substitute_values(kwargs['command'], values)
+            mlog.log('Configuring', mlog.bold(output), 'with command')
+            cmd, *args = mesonlib.listify(_cmd)
+            res = self.run_command_impl(node, (cmd, args),
+                                        {'capture': True, 'check': True, 'env': build.EnvironmentVariables()},
+                                         True)
+            if 'capture' in kwargs and kwargs['capture']:
+                dst_tmp = ofile_abs + '~'
+                file_encoding = kwargs.setdefault('encoding', 'utf-8')
+                with open(dst_tmp, 'w', encoding=file_encoding) as f:
+                    f.writelines(res.stdout)
+                if inputs_abs:
+                    shutil.copymode(inputs_abs[0], dst_tmp)
+                mesonlib.replace_if_different(ofile_abs, dst_tmp)
+            if depfile:
+                mlog.log('Reading depfile:', mlog.bold(depfile))
+                with open(depfile, encoding='utf-8') as f:
+                    df = DepFile(f.readlines())
+                    deps = df.get_all_dependencies(ofile_fname)
+                    for dep in deps:
+                        self.add_build_def_file(dep)
+
+        elif 'copy' in kwargs:
+            if len(inputs_abs) != 1:
+                raise InterpreterException('Exactly one input file must be given in copy mode')
+            os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
+            shutil.copy2(inputs_abs[0], ofile_abs)
+        else:
+            # Not reachable
+            raise AssertionError
+        # Install file if requested, we check for the empty string
+        # for backwards compatibility. That was the behaviour before
+        # 0.45.0 so preserve it.
+        idir = kwargs.get('install_dir', '')
+        if idir is False:
+            idir = ''
+            FeatureDeprecated.single_use('configure_file install_dir: false', '0.50.0',
+                                         self.subproject, 'Use the `install:` kwarg instead', location=node)
+        if not isinstance(idir, str):
+            if isinstance(idir, list) and len(idir) == 0:
+                mlog.deprecation('install_dir: kwarg must be a string and not an empty array. '
+                                 'Please use the install: kwarg to enable or disable installation. '
+                                 'This will be a hard error in the next release.')
+            else:
+                raise InterpreterException('"install_dir" must be a string')
+        install = kwargs.get('install', idir != '')
+        if not isinstance(install, bool):
+            raise InterpreterException('"install" must be a boolean')
+        if install:
+            if not idir:
+                raise InterpreterException('"install_dir" must be specified '
+                                           'when "install" in a configure_file '
+                                           'is true')
+            cfile = mesonlib.File.from_built_file(ofile_path, ofile_fname)
+            install_mode = self._get_kwarg_install_mode(kwargs)
+            install_tag = kwargs.get('install_tag')
+            if install_tag is not None and not isinstance(install_tag, str):
+                raise InvalidArguments('install_tag keyword argument must be string')
+            self.build.data.append(build.Data([cfile], idir, idir, install_mode, self.subproject,
+                                              install_tag=install_tag, data_type='configure'))
+        return mesonlib.File.from_built_file(self.subdir, output)
+
+    def extract_incdirs(self, kwargs):
+        prospectives = extract_as_list(kwargs, 'include_directories')
+        result = []
+        for p in prospectives:
+            if isinstance(p, build.IncludeDirs):
+                result.append(p)
+            elif isinstance(p, str):
+                result.append(self.build_incdir_object([p]))
+            else:
+                raise InterpreterException('Include directory objects can only be created from strings or include directories.')
+        return result
+
+    @typed_pos_args('include_directories', varargs=str)
+    @typed_kwargs('include_directories', KwargInfo('is_system', bool, default=False))
+    def func_include_directories(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]],
+                                 kwargs: 'kwargs.FuncIncludeDirectories') -> build.IncludeDirs:
+        return self.build_incdir_object(args[0], kwargs['is_system'])
+
+    def build_incdir_object(self, incdir_strings: T.List[str], is_system: bool = False) -> build.IncludeDirs:
+        if not isinstance(is_system, bool):
+            raise InvalidArguments('Is_system must be boolean.')
+        src_root = self.environment.get_source_dir()
+        build_root = self.environment.get_build_dir()
+        absbase_src = os.path.join(src_root, self.subdir)
+        absbase_build = os.path.join(build_root, self.subdir)
+
+        for a in incdir_strings:
+            if a.startswith(src_root):
+                raise InvalidArguments(textwrap.dedent('''\
+                    Tried to form an absolute path to a source dir.
+                    You should not do that but use relative paths instead.
+
+                    To get include path to any directory relative to the current dir do
+
+                    incdir = include_directories(dirname)
+
+                    After this incdir will contain both the current source dir as well as the
+                    corresponding build dir. It can then be used in any subdirectory and
+                    Meson will take care of all the busywork to make paths work.
+
+                    Dirname can even be '.' to mark the current directory. Though you should
+                    remember that the current source and build directories are always
+                    put in the include directories by default so you only need to do
+                    include_directories('.') if you intend to use the result in a
+                    different subdirectory.
+                    '''))
+            else:
+                try:
+                    self.validate_within_subproject(self.subdir, a)
+                except InterpreterException:
+                    mlog.warning('include_directories sandbox violation!')
+                    print(textwrap.dedent(f'''\
+                        The project is trying to access the directory {a} which belongs to a different
+                        subproject. This is a problem as it hardcodes the relative paths of these two projects.
+                        This makes it impossible to compile the project in any other directory layout and also
+                        prevents the subproject from changing its own directory layout.
+
+                        Instead of poking directly at the internals the subproject should be executed and
+                        it should set a variable that the caller can then use. Something like:
+
+                        # In subproject
+                        some_dep = declare_dependency(include_directories: include_directories('include'))
+
+                        # In subproject wrap file
+                        [provide]
+                        some = some_dep
+
+                        # In parent project
+                        some_dep = dependency('some')
+                        executable(..., dependencies: [some_dep])
+
+                        This warning will become a hard error in a future Meson release.
+                        '''))
+            absdir_src = os.path.join(absbase_src, a)
+            absdir_build = os.path.join(absbase_build, a)
+            if not os.path.isdir(absdir_src) and not os.path.isdir(absdir_build):
+                raise InvalidArguments(f'Include dir {a} does not exist.')
+        i = build.IncludeDirs(self.subdir, incdir_strings, is_system)
+        return i
+
+    @typed_pos_args('add_test_setup', str)
+    @typed_kwargs(
+        'add_test_setup',
+        KwargInfo('exe_wrapper', ContainerTypeInfo(list, (str, ExternalProgram)), listify=True, default=[]),
+        KwargInfo('gdb', bool, default=False),
+        KwargInfo('timeout_multiplier', int, default=1),
+        KwargInfo('exclude_suites', ContainerTypeInfo(list, str), listify=True, default=[], since='0.57.0'),
+        KwargInfo('is_default', bool, default=False, since='0.49.0'),
+        ENV_KW,
+    )
+    def func_add_test_setup(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwargs.AddTestSetup') -> None:
+        setup_name = args[0]
+        if re.fullmatch('([_a-zA-Z][_0-9a-zA-Z]*:)?[_a-zA-Z][_0-9a-zA-Z]*', setup_name) is None:
+            raise InterpreterException('Setup name may only contain alphanumeric characters.')
+        if ":" not in setup_name:
+            setup_name = f'{(self.subproject if self.subproject else self.build.project_name)}:{setup_name}'
+
+        exe_wrapper: T.List[str] = []
+        for i in kwargs['exe_wrapper']:
+            if isinstance(i, str):
+                exe_wrapper.append(i)
+            else:
+                if not i.found():
+                    raise InterpreterException('Tried to use non-found executable.')
+                exe_wrapper += i.get_command()
+
+        timeout_multiplier = kwargs['timeout_multiplier']
+        if timeout_multiplier <= 0:
+            FeatureNew('add_test_setup() timeout_multiplier <= 0', '0.57.0').use(self.subproject)
+
+        if kwargs['is_default']:
+            if self.build.test_setup_default_name is not None:
+                raise InterpreterException(f'{self.build.test_setup_default_name!r} is already set as default. '
+                                           'is_default can be set to true only once')
+            self.build.test_setup_default_name = setup_name
+        self.build.test_setups[setup_name] = build.TestSetup(exe_wrapper, kwargs['gdb'], timeout_multiplier, kwargs['env'],
+                                                             kwargs['exclude_suites'])
+
+    @typed_pos_args('add_global_arguments', varargs=str)
+    @typed_kwargs('add_global_arguments', NATIVE_KW, LANGUAGE_KW)
+    def func_add_global_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
+        self._add_global_arguments(node, self.build.global_args[kwargs['native']], args[0], kwargs)
+
+    @typed_pos_args('add_global_link_arguments', varargs=str)
+    @typed_kwargs('add_global_arguments', NATIVE_KW, LANGUAGE_KW)
+    def func_add_global_link_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
+        self._add_global_arguments(node, self.build.global_link_args[kwargs['native']], args[0], kwargs)
+
+    @typed_pos_args('add_project_arguments', varargs=str)
+    @typed_kwargs('add_project_arguments', NATIVE_KW, LANGUAGE_KW)
+    def func_add_project_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
+        self._add_project_arguments(node, self.build.projects_args[kwargs['native']], args[0], kwargs)
+
+    @typed_pos_args('add_project_link_arguments', varargs=str)
+    @typed_kwargs('add_global_arguments', NATIVE_KW, LANGUAGE_KW)
+    def func_add_project_link_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
+        self._add_project_arguments(node, self.build.projects_link_args[kwargs['native']], args[0], kwargs)
+
+    def _warn_about_builtin_args(self, args: T.List[str]) -> None:
+        # -Wpedantic is deliberately not included, since some people want to use it but not use -Wextra
+        # see e.g.
+        # https://github.com/mesonbuild/meson/issues/3275#issuecomment-641354956
+        # https://github.com/mesonbuild/meson/issues/3742
+        warnargs = ('/W1', '/W2', '/W3', '/W4', '/Wall', '-Wall', '-Wextra')
+        optargs = ('-O0', '-O2', '-O3', '-Os', '-Oz', '/O1', '/O2', '/Os')
+        for arg in args:
+            if arg in warnargs:
+                mlog.warning(f'Consider using the built-in warning_level option instead of using "{arg}".',
+                             location=self.current_node)
+            elif arg in optargs:
+                mlog.warning(f'Consider using the built-in optimization level instead of using "{arg}".',
+                             location=self.current_node)
+            elif arg == '-Werror':
+                mlog.warning(f'Consider using the built-in werror option instead of using "{arg}".',
+                             location=self.current_node)
+            elif arg == '-g':
+                mlog.warning(f'Consider using the built-in debug option instead of using "{arg}".',
+                             location=self.current_node)
+            elif arg.startswith('-fsanitize'):
+                mlog.warning(f'Consider using the built-in option for sanitizers instead of using "{arg}".',
+                             location=self.current_node)
+            elif arg.startswith('-std=') or arg.startswith('/std:'):
+                mlog.warning(f'Consider using the built-in option for language standard version instead of using "{arg}".',
+                             location=self.current_node)
+
+    def _add_global_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.List[str]],
+                              args: T.List[str], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
+        if self.is_subproject():
+            msg = f'Function \'{node.func_name}\' cannot be used in subprojects because ' \
+                  'there is no way to make that reliable.\nPlease only call ' \
+                  'this if is_subproject() returns false. Alternatively, ' \
+                  'define a variable that\ncontains your language-specific ' \
+                  'arguments and add it to the appropriate *_args kwarg ' \
+                  'in each target.'
+            raise InvalidCode(msg)
+        frozen = self.project_args_frozen or self.global_args_frozen
+        self._add_arguments(node, argsdict, frozen, args, kwargs)
+
+    def _add_project_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.Dict[str, T.List[str]]],
+                               args: T.List[str], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
+        if self.subproject not in argsdict:
+            argsdict[self.subproject] = {}
+        self._add_arguments(node, argsdict[self.subproject],
+                            self.project_args_frozen, args, kwargs)
+
+    def _add_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.List[str]],
+                       args_frozen: bool, args: T.List[str], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
+        if args_frozen:
+            msg = f'Tried to use \'{node.func_name}\' after a build target has been declared.\n' \
+                  'This is not permitted. Please declare all arguments before your targets.'
+            raise InvalidCode(msg)
+
+        self._warn_about_builtin_args(args)
+
+        for lang in kwargs['language']:
+            argsdict[lang] = argsdict.get(lang, []) + args
+
+    @noKwargs
+    @noArgsFlattening
+    @typed_pos_args('environment', optargs=[(str, list, dict)])
+    def func_environment(self, node: mparser.FunctionNode, args: T.Tuple[T.Union[None, str, T.List['TYPE_var'], T.Dict[str, 'TYPE_var']]],
+                         kwargs: 'TYPE_kwargs') -> build.EnvironmentVariables:
+        init = args[0]
+        if init is not None:
+            FeatureNew.single_use('environment positional arguments', '0.52.0', self.subproject, location=node)
+            msg = ENV_KW.validator(init)
+            if msg:
+                raise InvalidArguments(f'"environment": {msg}')
+            return ENV_KW.convertor(init)
+        return build.EnvironmentVariables()
+
+    @typed_pos_args('join_paths', varargs=str, min_varargs=1)
+    @noKwargs
+    def func_join_paths(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> str:
+        return os.path.join(*args[0]).replace('\\', '/')
+
+    def run(self) -> None:
+        super().run()
+        mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets))))
+        FeatureNew.report(self.subproject)
+        FeatureDeprecated.report(self.subproject)
+        if not self.is_subproject():
+            self.print_extra_warnings()
+        if self.subproject == '':
+            self._print_summary()
+
+    def print_extra_warnings(self) -> None:
+        # TODO cross compilation
+        for c in self.coredata.compilers.host.values():
+            if c.get_id() == 'clang':
+                self.check_clang_asan_lundef()
+                break
+
+    def check_clang_asan_lundef(self) -> None:
+        if OptionKey('b_lundef') not in self.coredata.options:
+            return
+        if OptionKey('b_sanitize') not in self.coredata.options:
+            return
+        if (self.coredata.options[OptionKey('b_lundef')].value and
+                self.coredata.options[OptionKey('b_sanitize')].value != 'none'):
+            mlog.warning('''Trying to use {} sanitizer on Clang with b_lundef.
+This will probably not work.
+Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey('b_sanitize')].value),
+                         location=self.current_node)
+
+    # Check that the indicated file is within the same subproject
+    # as we currently are. This is to stop people doing
+    # nasty things like:
+    #
+    # f = files('../../master_src/file.c')
+    #
+    # Note that this is validated only when the file
+    # object is generated. The result can be used in a different
+    # subproject than it is defined in (due to e.g. a
+    # declare_dependency).
+    def validate_within_subproject(self, subdir, fname):
+        srcdir = Path(self.environment.source_dir)
+        norm = Path(srcdir, subdir, fname).resolve()
+        if os.path.isdir(norm):
+            inputtype = 'directory'
+        else:
+            inputtype = 'file'
+        if srcdir not in norm.parents:
+            # Grabbing files outside the source tree is ok.
+            # This is for vendor stuff like:
+            #
+            # /opt/vendorsdk/src/file_with_license_restrictions.c
+            return
+        project_root = Path(srcdir, self.root_subdir)
+        if norm == project_root:
+            return
+        if project_root not in norm.parents:
+            raise InterpreterException(f'Sandbox violation: Tried to grab {inputtype} {norm.name} outside current (sub)project.')
+        if project_root / self.subproject_dir in norm.parents:
+            raise InterpreterException(f'Sandbox violation: Tried to grab {inputtype} {norm.name} from a nested subproject.')
+
+    @T.overload
+    def source_strings_to_files(self, sources: T.List['mesonlib.FileOrString'], strict: bool = True) -> T.List['mesonlib.File']: ...
+
+    @T.overload
+    def source_strings_to_files(self, sources: T.List['mesonlib.FileOrString'], strict: bool = False) -> T.List['mesonlib.FileOrString']: ... # noqa: F811
+
+    @T.overload
+    def source_strings_to_files(self, sources: T.List['SourceInputs'], strict: bool = True) -> T.List['SourceOutputs']: ... # noqa: F811
+
+    def source_strings_to_files(self, sources: T.List['SourceInputs'], strict: bool = True) -> T.List['SourceOutputs']: # noqa: F811
+        """Lower inputs to a list of Targets and Files, replacing any strings.
+
+        :param sources: A raw (Meson DSL) list of inputs (targets, files, and
+            strings)
+        :raises InterpreterException: if any of the inputs are of an invalid type
+        :return: A list of Targets and Files
+        """
+        mesonlib.check_direntry_issues(sources)
+        if not isinstance(sources, list):
+            sources = [sources]
+        results: T.List['SourceOutputs'] = []
+        for s in sources:
+            if isinstance(s, str):
+                if not strict and s.startswith(self.environment.get_build_dir()):
+                    results.append(s)
+                    mlog.warning(f'Source item {s!r} cannot be converted to File object, because it is a generated file. '
+                                 'This will become a hard error in the future.', location=self.current_node)
+                else:
+                    self.validate_within_subproject(self.subdir, s)
+                    results.append(mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s))
+            elif isinstance(s, mesonlib.File):
+                results.append(s)
+            elif isinstance(s, (build.GeneratedList, build.BuildTarget,
+                                build.CustomTargetIndex, build.CustomTarget,
+                                build.ExtractedObjects)):
+                results.append(s)
+            else:
+                raise InterpreterException(f'Source item is {s!r} instead of '
+                                           'string or File-type object')
+        return results
+
+    def add_target(self, name, tobj):
+        if name == '':
+            raise InterpreterException('Target name must not be empty.')
+        if name.strip() == '':
+            raise InterpreterException('Target name must not consist only of whitespace.')
+        if has_path_sep(name):
+            pathseg = os.path.join(self.subdir, os.path.split(name)[0])
+            if os.path.exists(os.path.join(self.source_root, pathseg)):
+                raise InvalidArguments(textwrap.dedent(f'''\
+                    Target "{name}" has a path segment pointing to directory "{pathseg}". This is an error.
+                    To define a target that builds in that directory you must define it
+                    in the meson.build file in that directory.
+            '''))
+        if name.startswith('meson-'):
+            raise InvalidArguments("Target names starting with 'meson-' are reserved "
+                                   "for Meson's internal use. Please rename.")
+        if name in coredata.FORBIDDEN_TARGET_NAMES:
+            raise InvalidArguments(f"Target name '{name}' is reserved for Meson's "
+                                   "internal use. Please rename.")
+        # To permit an executable and a shared library to have the
+        # same name, such as "foo.exe" and "libfoo.a".
+        idname = tobj.get_id()
+        if idname in self.build.targets:
+            raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.')
+        self.build.targets[idname] = tobj
+        if idname not in self.coredata.target_guids:
+            self.coredata.target_guids[idname] = str(uuid.uuid4()).upper()
+
+    @FeatureNew('both_libraries', '0.46.0')
+    def build_both_libraries(self, node, args, kwargs):
+        shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary)
+
+        # Check if user forces non-PIC static library.
+        pic = True
+        key = OptionKey('b_staticpic')
+        if 'pic' in kwargs:
+            pic = kwargs['pic']
+        elif key in self.environment.coredata.options:
+            pic = self.environment.coredata.options[key].value
+
+        if self.backend.name == 'xcode':
+            # Xcode is a bit special in that you can't (at least for the moment)
+            # form a library only from object file inputs. The simple but inefficient
+            # solution is to use the sources directly. This will lead to them being
+            # built twice. This is unfortunate and slow, but at least it works.
+            # Feel free to submit patches to get this fixed if it is an
+            # issue for you.
+            reuse_object_files = False
+        else:
+            reuse_object_files = pic
+
+        if reuse_object_files:
+            # Exclude sources from args and kwargs to avoid building them twice
+            static_args = [args[0]]
+            static_kwargs = kwargs.copy()
+            static_kwargs['sources'] = []
+            static_kwargs['objects'] = shared_lib.extract_all_objects()
+        else:
+            static_args = args
+            static_kwargs = kwargs
+
+        static_lib = self.build_target(node, static_args, static_kwargs, build.StaticLibrary)
+
+        return build.BothLibraries(shared_lib, static_lib)
+
+    def build_library(self, node, args, kwargs):
+        default_library = self.coredata.get_option(OptionKey('default_library', subproject=self.subproject))
+        if default_library == 'shared':
+            return self.build_target(node, args, kwargs, build.SharedLibrary)
+        elif default_library == 'static':
+            return self.build_target(node, args, kwargs, build.StaticLibrary)
+        elif default_library == 'both':
+            return self.build_both_libraries(node, args, kwargs)
+        else:
+            raise InterpreterException(f'Unknown default_library value: {default_library}.')
+
+    def build_target(self, node, args, kwargs, targetclass):
+        @FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories'])
+        @FeatureNewKwargs('build target', '0.41.0', ['rust_args'])
+        @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
+        @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility'])
+        def build_target_decorator_caller(self, node, args, kwargs):
+            return True
+
+        build_target_decorator_caller(self, node, args, kwargs)
+
+        if not args:
+            raise InterpreterException('Target does not have a name.')
+        name, *sources = args
+        for_machine = self.machine_from_native_kwarg(kwargs)
+        if 'sources' in kwargs:
+            sources += listify(kwargs['sources'])
+        sources = self.source_strings_to_files(sources)
+        objs = extract_as_list(kwargs, 'objects')
+        kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies')
+        kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs)
+        if 'extra_files' in kwargs:
+            ef = extract_as_list(kwargs, 'extra_files')
+            kwargs['extra_files'] = self.source_strings_to_files(ef)
+        self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources)
+        if targetclass not in {build.Executable, build.SharedLibrary, build.SharedModule, build.StaticLibrary, build.Jar}:
+            mlog.debug('Unknown target type:', str(targetclass))
+            raise RuntimeError('Unreachable code')
+        self.kwarg_strings_to_includedirs(kwargs)
+
+        # Filter out kwargs from other target types. For example 'soversion'
+        # passed to library() when default_library == 'static'.
+        kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs}
+
+        kwargs['include_directories'] = self.extract_incdirs(kwargs)
+        target = targetclass(name, self.subdir, self.subproject, for_machine, sources, objs, self.environment, kwargs)
+        target.project_version = self.project_version
+
+        self.add_stdlib_info(target)
+        self.add_target(name, target)
+        self.project_args_frozen = True
+        return target
+
+    def kwarg_strings_to_includedirs(self, kwargs):
+        if 'd_import_dirs' in kwargs:
+            items = mesonlib.extract_as_list(kwargs, 'd_import_dirs')
+            cleaned_items = []
+            for i in items:
+                if isinstance(i, str):
+                    # BW compatibility. This was permitted so we must support it
+                    # for a few releases so people can transition to "correct"
+                    # path declarations.
+                    if os.path.normpath(i).startswith(self.environment.get_source_dir()):
+                        mlog.warning('''Building a path to the source dir is not supported. Use a relative path instead.
+This will become a hard error in the future.''', location=self.current_node)
+                        i = os.path.relpath(i, os.path.join(self.environment.get_source_dir(), self.subdir))
+                        i = self.build_incdir_object([i])
+                cleaned_items.append(i)
+            kwargs['d_import_dirs'] = cleaned_items
+
+    def get_used_languages(self, target):
+        result = set()
+        for i in target.sources:
+            for lang, c in self.coredata.compilers[target.for_machine].items():
+                if c.can_compile(i):
+                    result.add(lang)
+                    break
+        return result
+
+    def add_stdlib_info(self, target):
+        for l in self.get_used_languages(target):
+            dep = self.build.stdlibs[target.for_machine].get(l, None)
+            if dep:
+                target.add_deps(dep)
+
+    def check_sources_exist(self, subdir, sources):
+        for s in sources:
+            if not isinstance(s, str):
+                continue # This means a generated source and they always exist.
+            fname = os.path.join(subdir, s)
+            if not os.path.isfile(fname):
+                raise InterpreterException(f'Tried to add non-existing source file {s}.')
+
+    # Only permit object extraction from the same subproject
+    def validate_extraction(self, buildtarget: mesonlib.HoldableObject) -> None:
+        if self.subproject != buildtarget.subproject:
+            raise InterpreterException('Tried to extract objects from a different subproject.')
+
+    def is_subproject(self) -> bool:
+        return self.subproject != ''
+
+    @typed_pos_args('set_variable', str, object)
+    @noKwargs
+    @noArgsFlattening
+    @noSecondLevelHolderResolving
+    def func_set_variable(self, node: mparser.BaseNode, args: T.Tuple[str, object], kwargs: 'TYPE_kwargs') -> None:
+        varname, value = args
+        self.set_variable(varname, value, holderify=True)
+
+    @typed_pos_args('get_variable', (str, Disabler), optargs=[object])
+    @noKwargs
+    @noArgsFlattening
+    @unholder_return
+    def func_get_variable(self, node: mparser.BaseNode, args: T.Tuple[T.Union[str, Disabler], T.Optional[object]],
+                          kwargs: 'TYPE_kwargs') -> 'TYPE_var':
+        varname, fallback = args
+        if isinstance(varname, Disabler):
+            return varname
+
+        try:
+            return self.variables[varname]
+        except KeyError:
+            if fallback is not None:
+                return self._holderify(fallback)
+        raise InterpreterException(f'Tried to get unknown variable "{varname}".')
+
+    @typed_pos_args('is_variable', str)
+    @noKwargs
+    def func_is_variable(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
+        return args[0] in self.variables
+
+    @FeatureNew('unset_variable', '0.60.0')
+    @typed_pos_args('unset_variable', str)
+    @noKwargs
+    def func_unset_variable(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> None:
+        varname = args[0]
+        try:
+            del self.variables[varname]
+        except KeyError:
+            raise InterpreterException(f'Tried to unset unknown variable "{varname}".')
+
+    @staticmethod
+    def machine_from_native_kwarg(kwargs: T.Dict[str, T.Any]) -> MachineChoice:
+        native = kwargs.get('native', False)
+        if not isinstance(native, bool):
+            raise InvalidArguments('Argument to "native" must be a boolean.')
+        return MachineChoice.BUILD if native else MachineChoice.HOST
+
+    @FeatureNew('is_disabler', '0.52.0')
+    @typed_pos_args('is_disabler', object)
+    @noKwargs
+    def func_is_disabler(self, node: mparser.BaseNode, args: T.Tuple[object], kwargs: 'TYPE_kwargs') -> bool:
+        return isinstance(args[0], Disabler)
+
+    @noKwargs
+    @FeatureNew('range', '0.58.0')
+    @typed_pos_args('range', int, optargs=[int, int])
+    def func_range(self, node, args: T.Tuple[int, T.Optional[int], T.Optional[int]], kwargs: T.Dict[str, T.Any]) -> P_OBJ.RangeHolder:
+        start, stop, step = args
+        # Just like Python's range, we allow range(stop), range(start, stop), or
+        # range(start, stop, step)
+        if stop is None:
+            stop = start
+            start = 0
+        if step is None:
+            step = 1
+        # This is more strict than Python's range()
+        if start < 0:
+            raise InterpreterException('start cannot be negative')
+        if stop < start:
+            raise InterpreterException('stop cannot be less than start')
+        if step < 1:
+            raise InterpreterException('step must be >=1')
+        return P_OBJ.RangeHolder(start, stop, step, subproject=self.subproject)
diff -Nru meson-0.53.2/mesonbuild/interpreter/kwargs.py meson-0.61.2/mesonbuild/interpreter/kwargs.py
--- meson-0.53.2/mesonbuild/interpreter/kwargs.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/kwargs.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,241 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright © 2021 The Meson Developers
+# Copyright © 2021 Intel Corporation
+
+"""Keyword Argument type annotations."""
+
+import typing as T
+
+from typing_extensions import TypedDict, Literal, Protocol
+
+from .. import build
+from .. import coredata
+from ..mesonlib import MachineChoice, File, FileMode, FileOrString, OptionKey
+from ..programs import ExternalProgram
+
+
+class FuncAddProjectArgs(TypedDict):
+
+    """Keyword Arguments for the add_*_arguments family of arguments.
+
+    including `add_global_arguments`, `add_project_arguments`, and their
+    link variants
+
+    Because of the use of a convertor function, we get the native keyword as
+    a MachineChoice instance already.
+    """
+
+    native: MachineChoice
+    language: T.List[str]
+
+
+class BaseTest(TypedDict):
+
+    """Shared base for the Rust module."""
+
+    args: T.List[T.Union[str, File, build.Target]]
+    should_fail: bool
+    timeout: int
+    workdir: T.Optional[str]
+    depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]]
+    priority: int
+    env: build.EnvironmentVariables
+    suite: T.List[str]
+
+
+class FuncBenchmark(BaseTest):
+
+    """Keyword Arguments shared between `test` and `benchmark`."""
+
+    protocol: Literal['exitcode', 'tap', 'gtest', 'rust']
+
+
+class FuncTest(FuncBenchmark):
+
+    """Keyword Arguments for `test`
+
+    `test` only adds the `is_prallel` argument over benchmark, so inherintance
+    is helpful here.
+    """
+
+    is_parallel: bool
+
+
+class ExtractRequired(TypedDict):
+
+    """Keyword Arguments consumed by the `extract_required_kwargs` function.
+
+    Any function that uses the `required` keyword argument which accepts either
+    a boolean or a feature option should inherit it's arguments from this class.
+    """
+
+    required: T.Union[bool, coredata.UserFeatureOption]
+
+
+class ExtractSearchDirs(TypedDict):
+
+    """Keyword arguments consumed by the `extract_search_dirs` function.
+
+    See the not in `ExtractRequired`
+    """
+
+    dirs: T.List[str]
+
+
+class FuncGenerator(TypedDict):
+
+    """Keyword rguments for the generator function."""
+
+    arguments: T.List[str]
+    output: T.List[str]
+    depfile: T.Optional[str]
+    capture:  bool
+    depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]]
+
+
+class GeneratorProcess(TypedDict):
+
+    """Keyword Arguments for generator.process."""
+
+    preserve_path_from: T.Optional[str]
+    extra_args: T.List[str]
+
+class DependencyMethodPartialDependency(TypedDict):
+
+    """ Keyword Arguments for the dep.partial_dependency methods """
+
+    compile_args: bool
+    link_args: bool
+    links: bool
+    includes: bool
+    sources: bool
+
+class BuildTargeMethodExtractAllObjects(TypedDict):
+    recursive: bool
+
+class FuncInstallSubdir(TypedDict):
+
+    install_dir: str
+    strip_directory: bool
+    exclude_files: T.List[str]
+    exclude_directories: T.List[str]
+    install_mode: FileMode
+
+
+class FuncInstallData(TypedDict):
+
+    install_dir: str
+    sources: T.List[FileOrString]
+    rename: T.List[str]
+    install_mode: FileMode
+
+
+class FuncInstallHeaders(TypedDict):
+
+    install_dir: T.Optional[str]
+    install_mode: FileMode
+    subdir: T.Optional[str]
+
+
+class FuncInstallMan(TypedDict):
+
+    install_dir: T.Optional[str]
+    install_mode: FileMode
+    locale: T.Optional[str]
+
+
+class FuncImportModule(ExtractRequired):
+
+    disabler: bool
+
+
+class FuncIncludeDirectories(TypedDict):
+
+    is_system: bool
+
+class FuncAddLanguages(ExtractRequired):
+
+    native: T.Optional[bool]
+
+class RunTarget(TypedDict):
+
+    command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, ExternalProgram, File]]
+    depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]]
+    env: build.EnvironmentVariables
+
+
+class CustomTarget(TypedDict):
+
+    build_always: bool
+    build_always_stale: bool
+    build_by_default: bool
+    capture: bool
+    command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget,
+                            build.CustomTargetIndex, ExternalProgram, File]]
+    consonle: bool
+    depend_files: T.List[FileOrString]
+    depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]]
+    depfile: T.Optional[str]
+    env: build.EnvironmentVariables
+    feed: bool
+    input: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex,
+                          build.ExtractedObjects, build.GeneratedList, ExternalProgram, File]]
+    install: bool
+    install_dir: T.List[T.Union[str, bool]]
+    install_mode: FileMode
+    install_tag: T.List[T.Union[str, bool]]
+    output: T.List[str]
+    override_options: T.Dict[OptionKey, str]
+
+class AddTestSetup(TypedDict):
+
+    exe_wrapper: T.List[T.Union[str, ExternalProgram]]
+    gdb: bool
+    timeout_multiplier: int
+    is_default: bool
+    exclude_suites: T.List[str]
+    env: build.EnvironmentVariables
+
+
+class Project(TypedDict):
+
+    version: T.Optional[FileOrString]
+    meson_version: T.Optional[str]
+    default_options: T.List[str]
+    license: T.List[str]
+    subproject_dir: str
+
+
+class _FoundProto(Protocol):
+
+    """Protocol for subdir arguments.
+
+    This allows us to define any objec that has a found(self) -> bool method
+    """
+
+    def found(self) -> bool: ...
+
+
+class Subdir(TypedDict):
+
+    if_found: T.List[_FoundProto]
+
+
+class Summary(TypedDict):
+
+    section: str
+    bool_yn: bool
+    list_sep: T.Optional[str]
+
+
+class FindProgram(ExtractRequired, ExtractSearchDirs):
+
+    native: MachineChoice
+    version: T.List[str]
+
+
+class RunCommand(TypedDict):
+
+    check: bool
+    capture: T.Optional[bool]
+    env: build.EnvironmentVariables
diff -Nru meson-0.53.2/mesonbuild/interpreter/mesonmain.py meson-0.61.2/mesonbuild/interpreter/mesonmain.py
--- meson-0.53.2/mesonbuild/interpreter/mesonmain.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/mesonmain.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,450 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright 2012-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+import os
+import typing as T
+
+from .. import mesonlib
+from .. import dependencies
+from .. import build
+from .. import mlog
+
+from ..mesonlib import MachineChoice, OptionKey
+from ..programs import OverrideProgram, ExternalProgram
+from ..interpreter.type_checking import ENV_KW
+from ..interpreterbase import (MesonInterpreterObject, FeatureNew, FeatureDeprecated,
+                               typed_pos_args,  noArgsFlattening, noPosargs, noKwargs,
+                               typed_kwargs, KwargInfo, InterpreterException)
+from .primitives import MesonVersionString
+from .type_checking import NATIVE_KW, NoneType
+
+if T.TYPE_CHECKING:
+    from ..backend.backends import ExecutableSerialisation
+    from ..compilers import Compiler
+    from ..interpreterbase import TYPE_kwargs, TYPE_var
+    from .interpreter import Interpreter
+
+    from typing_extensions import TypedDict
+
+    class FuncOverrideDependency(TypedDict):
+
+        native: mesonlib.MachineChoice
+        static: T.Optional[bool]
+
+    class AddInstallScriptKW(TypedDict):
+
+        skip_if_destdir: bool
+        install_tag: str
+
+    class NativeKW(TypedDict):
+
+        native: mesonlib.MachineChoice
+
+
+class MesonMain(MesonInterpreterObject):
+    def __init__(self, build: 'build.Build', interpreter: 'Interpreter'):
+        super().__init__(subproject=interpreter.subproject)
+        self.build = build
+        self.interpreter = interpreter
+        self.methods.update({'get_compiler': self.get_compiler_method,
+                             'is_cross_build': self.is_cross_build_method,
+                             'has_exe_wrapper': self.has_exe_wrapper_method,
+                             'can_run_host_binaries': self.can_run_host_binaries_method,
+                             'is_unity': self.is_unity_method,
+                             'is_subproject': self.is_subproject_method,
+                             'current_source_dir': self.current_source_dir_method,
+                             'current_build_dir': self.current_build_dir_method,
+                             'source_root': self.source_root_method,
+                             'build_root': self.build_root_method,
+                             'project_source_root': self.project_source_root_method,
+                             'project_build_root': self.project_build_root_method,
+                             'global_source_root': self.global_source_root_method,
+                             'global_build_root': self.global_build_root_method,
+                             'add_install_script': self.add_install_script_method,
+                             'add_postconf_script': self.add_postconf_script_method,
+                             'add_dist_script': self.add_dist_script_method,
+                             'install_dependency_manifest': self.install_dependency_manifest_method,
+                             'override_dependency': self.override_dependency_method,
+                             'override_find_program': self.override_find_program_method,
+                             'project_version': self.project_version_method,
+                             'project_license': self.project_license_method,
+                             'version': self.version_method,
+                             'project_name': self.project_name_method,
+                             'get_cross_property': self.get_cross_property_method,
+                             'get_external_property': self.get_external_property_method,
+                             'has_external_property': self.has_external_property_method,
+                             'backend': self.backend_method,
+                             'add_devenv': self.add_devenv_method,
+                             })
+
+    def _find_source_script(
+            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)
+        else:
+            if 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)
+        es = self.interpreter.backend.get_executable_serialisation(largs)
+        es.subproject = self.interpreter.subproject
+        return es
+
+    def _process_script_args(
+            self, name: str, args: T.Sequence[T.Union[
+                str, mesonlib.File, build.BuildTarget, build.CustomTarget,
+                build.CustomTargetIndex,
+                ExternalProgram,
+            ]]) -> T.List[str]:
+        script_args = []  # T.List[str]
+        new = False
+        for a in args:
+            if isinstance(a, str):
+                script_args.append(a)
+            elif isinstance(a, mesonlib.File):
+                new = True
+                script_args.append(a.rel_to_builddir(self.interpreter.environment.source_dir))
+            elif isinstance(a, (build.BuildTarget, build.CustomTarget, build.CustomTargetIndex)):
+                new = True
+                script_args.extend([os.path.join(a.get_subdir(), o) for o in a.get_outputs()])
+
+                # This feels really hacky, but I'm not sure how else to fix
+                # this without completely rewriting install script handling.
+                # This is complicated by the fact that the install target
+                # depends on all.
+                if isinstance(a, build.CustomTargetIndex):
+                    a.target.build_by_default = True
+                else:
+                    a.build_by_default = True
+            else:
+                script_args.extend(a.command)
+                new = True
+
+        if new:
+            FeatureNew.single_use(
+                f'Calling "{name}" with File, CustomTarget, Index of CustomTarget, '
+                'Executable, or ExternalProgram',
+                '0.55.0', self.interpreter.subproject, location=self.current_node)
+        return script_args
+
+    @typed_pos_args(
+        'meson.add_install_script',
+        (str, mesonlib.File, build.Executable, ExternalProgram),
+        varargs=(str, mesonlib.File, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, ExternalProgram)
+    )
+    @typed_kwargs(
+        'meson.add_install_script',
+        KwargInfo('skip_if_destdir', bool, default=False, since='0.57.0'),
+        KwargInfo('install_tag', (str, NoneType), since='0.60.0'),
+    )
+    def add_install_script_method(
+            self,
+            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:
+        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)
+
+    @typed_pos_args(
+        'meson.add_postconf_script',
+        (str, mesonlib.File, ExternalProgram),
+        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, ExternalProgram]]],
+            kwargs: 'TYPE_kwargs') -> None:
+        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, ExternalProgram),
+        varargs=(str, mesonlib.File, ExternalProgram)
+    )
+    @noKwargs
+    def add_dist_script_method(
+            self,
+            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, location=self.current_node)
+        if self.interpreter.subproject != '':
+            FeatureNew.single_use('Calling "add_dist_script" in a subproject',
+                                  '0.58.0', self.interpreter.subproject, location=self.current_node)
+        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
+    @noKwargs
+    def current_source_dir_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        src = self.interpreter.environment.source_dir
+        sub = self.interpreter.subdir
+        if sub == '':
+            return src
+        return os.path.join(src, sub)
+
+    @noPosargs
+    @noKwargs
+    def current_build_dir_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        src = self.interpreter.environment.build_dir
+        sub = self.interpreter.subdir
+        if sub == '':
+            return src
+        return os.path.join(src, sub)
+
+    @noPosargs
+    @noKwargs
+    def backend_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.interpreter.backend.name
+
+    @noPosargs
+    @noKwargs
+    @FeatureDeprecated('meson.source_root', '0.56.0', 'use meson.project_source_root() or meson.global_source_root() instead.')
+    def source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.interpreter.environment.source_dir
+
+    @noPosargs
+    @noKwargs
+    @FeatureDeprecated('meson.build_root', '0.56.0', 'use meson.project_build_root() or meson.global_build_root() instead.')
+    def build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.interpreter.environment.build_dir
+
+    @noPosargs
+    @noKwargs
+    @FeatureNew('meson.project_source_root', '0.56.0')
+    def project_source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        src = self.interpreter.environment.source_dir
+        sub = self.interpreter.root_subdir
+        if sub == '':
+            return src
+        return os.path.join(src, sub)
+
+    @noPosargs
+    @noKwargs
+    @FeatureNew('meson.project_build_root', '0.56.0')
+    def project_build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        src = self.interpreter.environment.build_dir
+        sub = self.interpreter.root_subdir
+        if sub == '':
+            return src
+        return os.path.join(src, sub)
+
+    @noPosargs
+    @noKwargs
+    @FeatureNew('meson.global_source_root', '0.58.0')
+    def global_source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.interpreter.environment.source_dir
+
+    @noPosargs
+    @noKwargs
+    @FeatureNew('meson.global_build_root', '0.58.0')
+    def global_build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.interpreter.environment.build_dir
+
+    @noPosargs
+    @noKwargs
+    @FeatureDeprecated('meson.has_exe_wrapper', '0.55.0', 'use meson.can_run_host_binaries instead.')
+    def has_exe_wrapper_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        return self._can_run_host_binaries_impl()
+
+    @noPosargs
+    @noKwargs
+    @FeatureNew('meson.can_run_host_binaries', '0.55.0')
+    def can_run_host_binaries_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        return self._can_run_host_binaries_impl()
+
+    def _can_run_host_binaries_impl(self) -> bool:
+        return not (
+            self.build.environment.is_cross_build() and
+            self.build.environment.need_exe_wrapper() and
+            self.build.environment.exe_wrapper is None
+        )
+
+    @noPosargs
+    @noKwargs
+    def is_cross_build_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        return self.build.environment.is_cross_build()
+
+    @typed_pos_args('meson.get_compiler', str)
+    @typed_kwargs('meson.get_compiler', NATIVE_KW)
+    def get_compiler_method(self, args: T.Tuple[str], kwargs: 'NativeKW') -> 'Compiler':
+        cname = args[0]
+        for_machine = kwargs['native']
+        clist = self.interpreter.coredata.compilers[for_machine]
+        try:
+            return clist[cname]
+        except KeyError:
+            raise InterpreterException(f'Tried to access compiler for language "{cname}", not specified for {for_machine.get_lower_case_name()} machine.')
+
+    @noPosargs
+    @noKwargs
+    def is_unity_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        optval = self.interpreter.environment.coredata.get_option(OptionKey('unity'))
+        return optval == 'on' or (optval == 'subprojects' and self.interpreter.is_subproject())
+
+    @noPosargs
+    @noKwargs
+    def is_subproject_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        return self.interpreter.is_subproject()
+
+    @typed_pos_args('meson.install_dependency_manifest', str)
+    @noKwargs
+    def install_dependency_manifest_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> None:
+        self.build.dep_manifest_name = args[0]
+
+    @FeatureNew('meson.override_find_program', '0.46.0')
+    @typed_pos_args('meson.override_find_program', str, (mesonlib.File, ExternalProgram, build.Executable))
+    @noKwargs
+    def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable]], kwargs: 'TYPE_kwargs') -> None:
+        name, exe = args
+        if isinstance(exe, mesonlib.File):
+            abspath = exe.absolute_path(self.interpreter.environment.source_dir,
+                                        self.interpreter.environment.build_dir)
+            if not os.path.exists(abspath):
+                raise InterpreterException(f'Tried to override {name} with a file that does not exist.')
+            exe = OverrideProgram(name, [abspath])
+        self.interpreter.add_find_program_override(name, exe)
+
+    @typed_kwargs(
+        'meson.override_dependency',
+        NATIVE_KW,
+        KwargInfo('static', (bool, NoneType), since='0.60.0'),
+    )
+    @typed_pos_args('meson.override_dependency', str, dependencies.Dependency)
+    @FeatureNew('meson.override_dependency', '0.54.0')
+    def override_dependency_method(self, args: T.Tuple[str, dependencies.Dependency], kwargs: 'FuncOverrideDependency') -> None:
+        name, dep = args
+        if not name:
+            raise InterpreterException('First argument must be a string and cannot be empty')
+
+        optkey = OptionKey('default_library', subproject=self.interpreter.subproject)
+        default_library = self.interpreter.coredata.get_option(optkey)
+        assert isinstance(default_library, str), 'for mypy'
+        static = kwargs['static']
+        if static is None:
+            # We don't know if dep represents a static or shared library, could
+            # be a mix of both. We assume it is following default_library
+            # value.
+            self._override_dependency_impl(name, dep, kwargs, static=None)
+            if default_library == 'static':
+                self._override_dependency_impl(name, dep, kwargs, static=True)
+            elif default_library == 'shared':
+                self._override_dependency_impl(name, dep, kwargs, static=False)
+            else:
+                self._override_dependency_impl(name, dep, kwargs, static=True)
+                self._override_dependency_impl(name, dep, kwargs, static=False)
+        else:
+            # dependency('foo') without specifying static kwarg should find this
+            # override regardless of the static value here. But do not raise error
+            # if it has already been overridden, which would happen when overriding
+            # static and shared separately:
+            # meson.override_dependency('foo', shared_dep, static: false)
+            # meson.override_dependency('foo', static_dep, static: true)
+            # In that case dependency('foo') would return the first override.
+            self._override_dependency_impl(name, dep, kwargs, static=None, permissive=True)
+            self._override_dependency_impl(name, dep, kwargs, static=static)
+
+    def _override_dependency_impl(self, name: str, dep: dependencies.Dependency, kwargs: 'FuncOverrideDependency',
+                                  static: T.Optional[bool], permissive: bool = False) -> None:
+        # We need the cast here as get_dep_identifier works on such a dict,
+        # which FuncOverrideDependency is, but mypy can't fgure that out
+        nkwargs = T.cast(T.Dict[str, T.Any], kwargs.copy())
+        if static is None:
+            del nkwargs['static']
+        else:
+            nkwargs['static'] = static
+        identifier = dependencies.get_dep_identifier(name, nkwargs)
+        for_machine = kwargs['native']
+        override = self.build.dependency_overrides[for_machine].get(identifier)
+        if override:
+            if permissive:
+                return
+            m = 'Tried to override dependency {!r} which has already been resolved or overridden at {}'
+            location = mlog.get_error_location_string(override.node.filename, override.node.lineno)
+            raise InterpreterException(m.format(name, location))
+        self.build.dependency_overrides[for_machine][identifier] = \
+            build.DependencyOverride(dep, self.interpreter.current_node)
+
+    @noPosargs
+    @noKwargs
+    def project_version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.build.dep_manifest[self.interpreter.active_projectname].version
+
+    @FeatureNew('meson.project_license()', '0.45.0')
+    @noPosargs
+    @noKwargs
+    def project_license_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]:
+        return self.build.dep_manifest[self.interpreter.active_projectname].license
+
+    @noPosargs
+    @noKwargs
+    def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> MesonVersionString:
+        return MesonVersionString(self.interpreter.coredata.version)
+
+    @noPosargs
+    @noKwargs
+    def project_name_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.interpreter.active_projectname
+
+    def __get_external_property_impl(self, propname: str, fallback: T.Optional[object], machine: MachineChoice) -> object:
+        """Shared implementation for get_cross_property and get_external_property."""
+        try:
+            return self.interpreter.environment.properties[machine][propname]
+        except KeyError:
+            if fallback is not None:
+                return fallback
+            raise InterpreterException(f'Unknown property for {machine.get_lower_case_name()} machine: {propname}')
+
+    @noArgsFlattening
+    @FeatureDeprecated('meson.get_cross_property', '0.58.0', 'Use meson.get_external_property() instead')
+    @typed_pos_args('meson.get_cross_property', str, optargs=[object])
+    @noKwargs
+    def get_cross_property_method(self, args: T.Tuple[str, T.Optional[object]], kwargs: 'TYPE_kwargs') -> object:
+        propname, fallback = args
+        return self.__get_external_property_impl(propname, fallback, MachineChoice.HOST)
+
+    @noArgsFlattening
+    @FeatureNew('meson.get_external_property', '0.54.0')
+    @typed_pos_args('meson.get_external_property', str, optargs=[object])
+    @typed_kwargs('meson.get_external_property', NATIVE_KW)
+    def get_external_property_method(self, args: T.Tuple[str, T.Optional[object]], kwargs: 'NativeKW') -> object:
+        propname, fallback = args
+        return self.__get_external_property_impl(propname, fallback, kwargs['native'])
+
+    @FeatureNew('meson.has_external_property', '0.58.0')
+    @typed_pos_args('meson.has_external_property', str)
+    @typed_kwargs('meson.has_external_property', NATIVE_KW)
+    def has_external_property_method(self, args: T.Tuple[str], kwargs: 'NativeKW') -> bool:
+        prop_name = args[0]
+        return prop_name in self.interpreter.environment.properties[kwargs['native']]
+
+    @FeatureNew('add_devenv', '0.58.0')
+    @noKwargs
+    @typed_pos_args('add_devenv', (str, list, dict, build.EnvironmentVariables))
+    def add_devenv_method(self, args: T.Tuple[T.Union[str, list, dict, build.EnvironmentVariables]], kwargs: 'TYPE_kwargs') -> None:
+        env = args[0]
+        msg = ENV_KW.validator(env)
+        if msg:
+            raise build.InvalidArguments(f'"add_devenv": {msg}')
+        converted = ENV_KW.convertor(env)
+        assert isinstance(converted, build.EnvironmentVariables)
+        self.build.devenv.append(converted)
diff -Nru meson-0.53.2/mesonbuild/interpreter/primitives/array.py meson-0.61.2/mesonbuild/interpreter/primitives/array.py
--- meson-0.53.2/mesonbuild/interpreter/primitives/array.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/primitives/array.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,107 @@
+# Copyright 2021 The Meson development team
+# SPDX-license-identifier: Apache-2.0
+
+import typing as T
+
+from ...interpreterbase import (
+    ObjectHolder,
+    IterableObject,
+    MesonOperator,
+    typed_operator,
+    noKwargs,
+    noPosargs,
+    noArgsFlattening,
+    typed_pos_args,
+    FeatureNew,
+
+    TYPE_var,
+    TYPE_kwargs,
+
+    InvalidArguments,
+)
+from ...mparser import PlusAssignmentNode
+
+if T.TYPE_CHECKING:
+    # Object holders need the actual interpreter
+    from ...interpreter import Interpreter
+
+class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject):
+    def __init__(self, obj: T.List[TYPE_var], interpreter: 'Interpreter') -> None:
+        super().__init__(obj, interpreter)
+        self.methods.update({
+            'contains': self.contains_method,
+            'length': self.length_method,
+            'get': self.get_method,
+        })
+
+        self.trivial_operators.update({
+            MesonOperator.EQUALS: (list, lambda x: self.held_object == x),
+            MesonOperator.NOT_EQUALS: (list, lambda x: self.held_object != x),
+            MesonOperator.IN: (object, lambda x: x in self.held_object),
+            MesonOperator.NOT_IN: (object, lambda x: x not in self.held_object),
+        })
+
+        # Use actual methods for functions that require additional checks
+        self.operators.update({
+            MesonOperator.PLUS: self.op_plus,
+            MesonOperator.INDEX: self.op_index,
+        })
+
+    def display_name(self) -> str:
+        return 'array'
+
+    def iter_tuple_size(self) -> None:
+        return None
+
+    def iter_self(self) -> T.Iterator[TYPE_var]:
+        return iter(self.held_object)
+
+    def size(self) -> int:
+        return len(self.held_object)
+
+    @noArgsFlattening
+    @noKwargs
+    @typed_pos_args('array.contains', object)
+    def contains_method(self, args: T.Tuple[object], kwargs: TYPE_kwargs) -> bool:
+        def check_contains(el: T.List[TYPE_var]) -> bool:
+            for element in el:
+                if isinstance(element, list):
+                    found = check_contains(element)
+                    if found:
+                        return True
+                if element == args[0]:
+                    return True
+            return False
+        return check_contains(self.held_object)
+
+    @noKwargs
+    @noPosargs
+    def length_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
+        return len(self.held_object)
+
+    @noArgsFlattening
+    @noKwargs
+    @typed_pos_args('array.get', int, optargs=[object])
+    def get_method(self, args: T.Tuple[int, T.Optional[TYPE_var]], kwargs: TYPE_kwargs) -> TYPE_var:
+        index = args[0]
+        if index < -len(self.held_object) or index >= len(self.held_object):
+            if args[1] is None:
+                raise InvalidArguments(f'Array index {index} is out of bounds for array of size {len(self.held_object)}.')
+            return args[1]
+        return self.held_object[index]
+
+    @typed_operator(MesonOperator.PLUS, object)
+    def op_plus(self, other: TYPE_var) -> T.List[TYPE_var]:
+        if not isinstance(other, list):
+            if not isinstance(self.current_node, PlusAssignmentNode):
+                FeatureNew.single_use('list.', '0.60.0', self.subproject, 'The right hand operand was not a list.',
+                                      location=self.current_node)
+            other = [other]
+        return self.held_object + other
+
+    @typed_operator(MesonOperator.INDEX, int)
+    def op_index(self, other: int) -> TYPE_var:
+        try:
+            return self.held_object[other]
+        except IndexError:
+            raise InvalidArguments(f'Index {other} out of bounds of array of size {len(self.held_object)}.')
diff -Nru meson-0.53.2/mesonbuild/interpreter/primitives/boolean.py meson-0.61.2/mesonbuild/interpreter/primitives/boolean.py
--- meson-0.53.2/mesonbuild/interpreter/primitives/boolean.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/primitives/boolean.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,53 @@
+# Copyright 2021 The Meson development team
+# SPDX-license-identifier: Apache-2.0
+
+from ...interpreterbase import (
+    ObjectHolder,
+    MesonOperator,
+    typed_pos_args,
+    noKwargs,
+    noPosargs,
+
+    TYPE_var,
+    TYPE_kwargs,
+
+    InvalidArguments
+)
+
+import typing as T
+
+if T.TYPE_CHECKING:
+    # Object holders need the actual interpreter
+    from ...interpreter import Interpreter
+
+class BooleanHolder(ObjectHolder[bool]):
+    def __init__(self, obj: bool, interpreter: 'Interpreter') -> None:
+        super().__init__(obj, interpreter)
+        self.methods.update({
+            'to_int': self.to_int_method,
+            'to_string': self.to_string_method,
+        })
+
+        self.trivial_operators.update({
+            MesonOperator.BOOL: (None, lambda x: self.held_object),
+            MesonOperator.NOT: (None, lambda x: not self.held_object),
+            MesonOperator.EQUALS: (bool, lambda x: self.held_object == x),
+            MesonOperator.NOT_EQUALS: (bool, lambda x: self.held_object != x),
+        })
+
+    def display_name(self) -> str:
+        return 'bool'
+
+    @noKwargs
+    @noPosargs
+    def to_int_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
+        return 1 if self.held_object else 0
+
+    @noKwargs
+    @typed_pos_args('bool.to_string', optargs=[str, str])
+    def to_string_method(self, args: T.Tuple[T.Optional[str], T.Optional[str]], kwargs: TYPE_kwargs) -> str:
+        true_str = args[0] or 'true'
+        false_str = args[1] or 'false'
+        if any(x is not None for x in args) and not all(x is not None for x in args):
+            raise InvalidArguments('bool.to_string() must have either no arguments or exactly two string arguments that signify what values to return for true and false.')
+        return true_str if self.held_object else false_str
diff -Nru meson-0.53.2/mesonbuild/interpreter/primitives/dict.py meson-0.61.2/mesonbuild/interpreter/primitives/dict.py
--- meson-0.53.2/mesonbuild/interpreter/primitives/dict.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/primitives/dict.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,87 @@
+# Copyright 2021 The Meson development team
+# SPDX-license-identifier: Apache-2.0
+
+import typing as T
+
+from ...interpreterbase import (
+    ObjectHolder,
+    IterableObject,
+    MesonOperator,
+    typed_operator,
+    noKwargs,
+    noPosargs,
+    noArgsFlattening,
+    typed_pos_args,
+
+    TYPE_var,
+    TYPE_kwargs,
+
+    InvalidArguments,
+)
+
+if T.TYPE_CHECKING:
+    # Object holders need the actual interpreter
+    from ...interpreter import Interpreter
+
+class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject):
+    def __init__(self, obj: T.Dict[str, TYPE_var], interpreter: 'Interpreter') -> None:
+        super().__init__(obj, interpreter)
+        self.methods.update({
+            'has_key': self.has_key_method,
+            'keys': self.keys_method,
+            'get': self.get_method,
+        })
+
+        self.trivial_operators.update({
+            # Arithmetic
+            MesonOperator.PLUS: (dict, lambda x: {**self.held_object, **x}),
+
+            # Comparison
+            MesonOperator.EQUALS: (dict, lambda x: self.held_object == x),
+            MesonOperator.NOT_EQUALS: (dict, lambda x: self.held_object != x),
+            MesonOperator.IN: (str, lambda x: x in self.held_object),
+            MesonOperator.NOT_IN: (str, lambda x: x not in self.held_object),
+        })
+
+        # Use actual methods for functions that require additional checks
+        self.operators.update({
+            MesonOperator.INDEX: self.op_index,
+        })
+
+    def display_name(self) -> str:
+        return 'dict'
+
+    def iter_tuple_size(self) -> int:
+        return 2
+
+    def iter_self(self) -> T.Iterator[T.Tuple[str, TYPE_var]]:
+        return iter(self.held_object.items())
+
+    def size(self) -> int:
+        return len(self.held_object)
+
+    @noKwargs
+    @typed_pos_args('dict.has_key', str)
+    def has_key_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
+        return args[0] in self.held_object
+
+    @noKwargs
+    @noPosargs
+    def keys_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]:
+        return sorted(self.held_object)
+
+    @noArgsFlattening
+    @noKwargs
+    @typed_pos_args('dict.get', str, optargs=[object])
+    def get_method(self, args: T.Tuple[str, T.Optional[TYPE_var]], kwargs: TYPE_kwargs) -> TYPE_var:
+        if args[0] in self.held_object:
+            return self.held_object[args[0]]
+        if args[1] is not None:
+            return args[1]
+        raise InvalidArguments(f'Key {args[0]!r} is not in the dictionary.')
+
+    @typed_operator(MesonOperator.INDEX, str)
+    def op_index(self, other: str) -> TYPE_var:
+        if other not in self.held_object:
+            raise InvalidArguments(f'Key {other} is not in the dictionary.')
+        return self.held_object[other]
diff -Nru meson-0.53.2/mesonbuild/interpreter/primitives/__init__.py meson-0.61.2/mesonbuild/interpreter/primitives/__init__.py
--- meson-0.53.2/mesonbuild/interpreter/primitives/__init__.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/primitives/__init__.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,20 @@
+# Copyright 2021 The Meson development team
+# SPDX-license-identifier: Apache-2.0
+
+__all__ = [
+    'ArrayHolder',
+    'BooleanHolder',
+    'DictHolder',
+    'IntegerHolder',
+    'RangeHolder',
+    'StringHolder',
+    'MesonVersionString',
+    'MesonVersionStringHolder',
+]
+
+from .array import ArrayHolder
+from .boolean import BooleanHolder
+from .dict import DictHolder
+from .integer import IntegerHolder
+from .range import RangeHolder
+from .string import StringHolder, MesonVersionString, MesonVersionStringHolder
diff -Nru meson-0.53.2/mesonbuild/interpreter/primitives/integer.py meson-0.61.2/mesonbuild/interpreter/primitives/integer.py
--- meson-0.53.2/mesonbuild/interpreter/primitives/integer.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/primitives/integer.py	2021-11-02 19:58:13.000000000 +0000
@@ -0,0 +1,82 @@
+# Copyright 2021 The Meson development team
+# SPDX-license-identifier: Apache-2.0
+
+from ...interpreterbase import (
+    ObjectHolder,
+    MesonOperator,
+    typed_operator,
+    noKwargs,
+    noPosargs,
+
+    TYPE_var,
+    TYPE_kwargs,
+
+    InvalidArguments
+)
+
+import typing as T
+
+if T.TYPE_CHECKING:
+    # Object holders need the actual interpreter
+    from ...interpreter import Interpreter
+
+class IntegerHolder(ObjectHolder[int]):
+    def __init__(self, obj: int, interpreter: 'Interpreter') -> None:
+        super().__init__(obj, interpreter)
+        self.methods.update({
+            'is_even': self.is_even_method,
+            'is_odd': self.is_odd_method,
+            'to_string': self.to_string_method,
+        })
+
+        self.trivial_operators.update({
+            # Arithmetic
+            MesonOperator.UMINUS: (None, lambda x: -self.held_object),
+            MesonOperator.PLUS: (int, lambda x: self.held_object + x),
+            MesonOperator.MINUS: (int, lambda x: self.held_object - x),
+            MesonOperator.TIMES: (int, lambda x: self.held_object * x),
+
+            # Comparison
+            MesonOperator.EQUALS: (int, lambda x: self.held_object == x),
+            MesonOperator.NOT_EQUALS: (int, lambda x: self.held_object != x),
+            MesonOperator.GREATER: (int, lambda x: self.held_object > x),
+            MesonOperator.LESS: (int, lambda x: self.held_object < x),
+            MesonOperator.GREATER_EQUALS: (int, lambda x: self.held_object >= x),
+            MesonOperator.LESS_EQUALS: (int, lambda x: self.held_object <= x),
+        })
+
+        # Use actual methods for functions that require additional checks
+        self.operators.update({
+            MesonOperator.DIV: self.op_div,
+            MesonOperator.MOD: self.op_mod,
+        })
+
+    def display_name(self) -> str:
+        return 'int'
+
+    @noKwargs
+    @noPosargs
+    def is_even_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return self.held_object % 2 == 0
+
+    @noKwargs
+    @noPosargs
+    def is_odd_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+        return self.held_object % 2 != 0
+
+    @noKwargs
+    @noPosargs
+    def to_string_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return str(self.held_object)
+
+    @typed_operator(MesonOperator.DIV, int)
+    def op_div(self, other: int) -> int:
+        if other == 0:
+            raise InvalidArguments('Tried to divide by 0')
+        return self.held_object // other
+
+    @typed_operator(MesonOperator.MOD, int)
+    def op_mod(self, other: int) -> int:
+        if other == 0:
+            raise InvalidArguments('Tried to divide by 0')
+        return self.held_object % other
diff -Nru meson-0.53.2/mesonbuild/interpreter/primitives/range.py meson-0.61.2/mesonbuild/interpreter/primitives/range.py
--- meson-0.53.2/mesonbuild/interpreter/primitives/range.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/primitives/range.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,34 @@
+# Copyright 2021 The Meson development team
+# SPDX-license-identifier: Apache-2.0
+
+import typing as T
+
+from ...interpreterbase import (
+    MesonInterpreterObject,
+    IterableObject,
+    MesonOperator,
+    InvalidArguments,
+)
+
+class RangeHolder(MesonInterpreterObject, IterableObject):
+    def __init__(self, start: int, stop: int, step: int, *, subproject: str) -> None:
+        super().__init__(subproject=subproject)
+        self.range = range(start, stop, step)
+        self.operators.update({
+            MesonOperator.INDEX: self.op_index,
+        })
+
+    def op_index(self, other: int) -> int:
+        try:
+            return self.range[other]
+        except:
+            raise InvalidArguments(f'Index {other} out of bounds of range.')
+
+    def iter_tuple_size(self) -> None:
+        return None
+
+    def iter_self(self) -> T.Iterator[int]:
+        return iter(self.range)
+
+    def size(self) -> int:
+        return len(self.range)
diff -Nru meson-0.53.2/mesonbuild/interpreter/primitives/string.py meson-0.61.2/mesonbuild/interpreter/primitives/string.py
--- meson-0.53.2/mesonbuild/interpreter/primitives/string.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/primitives/string.py	2021-11-25 22:00:46.000000000 +0000
@@ -0,0 +1,183 @@
+# Copyright 2021 The Meson development team
+# SPDX-license-identifier: Apache-2.0
+
+import re
+import os
+from pathlib import PurePath
+
+import typing as T
+
+from ...mesonlib import version_compare
+from ...interpreterbase import (
+    ObjectHolder,
+    MesonOperator,
+    FeatureNew,
+    typed_operator,
+    noArgsFlattening,
+    noKwargs,
+    noPosargs,
+    typed_pos_args,
+
+    TYPE_var,
+    TYPE_kwargs,
+
+    InvalidArguments,
+)
+
+
+if T.TYPE_CHECKING:
+    # Object holders need the actual interpreter
+    from ...interpreter import Interpreter
+
+class StringHolder(ObjectHolder[str]):
+    def __init__(self, obj: str, interpreter: 'Interpreter') -> None:
+        super().__init__(obj, interpreter)
+        self.methods.update({
+            'contains': self.contains_method,
+            'startswith': self.startswith_method,
+            'endswith': self.endswith_method,
+            'format': self.format_method,
+            'join': self.join_method,
+            'replace': self.replace_method,
+            'split': self.split_method,
+            'strip': self.strip_method,
+            'substring': self.substring_method,
+            'to_int': self.to_int_method,
+            'to_lower': self.to_lower_method,
+            'to_upper': self.to_upper_method,
+            'underscorify': self.underscorify_method,
+            'version_compare': self.version_compare_method,
+        })
+
+        self.trivial_operators.update({
+            # Arithmetic
+            MesonOperator.PLUS: (str, lambda x: self.held_object + x),
+
+            # Comparison
+            MesonOperator.EQUALS: (str, lambda x: self.held_object == x),
+            MesonOperator.NOT_EQUALS: (str, lambda x: self.held_object != x),
+            MesonOperator.GREATER: (str, lambda x: self.held_object > x),
+            MesonOperator.LESS: (str, lambda x: self.held_object < x),
+            MesonOperator.GREATER_EQUALS: (str, lambda x: self.held_object >= x),
+            MesonOperator.LESS_EQUALS: (str, lambda x: self.held_object <= x),
+        })
+
+        # Use actual methods for functions that require additional checks
+        self.operators.update({
+            MesonOperator.DIV: self.op_div,
+            MesonOperator.INDEX: self.op_index,
+        })
+
+    def display_name(self) -> str:
+        return 'str'
+
+    @noKwargs
+    @typed_pos_args('str.contains', str)
+    def contains_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
+        return self.held_object.find(args[0]) >= 0
+
+    @noKwargs
+    @typed_pos_args('str.startswith', str)
+    def startswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
+        return self.held_object.startswith(args[0])
+
+    @noKwargs
+    @typed_pos_args('str.endswith', str)
+    def endswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
+        return self.held_object.endswith(args[0])
+
+    @noArgsFlattening
+    @noKwargs
+    @typed_pos_args('str.format', varargs=object)
+    def format_method(self, args: T.Tuple[T.List[object]], kwargs: TYPE_kwargs) -> str:
+        arg_strings: T.List[str] = []
+        for arg in args[0]:
+            if isinstance(arg, bool): # Python boolean is upper case.
+                arg = str(arg).lower()
+            arg_strings.append(str(arg))
+
+        def arg_replace(match: T.Match[str]) -> str:
+            idx = int(match.group(1))
+            if idx >= len(arg_strings):
+                raise InvalidArguments(f'Format placeholder @{idx}@ out of range.')
+            return arg_strings[idx]
+
+        return re.sub(r'@(\d+)@', arg_replace, self.held_object)
+
+    @noKwargs
+    @typed_pos_args('str.join', varargs=str)
+    def join_method(self, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.join(args[0])
+
+    @noKwargs
+    @typed_pos_args('str.replace', str, str)
+    def replace_method(self, args: T.Tuple[str, str], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.replace(args[0], args[1])
+
+    @noKwargs
+    @typed_pos_args('str.split', optargs=[str])
+    def split_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> T.List[str]:
+        return self.held_object.split(args[0])
+
+    @noKwargs
+    @typed_pos_args('str.strip', optargs=[str])
+    def strip_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.strip(args[0])
+
+    @noKwargs
+    @typed_pos_args('str.substring', optargs=[int, int])
+    def substring_method(self, args: T.Tuple[T.Optional[int], T.Optional[int]], kwargs: TYPE_kwargs) -> str:
+        start = args[0] if args[0] is not None else 0
+        end   = args[1] if args[1] is not None else len(self.held_object)
+        return self.held_object[start:end]
+
+    @noKwargs
+    @noPosargs
+    def to_int_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
+        try:
+            return int(self.held_object)
+        except ValueError:
+            raise InvalidArguments(f'String {self.held_object!r} cannot be converted to int')
+
+    @noKwargs
+    @noPosargs
+    def to_lower_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.lower()
+
+    @noKwargs
+    @noPosargs
+    def to_upper_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return self.held_object.upper()
+
+    @noKwargs
+    @noPosargs
+    def underscorify_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+        return re.sub(r'[^a-zA-Z0-9]', '_', self.held_object)
+
+    @noKwargs
+    @typed_pos_args('str.version_compare', str)
+    def version_compare_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
+        return version_compare(self.held_object, args[0])
+
+    @FeatureNew('/ with string arguments', '0.49.0')
+    @typed_operator(MesonOperator.DIV, str)
+    def op_div(self, other: str) -> str:
+        return os.path.join(self.held_object, other).replace('\\', '/')
+
+    @typed_operator(MesonOperator.INDEX, int)
+    def op_index(self, other: int) -> str:
+        try:
+            return self.held_object[other]
+        except IndexError:
+            raise InvalidArguments(f'Index {other} out of bounds of string of size {len(self.held_object)}.')
+
+
+class MesonVersionString(str):
+    pass
+
+class MesonVersionStringHolder(StringHolder):
+    @noKwargs
+    @typed_pos_args('str.version_compare', str)
+    def version_compare_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
+        self.interpreter.tmp_meson_version = args[0]
+        return version_compare(self.held_object, args[0])
diff -Nru meson-0.53.2/mesonbuild/interpreter/type_checking.py meson-0.61.2/mesonbuild/interpreter/type_checking.py
--- meson-0.53.2/mesonbuild/interpreter/type_checking.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter/type_checking.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,310 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright © 2021 Intel Corporation
+
+"""Helpers for strict type checking."""
+
+import typing as T
+
+from .. import compilers
+from ..build import EnvironmentVariables, CustomTarget, BuildTarget, CustomTargetIndex, ExtractedObjects, GeneratedList, IncludeDirs
+from ..coredata import UserFeatureOption
+from ..interpreterbase import TYPE_var
+from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo
+from ..mesonlib import File, FileMode, MachineChoice, listify, has_path_sep, OptionKey
+from ..programs import ExternalProgram
+
+# Helper definition for type checks that are `Optional[T]`
+NoneType: T.Type[None] = type(None)
+
+
+def in_set_validator(choices: T.Set[str]) -> T.Callable[[str], T.Optional[str]]:
+    """Check that the choice given was one of the given set."""
+
+    def inner(check: str) -> T.Optional[str]:
+        if check not in choices:
+            return f"must be one of {', '.join(sorted(choices))}, not {check}"
+        return None
+
+    return inner
+
+
+def _language_validator(l: T.List[str]) -> T.Optional[str]:
+    """Validate language keyword argument.
+
+    Particularly for functions like `add_compiler()`, and `add_*_args()`
+    """
+    diff = {a.lower() for a in l}.difference(compilers.all_languages)
+    if diff:
+        return f'unknown languages: {", ".join(diff)}'
+    return None
+
+
+def _install_mode_validator(mode: T.List[T.Union[str, bool, int]]) -> T.Optional[str]:
+    """Validate the `install_mode` keyword argument.
+
+    This is a rather odd thing, it's a scalar, or an array of 3 values in the form:
+    [(str | False), (str | int | False) = False, (str | int | False) = False]
+    where the second and third components are not required and default to False.
+    """
+    if not mode:
+        return None
+    if True in mode:
+        return 'components can only be permission strings, numbers, or False'
+    if len(mode) > 3:
+        return 'may have at most 3 elements'
+
+    perms = mode[0]
+    if not isinstance(perms, (str, bool)):
+        return 'first component must be a permissions string or False'
+
+    if isinstance(perms, str):
+        if not len(perms) == 9:
+            return ('permissions string must be exactly 9 characters in the form rwxr-xr-x,'
+                    f' got {len(perms)}')
+        for i in [0, 3, 6]:
+            if perms[i] not in {'-', 'r'}:
+                return f'permissions character {i+1} must be "-" or "r", not {perms[i]}'
+        for i in [1, 4, 7]:
+            if perms[i] not in {'-', 'w'}:
+                return f'permissions character {i+1} must be "-" or "w", not {perms[i]}'
+        for i in [2, 5]:
+            if perms[i] not in {'-', 'x', 's', 'S'}:
+                return f'permissions character {i+1} must be "-", "s", "S", or "x", not {perms[i]}'
+        if perms[8] not in {'-', 'x', 't', 'T'}:
+            return f'permission character 9 must be "-", "t", "T", or "x", not {perms[8]}'
+
+        if len(mode) >= 2 and not isinstance(mode[1], (int, str, bool)):
+            return 'second componenent can only be a string, number, or False'
+        if len(mode) >= 3 and not isinstance(mode[2], (int, str, bool)):
+            return 'third componenent can only be a string, number, or False'
+
+    return None
+
+
+def _install_mode_convertor(mode: T.Optional[T.List[T.Union[str, bool, int]]]) -> FileMode:
+    """Convert the DSL form of the `install_mode` keyword argument to `FileMode`
+
+    This is not required, and if not required returns None
+
+    TODO: It's not clear to me why this needs to be None and not just return an
+    empty FileMode.
+    """
+    # this has already been validated by the validator
+    return FileMode(*(m if isinstance(m, str) else None for m in mode))
+
+
+def _lower_strlist(input: T.List[str]) -> T.List[str]:
+    """Lower a list of strings.
+
+    mypy (but not pyright) gets confused about using a lambda as the convertor function
+    """
+    return [i.lower() for i in input]
+
+
+NATIVE_KW = KwargInfo(
+    'native', bool,
+    default=False,
+    convertor=lambda n: MachineChoice.BUILD if n else MachineChoice.HOST)
+
+LANGUAGE_KW = KwargInfo(
+    'language', ContainerTypeInfo(list, str, allow_empty=False),
+    listify=True,
+    required=True,
+    validator=_language_validator,
+    convertor=_lower_strlist)
+
+INSTALL_MODE_KW: KwargInfo[T.List[T.Union[str, bool, int]]] = KwargInfo(
+    'install_mode',
+    ContainerTypeInfo(list, (str, bool, int)),
+    listify=True,
+    default=[],
+    validator=_install_mode_validator,
+    convertor=_install_mode_convertor,
+)
+
+REQUIRED_KW: KwargInfo[T.Union[bool, UserFeatureOption]] = KwargInfo(
+    'required',
+    (bool, UserFeatureOption),
+    default=True,
+    # TODO: extract_required_kwarg could be converted to a convertor
+)
+
+DISABLER_KW: KwargInfo[bool] = KwargInfo('disabler', bool, default=False)
+
+def _env_validator(value: T.Union[EnvironmentVariables, T.List['TYPE_var'], T.Dict[str, 'TYPE_var'], str, None]) -> T.Optional[str]:
+    def _splitter(v: str) -> T.Optional[str]:
+        split = v.split('=', 1)
+        if len(split) == 1:
+            return f'"{v}" is not two string values separated by an "="'
+        return None
+
+    if isinstance(value, str):
+        v = _splitter(value)
+        if v is not None:
+            return v
+    elif isinstance(value, list):
+        for i in listify(value):
+            if not isinstance(i, str):
+                return f"All array elements must be a string, not {i!r}"
+            v = _splitter(i)
+            if v is not None:
+                return v
+    elif isinstance(value, dict):
+        # We don't need to spilt here, just do the type checking
+        for k, dv in value.items():
+            if not isinstance(dv, str):
+                return f"Dictionary element {k} must be a string not {dv!r}"
+    # We know that otherwise we have an EnvironmentVariables object or None, and
+    # we're okay at this point
+    return None
+
+
+def split_equal_string(input: str) -> T.Tuple[str, str]:
+    """Split a string in the form `x=y`
+
+    This assumes that the string has already been validated to split properly.
+    """
+    a, b = input.split('=', 1)
+    return (a, b)
+
+
+def _env_convertor(value: T.Union[EnvironmentVariables, T.List[str], T.List[T.List[str]], T.Dict[str, str], str, None]) -> EnvironmentVariables:
+    if isinstance(value, str):
+        return EnvironmentVariables(dict([split_equal_string(value)]))
+    elif isinstance(value, list):
+        return EnvironmentVariables(dict(split_equal_string(v) for v in listify(value)))
+    elif isinstance(value, dict):
+        return EnvironmentVariables(value)
+    elif value is None:
+        return EnvironmentVariables()
+    return value
+
+
+ENV_KW: KwargInfo[T.Union[EnvironmentVariables, T.List, T.Dict, str, None]] = KwargInfo(
+    'env',
+    (EnvironmentVariables, list, dict, str, NoneType),
+    validator=_env_validator,
+    convertor=_env_convertor,
+)
+
+DEPFILE_KW: KwargInfo[T.Optional[str]] = KwargInfo(
+    'depfile',
+    (str, type(None)),
+    validator=lambda x: 'Depfile must be a plain filename with a subdirectory' if has_path_sep(x) else None
+)
+
+# TODO: CustomTargetIndex should be supported here as well
+DEPENDS_KW: KwargInfo[T.List[T.Union[BuildTarget, CustomTarget]]] = KwargInfo(
+    'depends',
+    ContainerTypeInfo(list, (BuildTarget, CustomTarget)),
+    listify=True,
+    default=[],
+)
+
+DEPEND_FILES_KW: KwargInfo[T.List[T.Union[str, File]]] = KwargInfo(
+    'depend_files',
+    ContainerTypeInfo(list, (File, str)),
+    listify=True,
+    default=[],
+)
+
+COMMAND_KW: KwargInfo[T.List[T.Union[str, BuildTarget, CustomTarget, CustomTargetIndex, ExternalProgram, File]]] = KwargInfo(
+    'command',
+    # TODO: should accept CustomTargetIndex as well?
+    ContainerTypeInfo(list, (str, BuildTarget, CustomTarget, CustomTargetIndex, ExternalProgram, File), allow_empty=False),
+    required=True,
+    listify=True,
+    default=[],
+)
+
+def _override_options_convertor(raw: T.List[str]) -> T.Dict[OptionKey, str]:
+    output: T.Dict[OptionKey, str] = {}
+    for each in raw:
+        k, v = split_equal_string(each)
+        output[OptionKey.from_string(k)] = v
+    return output
+
+
+OVERRIDE_OPTIONS_KW: KwargInfo[T.List[str]] = KwargInfo(
+    'override_options',
+    ContainerTypeInfo(list, str),
+    listify=True,
+    default=[],
+    # Reusing the env validator is a littl overkill, but nicer than duplicating the code
+    validator=_env_validator,
+    convertor=_override_options_convertor,
+)
+
+
+def _output_validator(outputs: T.List[str]) -> T.Optional[str]:
+    for i in outputs:
+        if i == '':
+            return 'Output must not be empty.'
+        elif i.strip() == '':
+            return 'Output must not consist only of whitespace.'
+        elif has_path_sep(i):
+            return f'Output {i!r} must not contain a path segment.'
+
+    return None
+
+CT_OUTPUT_KW: KwargInfo[T.List[str]] = KwargInfo(
+    'output',
+    ContainerTypeInfo(list, str, allow_empty=False),
+    listify=True,
+    required=True,
+    default=[],
+    validator=_output_validator,
+)
+
+CT_INPUT_KW: KwargInfo[T.List[T.Union[str, File, ExternalProgram, BuildTarget, CustomTarget, CustomTargetIndex, ExtractedObjects, GeneratedList]]] = KwargInfo(
+    'input',
+    ContainerTypeInfo(list, (str, File, ExternalProgram, BuildTarget, CustomTarget, CustomTargetIndex, ExtractedObjects, GeneratedList)),
+    listify=True,
+    default=[],
+)
+
+CT_INSTALL_TAG_KW: KwargInfo[T.List[T.Union[str, bool]]] = KwargInfo(
+    'install_tag',
+    ContainerTypeInfo(list, (str, bool)),
+    listify=True,
+    default=[],
+    since='0.60.0',
+)
+
+INSTALL_KW = KwargInfo('install', bool, default=False)
+
+CT_INSTALL_DIR_KW: KwargInfo[T.List[T.Union[str, bool]]] = KwargInfo(
+    'install_dir',
+    ContainerTypeInfo(list, (str, bool)),
+    listify=True,
+    default=[],
+)
+
+CT_BUILD_BY_DEFAULT: KwargInfo[T.Optional[bool]] = KwargInfo('build_by_default', (bool, type(None)), since='0.40.0')
+
+CT_BUILD_ALWAYS: KwargInfo[T.Optional[bool]] = KwargInfo(
+    'build_always', (bool, NoneType),
+     deprecated='0.47.0',
+     deprecated_message='combine build_by_default and build_always_stale instead.',
+)
+
+CT_BUILD_ALWAYS_STALE: KwargInfo[T.Optional[bool]] = KwargInfo(
+    'build_always_stale', (bool, NoneType),
+    since='0.47.0',
+)
+
+INCLUDE_DIRECTORIES: KwargInfo[T.List[T.Union[str, IncludeDirs]]] = KwargInfo(
+    'include_dirs',
+    ContainerTypeInfo(list, (str, IncludeDirs)),
+    listify=True,
+    default=[],
+)
+
+# for cases like default_options and override_options
+DEFAULT_OPTIONS: KwargInfo[T.List[str]] = KwargInfo(
+    'default_options',
+    ContainerTypeInfo(list, (str, IncludeDirs)),
+    listify=True,
+    default=[],
+    validator=_env_validator,
+)
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/baseobjects.py meson-0.61.2/mesonbuild/interpreterbase/baseobjects.py
--- meson-0.53.2/mesonbuild/interpreterbase/baseobjects.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/baseobjects.py	2021-11-02 19:58:13.000000000 +0000
@@ -0,0 +1,179 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .. import mparser
+from .exceptions import InvalidCode, InvalidArguments
+from .helpers import flatten, resolve_second_level_holders
+from .operator import MesonOperator
+from ..mesonlib import HoldableObject, MesonBugException
+import textwrap
+
+import typing as T
+from abc import ABCMeta
+
+if T.TYPE_CHECKING:
+    # Object holders need the actual interpreter
+    from ..interpreter import Interpreter
+
+TV_fw_var = T.Union[str, int, bool, list, dict, 'InterpreterObject']
+TV_fw_args = T.List[T.Union[mparser.BaseNode, TV_fw_var]]
+TV_fw_kwargs = T.Dict[str, T.Union[mparser.BaseNode, TV_fw_var]]
+
+TV_func = T.TypeVar('TV_func', bound=T.Callable[..., T.Any])
+
+TYPE_elementary = T.Union[str, int, bool, T.List[T.Any], T.Dict[str, T.Any]]
+TYPE_var = T.Union[TYPE_elementary, HoldableObject, 'MesonInterpreterObject']
+TYPE_nvar = T.Union[TYPE_var, mparser.BaseNode]
+TYPE_kwargs = T.Dict[str, TYPE_var]
+TYPE_nkwargs = T.Dict[str, TYPE_nvar]
+TYPE_key_resolver = T.Callable[[mparser.BaseNode], str]
+
+if T.TYPE_CHECKING:
+    from typing_extensions import Protocol
+    __T = T.TypeVar('__T', bound=TYPE_var, contravariant=True)
+
+    class OperatorCall(Protocol[__T]):
+        def __call__(self, other: __T) -> TYPE_var: ...
+
+class InterpreterObject:
+    def __init__(self, *, subproject: T.Optional[str] = None) -> None:
+        self.methods: T.Dict[
+            str,
+            T.Callable[[T.List[TYPE_var], TYPE_kwargs], TYPE_var]
+        ] = {}
+        self.operators: T.Dict[MesonOperator, 'OperatorCall'] = {}
+        self.trivial_operators: T.Dict[
+            MesonOperator,
+            T.Tuple[
+                T.Union[T.Type, T.Tuple[T.Type, ...]],
+                'OperatorCall'
+            ]
+        ] = {}
+        # Current node set during a method call. This can be used as location
+        # when printing a warning message during a method call.
+        self.current_node:  mparser.BaseNode = None
+        self.subproject: str = subproject or ''
+
+        # Some default operators supported by all objects
+        self.operators.update({
+            MesonOperator.EQUALS: self.op_equals,
+            MesonOperator.NOT_EQUALS: self.op_not_equals,
+        })
+
+    # The type of the object that can be printed to the user
+    def display_name(self) -> str:
+        return type(self).__name__
+
+    def method_call(
+                self,
+                method_name: str,
+                args: T.List[TYPE_var],
+                kwargs: TYPE_kwargs
+            ) -> TYPE_var:
+        if method_name in self.methods:
+            method = self.methods[method_name]
+            if not getattr(method, 'no-args-flattening', False):
+                args = flatten(args)
+            if not getattr(method, 'no-second-level-holder-flattening', False):
+                args, kwargs = resolve_second_level_holders(args, kwargs)
+            return method(args, kwargs)
+        raise InvalidCode(f'Unknown method "{method_name}" in object {self} of type {type(self).__name__}.')
+
+    def operator_call(self, operator: MesonOperator, other: TYPE_var) -> TYPE_var:
+        if operator in self.trivial_operators:
+            op = self.trivial_operators[operator]
+            if op[0] is None and other is not None:
+                raise MesonBugException(f'The unary operator `{operator.value}` of {self.display_name()} was passed the object {other} of type {type(other).__name__}')
+            if op[0] is not None and not isinstance(other, op[0]):
+                raise InvalidArguments(f'The `{operator.value}` operator of {self.display_name()} does not accept objects of type {type(other).__name__} ({other})')
+            return op[1](other)
+        if operator in self.operators:
+            return self.operators[operator](other)
+        raise InvalidCode(f'Object {self} of type {self.display_name()} does not support the `{operator.value}` operator.')
+
+    # Default comparison operator support
+    def _throw_comp_exception(self, other: TYPE_var, opt_type: str) -> T.NoReturn:
+        raise InvalidArguments(textwrap.dedent(
+            f'''
+                Trying to compare values of different types ({self.display_name()}, {type(other).__name__}) using {opt_type}.
+                This was deprecated and undefined behavior previously and is as of 0.60.0 a hard error.
+            '''
+        ))
+
+    def op_equals(self, other: TYPE_var) -> bool:
+        # We use `type(...) == type(...)` here to enforce an *exact* match for comparison. We
+        # don't want comparisons to be possible where `isinstance(derived_obj, type(base_obj))`
+        # would pass because this comparison must never be true: `derived_obj == base_obj`
+        if type(self) != type(other):
+            self._throw_comp_exception(other, '==')
+        return self == other
+
+    def op_not_equals(self, other: TYPE_var) -> bool:
+        if type(self) != type(other):
+            self._throw_comp_exception(other, '!=')
+        return self != other
+
+class MesonInterpreterObject(InterpreterObject):
+    ''' All non-elementary objects and non-object-holders should be derived from this '''
+
+class MutableInterpreterObject:
+    ''' Dummy class to mark the object type as mutable '''
+
+HoldableTypes = (HoldableObject, int, bool, str, list, dict)
+TYPE_HoldableTypes = T.Union[TYPE_elementary, HoldableObject]
+InterpreterObjectTypeVar = T.TypeVar('InterpreterObjectTypeVar', bound=TYPE_HoldableTypes)
+
+class ObjectHolder(InterpreterObject, T.Generic[InterpreterObjectTypeVar]):
+    def __init__(self, obj: InterpreterObjectTypeVar, interpreter: 'Interpreter') -> None:
+        super().__init__(subproject=interpreter.subproject)
+        # This causes some type checkers to assume that obj is a base
+        # HoldableObject, not the specialized type, so only do this assert in
+        # non-type checking situations
+        if not T.TYPE_CHECKING:
+            assert isinstance(obj, HoldableTypes), f'This is a bug: Trying to hold object of type `{type(obj).__name__}` that is not in `{HoldableTypes}`'
+        self.held_object = obj
+        self.interpreter = interpreter
+        self.env = self.interpreter.environment
+
+    # Hide the object holder abstraction from the user
+    def display_name(self) -> str:
+        return type(self.held_object).__name__
+
+    # Override default comparison operators for the held object
+    def op_equals(self, other: TYPE_var) -> bool:
+        # See the comment from InterpreterObject why we are using `type()` here.
+        if type(self.held_object) != type(other):
+            self._throw_comp_exception(other, '==')
+        return self.held_object == other
+
+    def op_not_equals(self, other: TYPE_var) -> bool:
+        if type(self.held_object) != type(other):
+            self._throw_comp_exception(other, '!=')
+        return self.held_object != other
+
+    def __repr__(self) -> str:
+        return f'<[{type(self).__name__}] holds [{type(self.held_object).__name__}]: {self.held_object!r}>'
+
+class IterableObject(metaclass=ABCMeta):
+    '''Base class for all objects that can be iterated over in a foreach loop'''
+
+    def iter_tuple_size(self) -> T.Optional[int]:
+        '''Return the size of the tuple for each iteration. Returns None if only a single value is returned.'''
+        raise MesonBugException(f'iter_tuple_size not implemented for {self.__class__.__name__}')
+
+    def iter_self(self) -> T.Iterator[T.Union[TYPE_var, T.Tuple[TYPE_var, ...]]]:
+        raise MesonBugException(f'iter not implemented for {self.__class__.__name__}')
+
+    def size(self) -> int:
+        raise MesonBugException(f'size not implemented for {self.__class__.__name__}')
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/decorators.py meson-0.61.2/mesonbuild/interpreterbase/decorators.py
--- meson-0.53.2/mesonbuild/interpreterbase/decorators.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/decorators.py	2022-01-17 10:50:45.000000000 +0000
@@ -0,0 +1,775 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .. import mesonlib, mlog
+from .baseobjects import TV_func, TYPE_var, TYPE_kwargs
+from .disabler import Disabler
+from .exceptions import InterpreterException, InvalidArguments
+from .operator import MesonOperator
+from ._unholder import _unholder
+
+from functools import wraps
+import abc
+import itertools
+import copy
+import typing as T
+if T.TYPE_CHECKING:
+    from .. import mparser
+
+def get_callee_args(wrapped_args: T.Sequence[T.Any]) -> T.Tuple['mparser.BaseNode', T.List['TYPE_var'], 'TYPE_kwargs', str]:
+    # First argument could be InterpreterBase, InterpreterObject or ModuleObject.
+    # In the case of a ModuleObject it is the 2nd argument (ModuleState) that
+    # contains the needed information.
+    s = wrapped_args[0]
+    if not hasattr(s, 'current_node'):
+        s = wrapped_args[1]
+    node = s.current_node
+    subproject = s.subproject
+    args = kwargs = None
+    if len(wrapped_args) >= 3:
+        args = wrapped_args[-2]
+        kwargs = wrapped_args[-1]
+    return node, args, kwargs, subproject
+
+def noPosargs(f: TV_func) -> TV_func:
+    @wraps(f)
+    def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+        args = get_callee_args(wrapped_args)[1]
+        if args:
+            raise InvalidArguments('Function does not take positional arguments.')
+        return f(*wrapped_args, **wrapped_kwargs)
+    return T.cast(TV_func, wrapped)
+
+def noKwargs(f: TV_func) -> TV_func:
+    @wraps(f)
+    def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+        kwargs = get_callee_args(wrapped_args)[2]
+        if kwargs:
+            raise InvalidArguments('Function does not take keyword arguments.')
+        return f(*wrapped_args, **wrapped_kwargs)
+    return T.cast(TV_func, wrapped)
+
+def stringArgs(f: TV_func) -> TV_func:
+    @wraps(f)
+    def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+        args = get_callee_args(wrapped_args)[1]
+        if not isinstance(args, list):
+            mlog.debug('Not a list:', str(args))
+            raise InvalidArguments('Argument not a list.')
+        if not all(isinstance(s, str) for s in args):
+            mlog.debug('Element not a string:', str(args))
+            raise InvalidArguments('Arguments must be strings.')
+        return f(*wrapped_args, **wrapped_kwargs)
+    return T.cast(TV_func, wrapped)
+
+def noArgsFlattening(f: TV_func) -> TV_func:
+    setattr(f, 'no-args-flattening', True)  # noqa: B010
+    return f
+
+def noSecondLevelHolderResolving(f: TV_func) -> TV_func:
+    setattr(f, 'no-second-level-holder-flattening', True)  # noqa: B010
+    return f
+
+def unholder_return(f: TV_func) -> T.Callable[..., TYPE_var]:
+    @wraps(f)
+    def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+        res = f(*wrapped_args, **wrapped_kwargs)
+        return _unholder(res)
+    return T.cast(T.Callable[..., TYPE_var], wrapped)
+
+def disablerIfNotFound(f: TV_func) -> TV_func:
+    @wraps(f)
+    def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+        kwargs = get_callee_args(wrapped_args)[2]
+        disabler = kwargs.pop('disabler', False)
+        ret = f(*wrapped_args, **wrapped_kwargs)
+        if disabler and not ret.found():
+            return Disabler()
+        return ret
+    return T.cast(TV_func, wrapped)
+
+class permittedKwargs:
+
+    def __init__(self, permitted: T.Set[str]):
+        self.permitted = permitted  # type: T.Set[str]
+
+    def __call__(self, f: TV_func) -> TV_func:
+        @wraps(f)
+        def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+            kwargs = get_callee_args(wrapped_args)[2]
+            unknowns = set(kwargs).difference(self.permitted)
+            if unknowns:
+                ustr = ', '.join([f'"{u}"' for u in sorted(unknowns)])
+                raise InvalidArguments(f'Got unknown keyword arguments {ustr}')
+            return f(*wrapped_args, **wrapped_kwargs)
+        return T.cast(TV_func, wrapped)
+
+if T.TYPE_CHECKING:
+    from .baseobjects import InterpreterObject
+    from typing_extensions import Protocol
+
+    _TV_IntegerObject = T.TypeVar('_TV_IntegerObject', bound=InterpreterObject, contravariant=True)
+    _TV_ARG1 = T.TypeVar('_TV_ARG1', bound=TYPE_var, contravariant=True)
+
+    class FN_Operator(Protocol[_TV_IntegerObject, _TV_ARG1]):
+        def __call__(s, self: _TV_IntegerObject, other: _TV_ARG1) -> TYPE_var: ...
+    _TV_FN_Operator = T.TypeVar('_TV_FN_Operator', bound=FN_Operator)
+
+def typed_operator(operator: MesonOperator,
+                   types: T.Union[T.Type, T.Tuple[T.Type, ...]]) -> T.Callable[['_TV_FN_Operator'], '_TV_FN_Operator']:
+    """Decorator that does type checking for operator calls.
+
+    The principle here is similar to typed_pos_args, however much simpler
+    since only one other object ever is passed
+    """
+    def inner(f: '_TV_FN_Operator') -> '_TV_FN_Operator':
+        @wraps(f)
+        def wrapper(self: 'InterpreterObject', other: TYPE_var) -> TYPE_var:
+            if not isinstance(other, types):
+                raise InvalidArguments(f'The `{operator.value}` of {self.display_name()} does not accept objects of type {type(other).__name__} ({other})')
+            return f(self, other)
+        return T.cast('_TV_FN_Operator', wrapper)
+    return inner
+
+def unary_operator(operator: MesonOperator) -> T.Callable[['_TV_FN_Operator'], '_TV_FN_Operator']:
+    """Decorator that does type checking for unary operator calls.
+
+    This decorator is for unary operators that do not take any other objects.
+    It should be impossible for a user to accidentally break this. Triggering
+    this check always indicates a bug in the Meson interpreter.
+    """
+    def inner(f: '_TV_FN_Operator') -> '_TV_FN_Operator':
+        @wraps(f)
+        def wrapper(self: 'InterpreterObject', other: TYPE_var) -> TYPE_var:
+            if other is not None:
+                raise mesonlib.MesonBugException(f'The unary operator `{operator.value}` of {self.display_name()} was passed the object {other} of type {type(other).__name__}')
+            return f(self, other)
+        return T.cast('_TV_FN_Operator', wrapper)
+    return inner
+
+
+def typed_pos_args(name: str, *types: T.Union[T.Type, T.Tuple[T.Type, ...]],
+                   varargs: T.Optional[T.Union[T.Type, T.Tuple[T.Type, ...]]] = None,
+                   optargs: T.Optional[T.List[T.Union[T.Type, T.Tuple[T.Type, ...]]]] = None,
+                   min_varargs: int = 0, max_varargs: int = 0) -> T.Callable[..., T.Any]:
+    """Decorator that types type checking of positional arguments.
+
+    This supports two different models of optional arguments, the first is the
+    variadic argument model. Variadic arguments are a possibly bounded,
+    possibly unbounded number of arguments of the same type (unions are
+    supported). The second is the standard default value model, in this case
+    a number of optional arguments may be provided, but they are still
+    ordered, and they may have different types.
+
+    This function does not support mixing variadic and default arguments.
+
+    :name: The name of the decorated function (as displayed in error messages)
+    :varargs: They type(s) of any variadic arguments the function takes. If
+        None the function takes no variadic args
+    :min_varargs: the minimum number of variadic arguments taken
+    :max_varargs: the maximum number of variadic arguments taken. 0 means unlimited
+    :optargs: The types of any optional arguments parameters taken. If None
+        then no optional parameters are taken.
+
+    Some examples of usage blow:
+    >>> @typed_pos_args('mod.func', str, (str, int))
+    ... def func(self, state: ModuleState, args: T.Tuple[str, T.Union[str, int]], kwargs: T.Dict[str, T.Any]) -> T.Any:
+    ...     pass
+
+    >>> @typed_pos_args('method', str, varargs=str)
+    ... def method(self, node: BaseNode, args: T.Tuple[str, T.List[str]], kwargs: T.Dict[str, T.Any]) -> T.Any:
+    ...     pass
+
+    >>> @typed_pos_args('method', varargs=str, min_varargs=1)
+    ... def method(self, node: BaseNode, args: T.Tuple[T.List[str]], kwargs: T.Dict[str, T.Any]) -> T.Any:
+    ...     pass
+
+    >>> @typed_pos_args('method', str, optargs=[(str, int), str])
+    ... def method(self, node: BaseNode, args: T.Tuple[str, T.Optional[T.Union[str, int]], T.Optional[str]], kwargs: T.Dict[str, T.Any]) -> T.Any:
+    ...     pass
+
+    When should you chose `typed_pos_args('name', varargs=str,
+    min_varargs=1)` vs `typed_pos_args('name', str, varargs=str)`?
+
+    The answer has to do with the semantics of the function, if all of the
+    inputs are the same type (such as with `files()`) then the former is
+    correct, all of the arguments are string names of files. If the first
+    argument is something else the it should be separated.
+    """
+    def inner(f: TV_func) -> TV_func:
+
+        @wraps(f)
+        def wrapper(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+            args = get_callee_args(wrapped_args)[1]
+
+            # These are implementation programming errors, end users should never see them.
+            assert isinstance(args, list), args
+            assert max_varargs >= 0, 'max_varags cannot be negative'
+            assert min_varargs >= 0, 'min_varags cannot be negative'
+            assert optargs is None or varargs is None, \
+                'varargs and optargs not supported together as this would be ambiguous'
+
+            num_args = len(args)
+            num_types = len(types)
+            a_types = types
+
+            if varargs:
+                min_args = num_types + min_varargs
+                max_args = num_types + max_varargs
+                if max_varargs == 0 and num_args < min_args:
+                    raise InvalidArguments(f'{name} takes at least {min_args} arguments, but got {num_args}.')
+                elif max_varargs != 0 and (num_args < min_args or num_args > max_args):
+                    raise InvalidArguments(f'{name} takes between {min_args} and {max_args} arguments, but got {num_args}.')
+            elif optargs:
+                if num_args < num_types:
+                    raise InvalidArguments(f'{name} takes at least {num_types} arguments, but got {num_args}.')
+                elif num_args > num_types + len(optargs):
+                    raise InvalidArguments(f'{name} takes at most {num_types + len(optargs)} arguments, but got {num_args}.')
+                # Add the number of positional arguments required
+                if num_args > num_types:
+                    diff = num_args - num_types
+                    a_types = tuple(list(types) + list(optargs[:diff]))
+            elif num_args != num_types:
+                raise InvalidArguments(f'{name} takes exactly {num_types} arguments, but got {num_args}.')
+
+            for i, (arg, type_) in enumerate(itertools.zip_longest(args, a_types, fillvalue=varargs), start=1):
+                if not isinstance(arg, type_):
+                    if isinstance(type_, tuple):
+                        shouldbe = 'one of: {}'.format(", ".join(f'"{t.__name__}"' for t in type_))
+                    else:
+                        shouldbe = f'"{type_.__name__}"'
+                    raise InvalidArguments(f'{name} argument {i} was of type "{type(arg).__name__}" but should have been {shouldbe}')
+
+            # Ensure that we're actually passing a tuple.
+            # Depending on what kind of function we're calling the length of
+            # wrapped_args can vary.
+            nargs = list(wrapped_args)
+            i = nargs.index(args)
+            if varargs:
+                # if we have varargs we need to split them into a separate
+                # tuple, as python's typing doesn't understand tuples with
+                # fixed elements and variadic elements, only one or the other.
+                # so in that case we need T.Tuple[int, str, float, T.Tuple[str, ...]]
+                pos = args[:len(types)]
+                var = list(args[len(types):])
+                pos.append(var)
+                nargs[i] = tuple(pos)
+            elif optargs:
+                if num_args < num_types + len(optargs):
+                    diff = num_types + len(optargs) - num_args
+                    nargs[i] = tuple(list(args) + [None] * diff)
+                else:
+                    nargs[i] = args
+            else:
+                nargs[i] = tuple(args)
+            return f(*nargs, **wrapped_kwargs)
+
+        return T.cast(TV_func, wrapper)
+    return inner
+
+
+class ContainerTypeInfo:
+
+    """Container information for keyword arguments.
+
+    For keyword arguments that are containers (list or dict), this class encodes
+    that information.
+
+    :param container: the type of container
+    :param contains: the types the container holds
+    :param pairs: if the container is supposed to be of even length.
+        This is mainly used for interfaces that predate the addition of dictionaries, and use
+        `[key, value, key2, value2]` format.
+    :param allow_empty: Whether this container is allowed to be empty
+        There are some cases where containers not only must be passed, but must
+        not be empty, and other cases where an empty container is allowed.
+    """
+
+    def __init__(self, container: T.Type, contains: T.Union[T.Type, T.Tuple[T.Type, ...]], *,
+                 pairs: bool = False, allow_empty: bool = True):
+        self.container = container
+        self.contains = contains
+        self.pairs = pairs
+        self.allow_empty = allow_empty
+
+    def check(self, value: T.Any) -> bool:
+        """Check that a value is valid.
+
+        :param value: A value to check
+        :return: True if it is valid, False otherwise
+        """
+        if not isinstance(value, self.container):
+            return False
+        iter_ = iter(value.values()) if isinstance(value, dict) else iter(value)
+        for each in iter_:
+            if not isinstance(each, self.contains):
+                return False
+        if self.pairs and len(value) % 2 != 0:
+            return False
+        if not value and not self.allow_empty:
+            return False
+        return True
+
+    def description(self) -> str:
+        """Human readable description of this container type.
+
+        :return: string to be printed
+        """
+        container = 'dict' if self.container is dict else 'array'
+        if isinstance(self.contains, tuple):
+            contains = ' | '.join([t.__name__ for t in self.contains])
+        else:
+            contains = self.contains.__name__
+        s = f'{container}[{contains}]'
+        if self.pairs:
+            s += ' that has even size'
+        if not self.allow_empty:
+            s += ' that cannot be empty'
+        return s
+
+_T = T.TypeVar('_T')
+
+class _NULL_T:
+    """Special null type for evolution, this is an implementation detail."""
+
+
+_NULL = _NULL_T()
+
+class KwargInfo(T.Generic[_T]):
+
+    """A description of a keyword argument to a meson function
+
+    This is used to describe a value to the :func:typed_kwargs function.
+
+    :param name: the name of the parameter
+    :param types: A type or tuple of types that are allowed, or a :class:ContainerType
+    :param required: Whether this is a required keyword argument. defaults to False
+    :param listify: If true, then the argument will be listified before being
+        checked. This is useful for cases where the Meson DSL allows a scalar or
+        a container, but internally we only want to work with containers
+    :param default: A default value to use if this isn't set. defaults to None,
+        this may be safely set to a mutable type, as long as that type does not
+        itself contain mutable types, typed_kwargs will copy the default
+    :param since: Meson version in which this argument has been added. defaults to None
+    :param since_message: An extra message to pass to FeatureNew when since is triggered
+    :param deprecated: Meson version in which this argument has been deprecated. defaults to None
+    :param deprecated_message: An extra message to pass to FeatureDeprecated
+        when since is triggered
+    :param validator: A callable that does additional validation. This is mainly
+        intended for cases where a string is expected, but only a few specific
+        values are accepted. Must return None if the input is valid, or a
+        message if the input is invalid
+    :param convertor: A callable that converts the raw input value into a
+        different type. This is intended for cases such as the meson DSL using a
+        string, but the implementation using an Enum. This should not do
+        validation, just conversion.
+    :param deprecated_values: a dictionary mapping a value to the version of
+        meson it was deprecated in. The Value may be any valid value for this
+        argument.
+    :param since_values: a dictionary mapping a value to the version of meson it was
+        added in.
+    :param not_set_warning: A warning message that is logged if the kwarg is not
+        set by the user.
+    """
+    def __init__(self, name: str,
+                 types: T.Union[T.Type[_T], T.Tuple[T.Union[T.Type[_T], ContainerTypeInfo], ...], ContainerTypeInfo],
+                 *, required: bool = False, listify: bool = False,
+                 default: T.Optional[_T] = None,
+                 since: T.Optional[str] = None,
+                 since_message: T.Optional[str] = None,
+                 since_values: T.Optional[T.Dict[_T, T.Union[str, T.Tuple[str, str]]]] = None,
+                 deprecated: T.Optional[str] = None,
+                 deprecated_message: T.Optional[str] = None,
+                 deprecated_values: T.Optional[T.Dict[_T, T.Union[str, T.Tuple[str, str]]]] = None,
+                 validator: T.Optional[T.Callable[[T.Any], T.Optional[str]]] = None,
+                 convertor: T.Optional[T.Callable[[_T], object]] = None,
+                 not_set_warning: T.Optional[str] = None):
+        self.name = name
+        self.types = types
+        self.required = required
+        self.listify = listify
+        self.default = default
+        self.since = since
+        self.since_message = since_message
+        self.since_values = since_values
+        self.deprecated = deprecated
+        self.deprecated_message = deprecated_message
+        self.deprecated_values = deprecated_values
+        self.validator = validator
+        self.convertor = convertor
+        self.not_set_warning = not_set_warning
+
+    def evolve(self, *,
+               name: T.Union[str, _NULL_T] = _NULL,
+               required: T.Union[bool, _NULL_T] = _NULL,
+               listify: T.Union[bool, _NULL_T] = _NULL,
+               default: T.Union[_T, None, _NULL_T] = _NULL,
+               since: T.Union[str, None, _NULL_T] = _NULL,
+               since_message: T.Union[str, None, _NULL_T] = _NULL,
+               since_values: T.Union[T.Dict[_T, T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL,
+               deprecated: T.Union[str, None, _NULL_T] = _NULL,
+               deprecated_message: T.Union[str, None, _NULL_T] = _NULL,
+               deprecated_values: T.Union[T.Dict[_T, T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL,
+               validator: T.Union[T.Callable[[_T], T.Optional[str]], None, _NULL_T] = _NULL,
+               convertor: T.Union[T.Callable[[_T], TYPE_var], None, _NULL_T] = _NULL) -> 'KwargInfo':
+        """Create a shallow copy of this KwargInfo, with modifications.
+
+        This allows us to create a new copy of a KwargInfo with modifications.
+        This allows us to use a shared kwarg that implements complex logic, but
+        has slight differences in usage, such as being added to different
+        functions in different versions of Meson.
+
+        The use the _NULL special value here allows us to pass None, which has
+        meaning in many of these cases. _NULL itself is never stored, always
+        being replaced by either the copy in self, or the provided new version.
+        """
+        return type(self)(
+            name if not isinstance(name, _NULL_T) else self.name,
+            self.types,
+            listify=listify if not isinstance(listify, _NULL_T) else self.listify,
+            required=required if not isinstance(required, _NULL_T) else self.required,
+            default=default if not isinstance(default, _NULL_T) else self.default,
+            since=since if not isinstance(since, _NULL_T) else self.since,
+            since_message=since_message if not isinstance(since_message, _NULL_T) else self.since_message,
+            since_values=since_values if not isinstance(since_values, _NULL_T) else self.since_values,
+            deprecated=deprecated if not isinstance(deprecated, _NULL_T) else self.deprecated,
+            deprecated_message=deprecated_message if not isinstance(deprecated_message, _NULL_T) else self.deprecated_message,
+            deprecated_values=deprecated_values if not isinstance(deprecated_values, _NULL_T) else self.deprecated_values,
+            validator=validator if not isinstance(validator, _NULL_T) else self.validator,
+            convertor=convertor if not isinstance(convertor, _NULL_T) else self.convertor,
+        )
+
+
+def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
+    """Decorator for type checking keyword arguments.
+
+    Used to wrap a meson DSL implementation function, where it checks various
+    things about keyword arguments, including the type, and various other
+    information. For non-required values it sets the value to a default, which
+    means the value will always be provided.
+
+    If type tyhpe is a :class:ContainerTypeInfo, then the default value will be
+    passed as an argument to the container initializer, making a shallow copy
+
+    :param name: the name of the function, including the object it's attached to
+        (if applicable)
+    :param *types: KwargInfo entries for each keyword argument.
+    """
+    def inner(f: TV_func) -> TV_func:
+
+        def types_description(types_tuple: T.Tuple[T.Union[T.Type, ContainerTypeInfo], ...]) -> str:
+            candidates = []
+            for t in types_tuple:
+                if isinstance(t, ContainerTypeInfo):
+                    candidates.append(t.description())
+                else:
+                    candidates.append(t.__name__)
+            shouldbe = 'one of: ' if len(candidates) > 1 else ''
+            shouldbe += ', '.join(candidates)
+            return shouldbe
+
+        def raw_description(t: object) -> str:
+            """describe a raw type (ie, one that is not a ContainerTypeInfo)."""
+            if isinstance(t, list):
+                if t:
+                    return f"array[{' | '.join(sorted(mesonlib.OrderedSet(type(v).__name__ for v in t)))}]"
+                return 'array[]'
+            elif isinstance(t, dict):
+                if t:
+                    return f"dict[{' | '.join(sorted(mesonlib.OrderedSet(type(v).__name__ for v in t.values())))}]"
+                return 'dict[]'
+            return type(t).__name__
+
+        def check_value_type(types_tuple: T.Tuple[T.Union[T.Type, ContainerTypeInfo], ...],
+                             value: T.Any) -> bool:
+            for t in types_tuple:
+                if isinstance(t, ContainerTypeInfo):
+                    if t.check(value):
+                        return True
+                elif isinstance(value, t):
+                    return True
+            return False
+
+        @wraps(f)
+        def wrapper(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+
+            def emit_feature_change(values: T.Dict[str, T.Union[str, T.Tuple[str, str]]], feature: T.Union[T.Type['FeatureDeprecated'], T.Type['FeatureNew']]) -> None:
+                for n, version in values.items():
+                    if isinstance(value, (dict, list)):
+                        warn = n in value
+                    else:
+                        warn = n == value
+
+                    if warn:
+                        if isinstance(version, tuple):
+                            version, msg = version
+                        else:
+                            msg = None
+                        feature.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject, msg, location=node)
+
+            node, _, _kwargs, subproject = get_callee_args(wrapped_args)
+            # Cast here, as the convertor function may place something other than a TYPE_var in the kwargs
+            kwargs = T.cast(T.Dict[str, object], _kwargs)
+
+            all_names = {t.name for t in types}
+            unknowns = set(kwargs).difference(all_names)
+            if unknowns:
+                ustr = ', '.join([f'"{u}"' for u in sorted(unknowns)])
+                raise InvalidArguments(f'{name} got unknown keyword arguments {ustr}')
+
+            for info in types:
+                types_tuple = info.types if isinstance(info.types, tuple) else (info.types,)
+                value = kwargs.get(info.name)
+                if value is not None:
+                    if info.since:
+                        feature_name = info.name + ' arg in ' + name
+                        FeatureNew.single_use(feature_name, info.since, subproject, info.since_message, location=node)
+                    if info.deprecated:
+                        feature_name = info.name + ' arg in ' + name
+                        FeatureDeprecated.single_use(feature_name, info.deprecated, subproject, info.deprecated_message, location=node)
+                    if info.listify:
+                        kwargs[info.name] = value = mesonlib.listify(value)
+                    if not check_value_type(types_tuple, value):
+                        shouldbe = types_description(types_tuple)
+                        raise InvalidArguments(f'{name} keyword argument {info.name!r} was of type {raw_description(value)} but should have been {shouldbe}')
+
+                    if info.validator is not None:
+                        msg = info.validator(value)
+                        if msg is not None:
+                            raise InvalidArguments(f'{name} keyword argument "{info.name}" {msg}')
+
+                    if info.deprecated_values is not None:
+                        emit_feature_change(info.deprecated_values, FeatureDeprecated)
+
+                    if info.since_values is not None:
+                        emit_feature_change(info.since_values, FeatureNew)
+
+                elif info.required:
+                    raise InvalidArguments(f'{name} is missing required keyword argument "{info.name}"')
+                else:
+                    # set the value to the default, this ensuring all kwargs are present
+                    # This both simplifies the typing checking and the usage
+                    assert check_value_type(types_tuple, info.default), f'In funcion {name} default value of {info.name} is not a valid type, got {type(info.default)} expected {types_description(types_tuple)}'
+                    # Create a shallow copy of the container. This allows mutable
+                    # types to be used safely as default values
+                    kwargs[info.name] = copy.copy(info.default)
+                    if info.not_set_warning:
+                        mlog.warning(info.not_set_warning)
+
+                if info.convertor:
+                    kwargs[info.name] = info.convertor(kwargs[info.name])
+
+            return f(*wrapped_args, **wrapped_kwargs)
+        return T.cast(TV_func, wrapper)
+    return inner
+
+
+class FeatureCheckBase(metaclass=abc.ABCMeta):
+    "Base class for feature version checks"
+
+    feature_registry: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[T.Tuple[str, T.Optional['mparser.BaseNode']]]]]]
+    emit_notice = False
+
+    def __init__(self, feature_name: str, feature_version: str, extra_message: str = '', location: T.Optional['mparser.BaseNode'] = None):
+        self.feature_name = feature_name  # type: str
+        self.feature_version = feature_version    # type: str
+        self.extra_message = extra_message  # type: str
+        self.location = location
+
+    @staticmethod
+    def get_target_version(subproject: str) -> str:
+        # Don't do any checks if project() has not been parsed yet
+        if subproject not in mesonlib.project_meson_versions:
+            return ''
+        return mesonlib.project_meson_versions[subproject]
+
+    @staticmethod
+    @abc.abstractmethod
+    def check_version(target_version: str, feature_version: str) -> bool:
+        pass
+
+    def use(self, subproject: str) -> None:
+        tv = self.get_target_version(subproject)
+        # No target version
+        if tv == '':
+            return
+        # Target version is new enough, don't warn
+        if self.check_version(tv, self.feature_version) and not self.emit_notice:
+            return
+        # Feature is too new for target version or we want to emit notices, register it
+        if subproject not in self.feature_registry:
+            self.feature_registry[subproject] = {self.feature_version: set()}
+        register = self.feature_registry[subproject]
+        if self.feature_version not in register:
+            register[self.feature_version] = set()
+
+        feature_key = (self.feature_name, self.location)
+        if feature_key in register[self.feature_version]:
+            # Don't warn about the same feature multiple times
+            # FIXME: This is needed to prevent duplicate warnings, but also
+            # means we won't warn about a feature used in multiple places.
+            return
+        register[self.feature_version].add(feature_key)
+        # Target version is new enough, don't warn even if it is registered for notice
+        if self.check_version(tv, self.feature_version):
+            return
+        self.log_usage_warning(tv)
+
+    @classmethod
+    def report(cls, subproject: str) -> None:
+        if subproject not in cls.feature_registry:
+            return
+        warning_str = cls.get_warning_str_prefix(cls.get_target_version(subproject))
+        notice_str = cls.get_notice_str_prefix(cls.get_target_version(subproject))
+        fv = cls.feature_registry[subproject]
+        tv = cls.get_target_version(subproject)
+        for version in sorted(fv.keys()):
+            if cls.check_version(tv, version):
+                notice_str += '\n * {}: {}'.format(version, {i[0] for i in fv[version]})
+            else:
+                warning_str += '\n * {}: {}'.format(version, {i[0] for i in fv[version]})
+        if '\n' in notice_str:
+            mlog.notice(notice_str, fatal=False)
+        if '\n' in warning_str:
+            mlog.warning(warning_str)
+
+    def log_usage_warning(self, tv: str) -> None:
+        raise InterpreterException('log_usage_warning not implemented')
+
+    @staticmethod
+    def get_warning_str_prefix(tv: str) -> str:
+        raise InterpreterException('get_warning_str_prefix not implemented')
+
+    @staticmethod
+    def get_notice_str_prefix(tv: str) -> str:
+        raise InterpreterException('get_notice_str_prefix not implemented')
+
+    def __call__(self, f: TV_func) -> TV_func:
+        @wraps(f)
+        def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+            node, _, _, subproject = get_callee_args(wrapped_args)
+            if subproject is None:
+                raise AssertionError(f'{wrapped_args!r}')
+            self.location = node
+            self.use(subproject)
+            return f(*wrapped_args, **wrapped_kwargs)
+        return T.cast(TV_func, wrapped)
+
+    @classmethod
+    def single_use(cls, feature_name: str, version: str, subproject: str,
+                   extra_message: str = '', location: T.Optional['mparser.BaseNode'] = None) -> None:
+        """Oneline version that instantiates and calls use()."""
+        cls(feature_name, version, extra_message, location).use(subproject)
+
+
+class FeatureNew(FeatureCheckBase):
+    """Checks for new features"""
+
+    # Class variable, shared across all instances
+    #
+    # Format: {subproject: {feature_version: set(feature_names)}}
+    feature_registry = {}  # type: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[T.Tuple[str, T.Optional[mparser.BaseNode]]]]]]
+
+    @staticmethod
+    def check_version(target_version: str, feature_version: str) -> bool:
+        return mesonlib.version_compare_condition_with_min(target_version, feature_version)
+
+    @staticmethod
+    def get_warning_str_prefix(tv: str) -> str:
+        return f'Project specifies a minimum meson_version \'{tv}\' but uses features which were added in newer versions:'
+
+    @staticmethod
+    def get_notice_str_prefix(tv: str) -> str:
+        return ''
+
+    def log_usage_warning(self, tv: str) -> None:
+        args = [
+            'Project targeting', f"'{tv}'",
+            'but tried to use feature introduced in',
+            f"'{self.feature_version}':",
+            f'{self.feature_name}.',
+        ]
+        if self.extra_message:
+            args.append(self.extra_message)
+        mlog.warning(*args, location=self.location)
+
+class FeatureDeprecated(FeatureCheckBase):
+    """Checks for deprecated features"""
+
+    # Class variable, shared across all instances
+    #
+    # Format: {subproject: {feature_version: set(feature_names)}}
+    feature_registry = {}  # type: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[T.Tuple[str, T.Optional[mparser.BaseNode]]]]]]
+    emit_notice = True
+
+    @staticmethod
+    def check_version(target_version: str, feature_version: str) -> bool:
+        # For deprecation checks we need to return the inverse of FeatureNew checks
+        return not mesonlib.version_compare_condition_with_min(target_version, feature_version)
+
+    @staticmethod
+    def get_warning_str_prefix(tv: str) -> str:
+        return 'Deprecated features used:'
+
+    @staticmethod
+    def get_notice_str_prefix(tv: str) -> str:
+        return 'Future-deprecated features used:'
+
+    def log_usage_warning(self, tv: str) -> None:
+        args = [
+            'Project targeting', f"'{tv}'",
+            'but tried to use feature deprecated since',
+            f"'{self.feature_version}':",
+            f'{self.feature_name}.',
+        ]
+        if self.extra_message:
+            args.append(self.extra_message)
+        mlog.warning(*args, location=self.location)
+
+
+class FeatureCheckKwargsBase(metaclass=abc.ABCMeta):
+
+    @property
+    @abc.abstractmethod
+    def feature_check_class(self) -> T.Type[FeatureCheckBase]:
+        pass
+
+    def __init__(self, feature_name: str, feature_version: str,
+                 kwargs: T.List[str], extra_message: T.Optional[str] = None, location: T.Optional['mparser.BaseNode'] = None):
+        self.feature_name = feature_name
+        self.feature_version = feature_version
+        self.kwargs = kwargs
+        self.extra_message = extra_message
+        self.location = location
+
+    def __call__(self, f: TV_func) -> TV_func:
+        @wraps(f)
+        def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
+            node, _, kwargs, subproject = get_callee_args(wrapped_args)
+            if subproject is None:
+                raise AssertionError(f'{wrapped_args!r}')
+            for arg in self.kwargs:
+                if arg not in kwargs:
+                    continue
+                name = arg + ' arg in ' + self.feature_name
+                self.feature_check_class.single_use(
+                        name, self.feature_version, subproject, self.extra_message, node)
+            return f(*wrapped_args, **wrapped_kwargs)
+        return T.cast(TV_func, wrapped)
+
+class FeatureNewKwargs(FeatureCheckKwargsBase):
+    feature_check_class = FeatureNew
+
+class FeatureDeprecatedKwargs(FeatureCheckKwargsBase):
+    feature_check_class = FeatureDeprecated
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/disabler.py meson-0.61.2/mesonbuild/interpreterbase/disabler.py
--- meson-0.53.2/mesonbuild/interpreterbase/disabler.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/disabler.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,40 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .baseobjects import MesonInterpreterObject, TYPE_var, TYPE_kwargs
+import typing as T
+
+class Disabler(MesonInterpreterObject):
+    def method_call(self, method_name: str, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> TYPE_var:
+        if method_name == 'found':
+            return False
+        return Disabler()
+
+def _is_arg_disabled(arg: T.Any) -> bool:
+    if isinstance(arg, Disabler):
+        return True
+    if isinstance(arg, list):
+        for i in arg:
+            if _is_arg_disabled(i):
+                return True
+    return False
+
+def is_disabled(args: T.Sequence[T.Any], kwargs: T.Dict[str, T.Any]) -> bool:
+    for i in args:
+        if _is_arg_disabled(i):
+            return True
+    for i in kwargs.values():
+        if _is_arg_disabled(i):
+            return True
+    return False
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/exceptions.py meson-0.61.2/mesonbuild/interpreterbase/exceptions.py
--- meson-0.53.2/mesonbuild/interpreterbase/exceptions.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/exceptions.py	2021-08-18 11:22:15.000000000 +0000
@@ -0,0 +1,33 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ..mesonlib import MesonException
+
+class InterpreterException(MesonException):
+    pass
+
+class InvalidCode(InterpreterException):
+    pass
+
+class InvalidArguments(InterpreterException):
+    pass
+
+class SubdirDoneRequest(BaseException):
+    pass
+
+class ContinueRequest(BaseException):
+    pass
+
+class BreakRequest(BaseException):
+    pass
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/helpers.py meson-0.61.2/mesonbuild/interpreterbase/helpers.py
--- meson-0.53.2/mesonbuild/interpreterbase/helpers.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/helpers.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,55 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .. import mesonlib, mparser
+from .exceptions import InterpreterException
+
+import collections.abc
+import typing as T
+
+if T.TYPE_CHECKING:
+    from .baseobjects import TYPE_var, TYPE_kwargs
+
+def flatten(args: T.Union['TYPE_var', T.List['TYPE_var']]) -> T.List['TYPE_var']:
+    if isinstance(args, mparser.StringNode):
+        assert isinstance(args.value, str)
+        return [args.value]
+    if not isinstance(args, collections.abc.Sequence):
+        return [args]
+    result: T.List['TYPE_var'] = []
+    for a in args:
+        if isinstance(a, list):
+            rest = flatten(a)
+            result = result + rest
+        elif isinstance(a, mparser.StringNode):
+            result.append(a.value)
+        else:
+            result.append(a)
+    return result
+
+def resolve_second_level_holders(args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.Tuple[T.List['TYPE_var'], 'TYPE_kwargs']:
+    def resolver(arg: 'TYPE_var') -> 'TYPE_var':
+        if isinstance(arg, list):
+            return [resolver(x) for x in arg]
+        if isinstance(arg, dict):
+            return {k: resolver(v) for k, v in arg.items()}
+        if isinstance(arg, mesonlib.SecondLevelHolder):
+            return arg.get_default_object()
+        return arg
+    return [resolver(x) for x in args], {k: resolver(v) for k, v in kwargs.items()}
+
+def default_resolve_key(key: mparser.BaseNode) -> str:
+    if not isinstance(key, mparser.IdNode):
+        raise InterpreterException('Invalid kwargs format.')
+    return key.value
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/__init__.py meson-0.61.2/mesonbuild/interpreterbase/__init__.py
--- meson-0.53.2/mesonbuild/interpreterbase/__init__.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/__init__.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,131 @@
+# Copyright 2013-2021 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.
+
+__all__ = [
+    'InterpreterObject',
+    'MesonInterpreterObject',
+    'ObjectHolder',
+    'IterableObject',
+    'MutableInterpreterObject',
+
+    'MesonOperator',
+
+    'Disabler',
+    'is_disabled',
+
+    'InterpreterException',
+    'InvalidCode',
+    'InvalidArguments',
+    'SubdirDoneRequest',
+    'ContinueRequest',
+    'BreakRequest',
+
+    'default_resolve_key',
+    'flatten',
+    'resolve_second_level_holders',
+
+    'noPosargs',
+    'noKwargs',
+    'stringArgs',
+    'noArgsFlattening',
+    'noSecondLevelHolderResolving',
+    'unholder_return',
+    'disablerIfNotFound',
+    'permittedKwargs',
+    'typed_operator',
+    'unary_operator',
+    'typed_pos_args',
+    'ContainerTypeInfo',
+    'KwargInfo',
+    'typed_kwargs',
+    'FeatureCheckBase',
+    'FeatureNew',
+    'FeatureDeprecated',
+    'FeatureNewKwargs',
+    'FeatureDeprecatedKwargs',
+
+    'InterpreterBase',
+
+    'TV_fw_var',
+    'TV_fw_args',
+    'TV_fw_kwargs',
+    'TV_func',
+    'TYPE_elementary',
+    'TYPE_var',
+    'TYPE_nvar',
+    'TYPE_kwargs',
+    'TYPE_nkwargs',
+    'TYPE_key_resolver',
+    'TYPE_HoldableTypes',
+
+    'HoldableTypes',
+]
+
+from .baseobjects import (
+    InterpreterObject,
+    MesonInterpreterObject,
+    ObjectHolder,
+    IterableObject,
+    MutableInterpreterObject,
+
+    TV_fw_var,
+    TV_fw_args,
+    TV_fw_kwargs,
+    TV_func,
+    TYPE_elementary,
+    TYPE_var,
+    TYPE_nvar,
+    TYPE_kwargs,
+    TYPE_nkwargs,
+    TYPE_key_resolver,
+    TYPE_HoldableTypes,
+
+    HoldableTypes,
+)
+
+from .decorators import (
+    noPosargs,
+    noKwargs,
+    stringArgs,
+    noArgsFlattening,
+    noSecondLevelHolderResolving,
+    unholder_return,
+    disablerIfNotFound,
+    permittedKwargs,
+    typed_pos_args,
+    ContainerTypeInfo,
+    KwargInfo,
+    typed_operator,
+    unary_operator,
+    typed_kwargs,
+    FeatureCheckBase,
+    FeatureNew,
+    FeatureDeprecated,
+    FeatureNewKwargs,
+    FeatureDeprecatedKwargs,
+)
+
+from .exceptions import (
+    InterpreterException,
+    InvalidCode,
+    InvalidArguments,
+    SubdirDoneRequest,
+    ContinueRequest,
+    BreakRequest,
+)
+
+from .disabler import Disabler, is_disabled
+from .helpers import default_resolve_key, flatten, resolve_second_level_holders
+from .interpreterbase import InterpreterBase
+from .operator import MesonOperator
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/interpreterbase.py meson-0.61.2/mesonbuild/interpreterbase/interpreterbase.py
--- meson-0.53.2/mesonbuild/interpreterbase/interpreterbase.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/interpreterbase.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,598 @@
+# Copyright 2016-2017 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 class contains the basic functionality needed to run any interpreter
+# or an interpreter-based tool.
+
+from .. import mparser, mesonlib
+from .. import environment
+
+from .baseobjects import (
+    InterpreterObject,
+    MesonInterpreterObject,
+    MutableInterpreterObject,
+    InterpreterObjectTypeVar,
+    ObjectHolder,
+    IterableObject,
+
+    TYPE_var,
+    TYPE_kwargs,
+
+    HoldableTypes,
+)
+
+from .exceptions import (
+    InterpreterException,
+    InvalidCode,
+    InvalidArguments,
+    SubdirDoneRequest,
+    ContinueRequest,
+    BreakRequest
+)
+
+from .decorators import FeatureNew
+from .disabler import Disabler, is_disabled
+from .helpers import default_resolve_key, flatten, resolve_second_level_holders
+from .operator import MesonOperator
+from ._unholder import _unholder
+
+import os, copy, re, pathlib
+import typing as T
+import textwrap
+
+if T.TYPE_CHECKING:
+    from ..interpreter import Interpreter
+
+HolderMapType = T.Dict[
+    T.Union[
+        T.Type[mesonlib.HoldableObject],
+        T.Type[int],
+        T.Type[bool],
+        T.Type[str],
+        T.Type[list],
+        T.Type[dict],
+    ],
+    # For some reason, this has to be a callable and can't just be ObjectHolder[InterpreterObjectTypeVar]
+    T.Callable[[InterpreterObjectTypeVar, 'Interpreter'], ObjectHolder[InterpreterObjectTypeVar]]
+]
+
+FunctionType = T.Dict[
+    str,
+    T.Callable[[mparser.BaseNode, T.List[TYPE_var], T.Dict[str, TYPE_var]], TYPE_var]
+]
+
+class InterpreterBase:
+    def __init__(self, source_root: str, subdir: str, subproject: str):
+        self.source_root = source_root
+        self.funcs: FunctionType = {}
+        self.builtin: T.Dict[str, InterpreterObject] = {}
+        # Holder maps store a mapping from an HoldableObject to a class ObjectHolder
+        self.holder_map: HolderMapType = {}
+        self.bound_holder_map: HolderMapType = {}
+        self.subdir = subdir
+        self.root_subdir = subdir
+        self.subproject = subproject
+        self.variables: T.Dict[str, InterpreterObject] = {}
+        self.argument_depth = 0
+        self.current_lineno = -1
+        # Current node set during a function call. This can be used as location
+        # when printing a warning message during a method call.
+        self.current_node = None  # type: mparser.BaseNode
+        # This is set to `version_string` when this statement is evaluated:
+        # meson.version().compare_version(version_string)
+        # If it was part of a if-clause, it is used to temporally override the
+        # current meson version target within that if-block.
+        self.tmp_meson_version = None # type: T.Optional[str]
+
+    def load_root_meson_file(self) -> None:
+        mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename)
+        if not os.path.isfile(mesonfile):
+            raise InvalidArguments(f'Missing Meson file in {mesonfile}')
+        with open(mesonfile, encoding='utf-8') as mf:
+            code = mf.read()
+        if code.isspace():
+            raise InvalidCode('Builder file is empty.')
+        assert isinstance(code, str)
+        try:
+            self.ast = mparser.Parser(code, mesonfile).parse()
+        except mesonlib.MesonException as me:
+            me.file = mesonfile
+            raise me
+
+    def parse_project(self) -> None:
+        """
+        Parses project() and initializes languages, compilers etc. Do this
+        early because we need this before we parse the rest of the AST.
+        """
+        self.evaluate_codeblock(self.ast, end=1)
+
+    def sanity_check_ast(self) -> None:
+        if not isinstance(self.ast, mparser.CodeBlockNode):
+            raise InvalidCode('AST is of invalid type. Possibly a bug in the parser.')
+        if not self.ast.lines:
+            raise InvalidCode('No statements in code.')
+        first = self.ast.lines[0]
+        if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project':
+            p = pathlib.Path(self.source_root).resolve()
+            found = p
+            for parent in p.parents:
+                if (parent / 'meson.build').is_file():
+                    with open(parent / 'meson.build', encoding='utf-8') as f:
+                        if f.readline().startswith('project('):
+                            found = parent
+                            break
+                else:
+                    break
+
+            error = 'first statement must be a call to project()'
+            if found != p:
+                raise InvalidCode(f'Not the project root: {error}\n\nDid you mean to run meson from the directory: "{found}"?')
+            else:
+                raise InvalidCode(f'Invalid source tree: {error}')
+
+    def run(self) -> None:
+        # Evaluate everything after the first line, which is project() because
+        # we already parsed that in self.parse_project()
+        try:
+            self.evaluate_codeblock(self.ast, start=1)
+        except SubdirDoneRequest:
+            pass
+
+    def evaluate_codeblock(self, node: mparser.CodeBlockNode, start: int = 0, end: T.Optional[int] = None) -> None:
+        if node is None:
+            return
+        if not isinstance(node, mparser.CodeBlockNode):
+            e = InvalidCode('Tried to execute a non-codeblock. Possibly a bug in the parser.')
+            e.lineno = node.lineno
+            e.colno = node.colno
+            raise e
+        statements = node.lines[start:end]
+        i = 0
+        while i < len(statements):
+            cur = statements[i]
+            try:
+                self.current_lineno = cur.lineno
+                self.evaluate_statement(cur)
+            except Exception as e:
+                if getattr(e, 'lineno', None) is None:
+                    # We are doing the equivalent to setattr here and mypy does not like it
+                    e.lineno = cur.lineno                                                             # type: ignore
+                    e.colno = cur.colno                                                               # type: ignore
+                    e.file = os.path.join(self.source_root, self.subdir, environment.build_filename)  # type: ignore
+                raise e
+            i += 1 # In THE FUTURE jump over blocks and stuff.
+
+    def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[InterpreterObject]:
+        self.current_node = cur
+        if isinstance(cur, mparser.FunctionNode):
+            return self.function_call(cur)
+        elif isinstance(cur, mparser.AssignmentNode):
+            self.assignment(cur)
+        elif isinstance(cur, mparser.MethodNode):
+            return self.method_call(cur)
+        elif isinstance(cur, mparser.StringNode):
+            return self._holderify(cur.value)
+        elif isinstance(cur, mparser.BooleanNode):
+            return self._holderify(cur.value)
+        elif isinstance(cur, mparser.IfClauseNode):
+            return self.evaluate_if(cur)
+        elif isinstance(cur, mparser.IdNode):
+            return self.get_variable(cur.value)
+        elif isinstance(cur, mparser.ComparisonNode):
+            return self.evaluate_comparison(cur)
+        elif isinstance(cur, mparser.ArrayNode):
+            return self.evaluate_arraystatement(cur)
+        elif isinstance(cur, mparser.DictNode):
+            return self.evaluate_dictstatement(cur)
+        elif isinstance(cur, mparser.NumberNode):
+            return self._holderify(cur.value)
+        elif isinstance(cur, mparser.AndNode):
+            return self.evaluate_andstatement(cur)
+        elif isinstance(cur, mparser.OrNode):
+            return self.evaluate_orstatement(cur)
+        elif isinstance(cur, mparser.NotNode):
+            return self.evaluate_notstatement(cur)
+        elif isinstance(cur, mparser.UMinusNode):
+            return self.evaluate_uminusstatement(cur)
+        elif isinstance(cur, mparser.ArithmeticNode):
+            return self.evaluate_arithmeticstatement(cur)
+        elif isinstance(cur, mparser.ForeachClauseNode):
+            self.evaluate_foreach(cur)
+        elif isinstance(cur, mparser.PlusAssignmentNode):
+            self.evaluate_plusassign(cur)
+        elif isinstance(cur, mparser.IndexNode):
+            return self.evaluate_indexing(cur)
+        elif isinstance(cur, mparser.TernaryNode):
+            return self.evaluate_ternary(cur)
+        elif isinstance(cur, mparser.FormatStringNode):
+            return self.evaluate_fstring(cur)
+        elif isinstance(cur, mparser.ContinueNode):
+            raise ContinueRequest()
+        elif isinstance(cur, mparser.BreakNode):
+            raise BreakRequest()
+        else:
+            raise InvalidCode("Unknown statement.")
+        return None
+
+    def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> InterpreterObject:
+        (arguments, kwargs) = self.reduce_arguments(cur.args)
+        if len(kwargs) > 0:
+            raise InvalidCode('Keyword arguments are invalid in array construction.')
+        return self._holderify([_unholder(x) for x in arguments])
+
+    @FeatureNew('dict', '0.47.0')
+    def evaluate_dictstatement(self, cur: mparser.DictNode) -> InterpreterObject:
+        def resolve_key(key: mparser.BaseNode) -> str:
+            if not isinstance(key, mparser.StringNode):
+                FeatureNew.single_use('Dictionary entry using non literal key', '0.53.0', self.subproject)
+            str_key = _unholder(self.evaluate_statement(key))
+            if not isinstance(str_key, str):
+                raise InvalidArguments('Key must be a string')
+            return str_key
+        arguments, kwargs = self.reduce_arguments(cur.args, key_resolver=resolve_key, duplicate_key_error='Duplicate dictionary key: {}')
+        assert not arguments
+        return self._holderify({k: _unholder(v) for k, v in kwargs.items()})
+
+    def evaluate_notstatement(self, cur: mparser.NotNode) -> InterpreterObject:
+        v = self.evaluate_statement(cur.value)
+        if isinstance(v, Disabler):
+            return v
+        return self._holderify(v.operator_call(MesonOperator.NOT, None))
+
+    def evaluate_if(self, node: mparser.IfClauseNode) -> T.Optional[Disabler]:
+        assert isinstance(node, mparser.IfClauseNode)
+        for i in node.ifs:
+            # Reset self.tmp_meson_version to know if it gets set during this
+            # statement evaluation.
+            self.tmp_meson_version = None
+            result = self.evaluate_statement(i.condition)
+            if isinstance(result, Disabler):
+                return result
+            if not isinstance(result, InterpreterObject):
+                raise mesonlib.MesonBugException(f'Argument to not ({result}) is not an InterpreterObject but {type(result).__name__}.')
+            res = result.operator_call(MesonOperator.BOOL, None)
+            if not isinstance(res, bool):
+                raise InvalidCode(f'If clause {result!r} does not evaluate to true or false.')
+            if res:
+                prev_meson_version = mesonlib.project_meson_versions[self.subproject]
+                if self.tmp_meson_version:
+                    mesonlib.project_meson_versions[self.subproject] = self.tmp_meson_version
+                try:
+                    self.evaluate_codeblock(i.block)
+                finally:
+                    mesonlib.project_meson_versions[self.subproject] = prev_meson_version
+                return None
+        if not isinstance(node.elseblock, mparser.EmptyNode):
+            self.evaluate_codeblock(node.elseblock)
+        return None
+
+    def evaluate_comparison(self, node: mparser.ComparisonNode) -> InterpreterObject:
+        val1 = self.evaluate_statement(node.left)
+        if isinstance(val1, Disabler):
+            return val1
+        val2 = self.evaluate_statement(node.right)
+        if isinstance(val2, Disabler):
+            return val2
+
+        # New code based on InterpreterObjects
+        operator = {
+            'in': MesonOperator.IN,
+            'notin': MesonOperator.NOT_IN,
+            '==': MesonOperator.EQUALS,
+            '!=': MesonOperator.NOT_EQUALS,
+            '>': MesonOperator.GREATER,
+            '<': MesonOperator.LESS,
+            '>=': MesonOperator.GREATER_EQUALS,
+            '<=': MesonOperator.LESS_EQUALS,
+        }[node.ctype]
+
+        # Check if the arguments should be reversed for simplicity (this essentially converts `in` to `contains`)
+        if operator in (MesonOperator.IN, MesonOperator.NOT_IN):
+            val1, val2 = val2, val1
+
+        val1.current_node = node
+        return self._holderify(val1.operator_call(operator, _unholder(val2)))
+
+    def evaluate_andstatement(self, cur: mparser.AndNode) -> InterpreterObject:
+        l = self.evaluate_statement(cur.left)
+        if isinstance(l, Disabler):
+            return l
+        l_bool = l.operator_call(MesonOperator.BOOL, None)
+        if not l_bool:
+            return self._holderify(l_bool)
+        r = self.evaluate_statement(cur.right)
+        if isinstance(r, Disabler):
+            return r
+        return self._holderify(r.operator_call(MesonOperator.BOOL, None))
+
+    def evaluate_orstatement(self, cur: mparser.OrNode) -> InterpreterObject:
+        l = self.evaluate_statement(cur.left)
+        if isinstance(l, Disabler):
+            return l
+        l_bool = l.operator_call(MesonOperator.BOOL, None)
+        if l_bool:
+            return self._holderify(l_bool)
+        r = self.evaluate_statement(cur.right)
+        if isinstance(r, Disabler):
+            return r
+        return self._holderify(r.operator_call(MesonOperator.BOOL, None))
+
+    def evaluate_uminusstatement(self, cur: mparser.UMinusNode) -> InterpreterObject:
+        v = self.evaluate_statement(cur.value)
+        if isinstance(v, Disabler):
+            return v
+        v.current_node = cur
+        return self._holderify(v.operator_call(MesonOperator.UMINUS, None))
+
+    def evaluate_arithmeticstatement(self, cur: mparser.ArithmeticNode) -> InterpreterObject:
+        l = self.evaluate_statement(cur.left)
+        if isinstance(l, Disabler):
+            return l
+        r = self.evaluate_statement(cur.right)
+        if isinstance(r, Disabler):
+            return r
+
+        mapping: T.Dict[str, MesonOperator] = {
+            'add': MesonOperator.PLUS,
+            'sub': MesonOperator.MINUS,
+            'mul': MesonOperator.TIMES,
+            'div': MesonOperator.DIV,
+            'mod': MesonOperator.MOD,
+        }
+        l.current_node = cur
+        res = l.operator_call(mapping[cur.operation], _unholder(r))
+        return self._holderify(res)
+
+    def evaluate_ternary(self, node: mparser.TernaryNode) -> T.Optional[InterpreterObject]:
+        assert isinstance(node, mparser.TernaryNode)
+        result = self.evaluate_statement(node.condition)
+        if isinstance(result, Disabler):
+            return result
+        result.current_node = node
+        result_bool = result.operator_call(MesonOperator.BOOL, None)
+        if result_bool:
+            return self.evaluate_statement(node.trueblock)
+        else:
+            return self.evaluate_statement(node.falseblock)
+
+    @FeatureNew('format strings', '0.58.0')
+    def evaluate_fstring(self, node: mparser.FormatStringNode) -> InterpreterObject:
+        assert isinstance(node, mparser.FormatStringNode)
+
+        def replace(match: T.Match[str]) -> str:
+            var = str(match.group(1))
+            try:
+                val = _unholder(self.variables[var])
+                if not isinstance(val, (str, int, float, bool)):
+                    raise InvalidCode(f'Identifier "{var}" does not name a formattable variable ' +
+                        '(has to be an integer, a string, a floating point number or a boolean).')
+
+                return str(val)
+            except KeyError:
+                raise InvalidCode(f'Identifier "{var}" does not name a variable.')
+
+        res = re.sub(r'@([_a-zA-Z][_0-9a-zA-Z]*)@', replace, node.value)
+        return self._holderify(res)
+
+    def evaluate_foreach(self, node: mparser.ForeachClauseNode) -> None:
+        assert isinstance(node, mparser.ForeachClauseNode)
+        items = self.evaluate_statement(node.items)
+        if not isinstance(items, IterableObject):
+            raise InvalidArguments('Items of foreach loop do not support iterating')
+
+        tsize = items.iter_tuple_size()
+        if len(node.varnames) != (tsize or 1):
+            raise InvalidArguments(f'Foreach expects exactly {tsize or 1} variables for iterating over objects of type {items.display_name()}')
+
+        for i in items.iter_self():
+            if tsize is None:
+                if isinstance(i, tuple):
+                    raise mesonlib.MesonBugException(f'Iteration of {items} returned a tuple even though iter_tuple_size() is None')
+                self.set_variable(node.varnames[0], self._holderify(i))
+            else:
+                if not isinstance(i, tuple):
+                    raise mesonlib.MesonBugException(f'Iteration of {items} did not return a tuple even though iter_tuple_size() is {tsize}')
+                if len(i) != tsize:
+                    raise mesonlib.MesonBugException(f'Iteration of {items} did not return a tuple even though iter_tuple_size() is {tsize}')
+                for j in range(tsize):
+                    self.set_variable(node.varnames[j], self._holderify(i[j]))
+            try:
+                self.evaluate_codeblock(node.block)
+            except ContinueRequest:
+                continue
+            except BreakRequest:
+                break
+
+    def evaluate_plusassign(self, node: mparser.PlusAssignmentNode) -> None:
+        assert isinstance(node, mparser.PlusAssignmentNode)
+        varname = node.var_name
+        addition = self.evaluate_statement(node.value)
+
+        # Remember that all variables are immutable. We must always create a
+        # full new variable and then assign it.
+        old_variable = self.get_variable(varname)
+        old_variable.current_node = node
+        new_value = self._holderify(old_variable.operator_call(MesonOperator.PLUS, _unholder(addition)))
+        self.set_variable(varname, new_value)
+
+    def evaluate_indexing(self, node: mparser.IndexNode) -> InterpreterObject:
+        assert isinstance(node, mparser.IndexNode)
+        iobject = self.evaluate_statement(node.iobject)
+        if isinstance(iobject, Disabler):
+            return iobject
+        index = _unholder(self.evaluate_statement(node.index))
+
+        if iobject is None:
+            raise InterpreterException('Tried to evaluate indexing on None')
+        iobject.current_node = node
+        return self._holderify(iobject.operator_call(MesonOperator.INDEX, index))
+
+    def function_call(self, node: mparser.FunctionNode) -> T.Optional[InterpreterObject]:
+        func_name = node.func_name
+        (h_posargs, h_kwargs) = self.reduce_arguments(node.args)
+        (posargs, kwargs) = self._unholder_args(h_posargs, h_kwargs)
+        if is_disabled(posargs, kwargs) and func_name not in {'get_variable', 'set_variable', 'unset_variable', 'is_disabler'}:
+            return Disabler()
+        if func_name in self.funcs:
+            func = self.funcs[func_name]
+            func_args = posargs
+            if not getattr(func, 'no-args-flattening', False):
+                func_args = flatten(posargs)
+            if not getattr(func, 'no-second-level-holder-flattening', False):
+                func_args, kwargs = resolve_second_level_holders(func_args, kwargs)
+            res = func(node, func_args, kwargs)
+            return self._holderify(res) if res is not None else None
+        else:
+            self.unknown_function_called(func_name)
+            return None
+
+    def method_call(self, node: mparser.MethodNode) -> T.Optional[InterpreterObject]:
+        invokable = node.source_object
+        obj: T.Optional[InterpreterObject]
+        if isinstance(invokable, mparser.IdNode):
+            object_name = invokable.value
+            obj = self.get_variable(object_name)
+        else:
+            obj = self.evaluate_statement(invokable)
+        method_name = node.name
+        (h_args, h_kwargs) = self.reduce_arguments(node.args)
+        (args, kwargs) = self._unholder_args(h_args, h_kwargs)
+        if is_disabled(args, kwargs):
+            return Disabler()
+        if not isinstance(obj, InterpreterObject):
+            raise InvalidArguments(f'Variable "{object_name}" is not callable.')
+        # TODO: InterpreterBase **really** shouldn't be in charge of checking this
+        if method_name == 'extract_objects':
+            if isinstance(obj, ObjectHolder):
+                self.validate_extraction(obj.held_object)
+            elif not isinstance(obj, Disabler):
+                raise InvalidArguments(f'Invalid operation "extract_objects" on variable "{object_name}" of type {type(obj).__name__}')
+        obj.current_node = node
+        res = obj.method_call(method_name, args, kwargs)
+        return self._holderify(res) if res is not None else None
+
+    def _holderify(self, res: T.Union[TYPE_var, InterpreterObject]) -> InterpreterObject:
+        if isinstance(res, HoldableTypes):
+            # Always check for an exact match first.
+            cls = self.holder_map.get(type(res), None)
+            if cls is not None:
+                # Casts to Interpreter are required here since an assertion would
+                # not work for the `ast` module.
+                return cls(res, T.cast('Interpreter', self))
+            # Try the boundary types next.
+            for typ, cls in self.bound_holder_map.items():
+                if isinstance(res, typ):
+                    return cls(res, T.cast('Interpreter', self))
+            raise mesonlib.MesonBugException(f'Object {res} of type {type(res).__name__} is neither in self.holder_map nor self.bound_holder_map.')
+        elif isinstance(res, ObjectHolder):
+            raise mesonlib.MesonBugException(f'Returned object {res} of type {type(res).__name__} is an object holder.')
+        elif isinstance(res, MesonInterpreterObject):
+            return res
+        raise mesonlib.MesonBugException(f'Unknown returned object {res} of type {type(res).__name__} in the parameters.')
+
+    def _unholder_args(self,
+                       args: T.List[InterpreterObject],
+                       kwargs: T.Dict[str, InterpreterObject]) -> T.Tuple[T.List[TYPE_var], TYPE_kwargs]:
+        return [_unholder(x) for x in args], {k: _unholder(v) for k, v in kwargs.items()}
+
+    def unknown_function_called(self, func_name: str) -> None:
+        raise InvalidCode(f'Unknown function "{func_name}".')
+
+    def reduce_arguments(
+                self,
+                args: mparser.ArgumentNode,
+                key_resolver: T.Callable[[mparser.BaseNode], str] = default_resolve_key,
+                duplicate_key_error: T.Optional[str] = None,
+            ) -> T.Tuple[
+                T.List[InterpreterObject],
+                T.Dict[str, InterpreterObject]
+            ]:
+        assert isinstance(args, mparser.ArgumentNode)
+        if args.incorrect_order():
+            raise InvalidArguments('All keyword arguments must be after positional arguments.')
+        self.argument_depth += 1
+        reduced_pos = [self.evaluate_statement(arg) for arg in args.arguments]
+        if any(x is None for x in reduced_pos):
+            raise InvalidArguments(f'At least one value in the arguments is void.')
+        reduced_kw: T.Dict[str, InterpreterObject] = {}
+        for key, val in args.kwargs.items():
+            reduced_key = key_resolver(key)
+            assert isinstance(val, mparser.BaseNode)
+            reduced_val = self.evaluate_statement(val)
+            if reduced_val is None:
+                raise InvalidArguments(f'Value of key {reduced_key} is void.')
+            if duplicate_key_error and reduced_key in reduced_kw:
+                raise InvalidArguments(duplicate_key_error.format(reduced_key))
+            reduced_kw[reduced_key] = reduced_val
+        self.argument_depth -= 1
+        final_kw = self.expand_default_kwargs(reduced_kw)
+        return reduced_pos, final_kw
+
+    def expand_default_kwargs(self, kwargs: T.Dict[str, T.Optional[InterpreterObject]]) -> T.Dict[str, T.Optional[InterpreterObject]]:
+        if 'kwargs' not in kwargs:
+            return kwargs
+        to_expand = _unholder(kwargs.pop('kwargs'))
+        if not isinstance(to_expand, dict):
+            raise InterpreterException('Value of "kwargs" must be dictionary.')
+        if 'kwargs' in to_expand:
+            raise InterpreterException('Kwargs argument must not contain a "kwargs" entry. Points for thinking meta, though. :P')
+        for k, v in to_expand.items():
+            if k in kwargs:
+                raise InterpreterException(f'Entry "{k}" defined both as a keyword argument and in a "kwarg" entry.')
+            kwargs[k] = self._holderify(v)
+        return kwargs
+
+    def assignment(self, node: mparser.AssignmentNode) -> None:
+        assert isinstance(node, mparser.AssignmentNode)
+        if self.argument_depth != 0:
+            raise InvalidArguments(textwrap.dedent('''\
+                Tried to assign values inside an argument list.
+                To specify a keyword argument, use : instead of =.
+            '''))
+        var_name = node.var_name
+        if not isinstance(var_name, str):
+            raise InvalidArguments('Tried to assign value to a non-variable.')
+        value = self.evaluate_statement(node.value)
+        # For mutable objects we need to make a copy on assignment
+        if isinstance(value, MutableInterpreterObject):
+            value = copy.deepcopy(value)
+        self.set_variable(var_name, value)
+        return None
+
+    def set_variable(self, varname: str, variable: T.Union[TYPE_var, InterpreterObject], *, holderify: bool = False) -> None:
+        if variable is None:
+            raise InvalidCode('Can not assign None to variable.')
+        if holderify:
+            variable = self._holderify(variable)
+        else:
+            # Ensure that we are always storing ObjectHolders
+            if not isinstance(variable, InterpreterObject):
+                raise mesonlib.MesonBugException(f'set_variable in InterpreterBase called with a non InterpreterObject {variable} of type {type(variable).__name__}')
+        if not isinstance(varname, str):
+            raise InvalidCode('First argument to set_variable must be a string.')
+        if re.match('[_a-zA-Z][_0-9a-zA-Z]*$', varname) is None:
+            raise InvalidCode('Invalid variable name: ' + varname)
+        if varname in self.builtin:
+            raise InvalidCode(f'Tried to overwrite internal variable "{varname}"')
+        self.variables[varname] = variable
+
+    def get_variable(self, varname: str) -> InterpreterObject:
+        if varname in self.builtin:
+            return self.builtin[varname]
+        if varname in self.variables:
+            return self.variables[varname]
+        raise InvalidCode(f'Unknown variable "{varname}".')
+
+    def validate_extraction(self, buildtarget: mesonlib.HoldableObject) -> None:
+        raise InterpreterException('validate_extraction is not implemented in this context (please file a bug)')
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/operator.py meson-0.61.2/mesonbuild/interpreterbase/operator.py
--- meson-0.53.2/mesonbuild/interpreterbase/operator.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/operator.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,32 @@
+# SPDX-license-identifier: Apache-2.0
+
+from enum import Enum
+
+class MesonOperator(Enum):
+    # Arithmetic
+    PLUS = '+'
+    MINUS = '-'
+    TIMES = '*'
+    DIV = '/'
+    MOD = '%'
+
+    UMINUS = 'uminus'
+
+    # Logic
+    NOT = 'not'
+
+    # Should return the boolsche interpretation of the value (`'' == false` for instance)
+    BOOL = 'bool()'
+
+    # Comparison
+    EQUALS = '=='
+    NOT_EQUALS = '!='
+    GREATER = '>'
+    LESS = '<'
+    GREATER_EQUALS = '>='
+    LESS_EQUALS = '<='
+
+    # Container
+    IN = 'in'
+    NOT_IN = 'not in'
+    INDEX = '[]'
diff -Nru meson-0.53.2/mesonbuild/interpreterbase/_unholder.py meson-0.61.2/mesonbuild/interpreterbase/_unholder.py
--- meson-0.53.2/mesonbuild/interpreterbase/_unholder.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase/_unholder.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,29 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .baseobjects import InterpreterObject, MesonInterpreterObject, ObjectHolder, TYPE_var, HoldableTypes
+from .exceptions import InvalidArguments
+from ..mesonlib import HoldableObject, MesonBugException
+
+def _unholder(obj: InterpreterObject) -> TYPE_var:
+    if isinstance(obj, ObjectHolder):
+        assert isinstance(obj.held_object, HoldableTypes)
+        return obj.held_object
+    elif isinstance(obj, MesonInterpreterObject):
+        return obj
+    elif isinstance(obj, HoldableObject):
+        raise MesonBugException(f'Argument {obj} of type {type(obj).__name__} is not held by an ObjectHolder.')
+    elif isinstance(obj, InterpreterObject):
+        raise InvalidArguments(f'Argument {obj} of type {type(obj).__name__} cannot be passed to a method or function')
+    raise MesonBugException(f'Unknown object {obj} of type {type(obj).__name__} in the parameters.')
diff -Nru meson-0.53.2/mesonbuild/interpreterbase.py meson-0.61.2/mesonbuild/interpreterbase.py
--- meson-0.53.2/mesonbuild/interpreterbase.py	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreterbase.py	1970-01-01 00:00:00.000000000 +0000
@@ -1,1098 +0,0 @@
-# Copyright 2016-2017 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 class contains the basic functionality needed to run any interpreter
-# or an interpreter-based tool.
-
-from . import mparser, mesonlib, mlog
-from . import environment, dependencies
-
-import os, copy, re
-from functools import wraps
-
-class ObjectHolder:
-    def __init__(self, obj, subproject=None):
-        self.held_object = obj
-        self.subproject = subproject
-
-    def __repr__(self):
-        return ''.format(self.held_object)
-
-# Decorators for method calls.
-
-def check_stringlist(a, msg='Arguments must be strings.'):
-    if not isinstance(a, list):
-        mlog.debug('Not a list:', str(a))
-        raise InvalidArguments('Argument not a list.')
-    if not all(isinstance(s, str) for s in a):
-        mlog.debug('Element not a string:', str(a))
-        raise InvalidArguments(msg)
-
-def _get_callee_args(wrapped_args, want_subproject=False):
-    s = wrapped_args[0]
-    n = len(wrapped_args)
-    # Raise an error if the codepaths are not there
-    subproject = None
-    if want_subproject and n == 2:
-        if hasattr(s, 'subproject'):
-            # Interpreter base types have 2 args: self, node
-            node = wrapped_args[1]
-            # args and kwargs are inside the node
-            args = None
-            kwargs = None
-            subproject = s.subproject
-        elif hasattr(wrapped_args[1], 'subproject'):
-            # Module objects have 2 args: self, interpreter
-            node = wrapped_args[1].current_node
-            # args and kwargs are inside the node
-            args = None
-            kwargs = None
-            subproject = wrapped_args[1].subproject
-        else:
-            raise AssertionError('Unknown args: {!r}'.format(wrapped_args))
-    elif n == 3:
-        # Methods on objects (*Holder, MesonMain, etc) have 3 args: self, args, kwargs
-        node = s.current_node
-        args = wrapped_args[1]
-        kwargs = wrapped_args[2]
-        if want_subproject:
-            if hasattr(s, 'subproject'):
-                subproject = s.subproject
-            elif hasattr(s, 'interpreter'):
-                subproject = s.interpreter.subproject
-    elif n == 4:
-        # Meson functions have 4 args: self, node, args, kwargs
-        # Module functions have 4 args: self, state, args, kwargs
-        if isinstance(s, InterpreterBase):
-            node = wrapped_args[1]
-        else:
-            node = wrapped_args[1].current_node
-        args = wrapped_args[2]
-        kwargs = wrapped_args[3]
-        if want_subproject:
-            if isinstance(s, InterpreterBase):
-                subproject = s.subproject
-            else:
-                subproject = wrapped_args[1].subproject
-    elif n == 5:
-        # Module snippets have 5 args: self, interpreter, state, args, kwargs
-        node = wrapped_args[2].current_node
-        args = wrapped_args[3]
-        kwargs = wrapped_args[4]
-        if want_subproject:
-            subproject = wrapped_args[2].subproject
-    else:
-        raise AssertionError('Unknown args: {!r}'.format(wrapped_args))
-    # Sometimes interpreter methods are called internally with None instead of
-    # empty list/dict
-    args = args if args is not None else []
-    kwargs = kwargs if kwargs is not None else {}
-    return s, node, args, kwargs, subproject
-
-def flatten(args):
-    if isinstance(args, mparser.StringNode):
-        return args.value
-    if isinstance(args, (int, str, mesonlib.File, InterpreterObject)):
-        return args
-    result = []
-    for a in args:
-        if isinstance(a, list):
-            rest = flatten(a)
-            result = result + rest
-        elif isinstance(a, mparser.StringNode):
-            result.append(a.value)
-        else:
-            result.append(a)
-    return result
-
-def noPosargs(f):
-    @wraps(f)
-    def wrapped(*wrapped_args, **wrapped_kwargs):
-        args = _get_callee_args(wrapped_args)[2]
-        if args:
-            raise InvalidArguments('Function does not take positional arguments.')
-        return f(*wrapped_args, **wrapped_kwargs)
-    return wrapped
-
-def noKwargs(f):
-    @wraps(f)
-    def wrapped(*wrapped_args, **wrapped_kwargs):
-        kwargs = _get_callee_args(wrapped_args)[3]
-        if kwargs:
-            raise InvalidArguments('Function does not take keyword arguments.')
-        return f(*wrapped_args, **wrapped_kwargs)
-    return wrapped
-
-def stringArgs(f):
-    @wraps(f)
-    def wrapped(*wrapped_args, **wrapped_kwargs):
-        args = _get_callee_args(wrapped_args)[2]
-        assert(isinstance(args, list))
-        check_stringlist(args)
-        return f(*wrapped_args, **wrapped_kwargs)
-    return wrapped
-
-def noArgsFlattening(f):
-    setattr(f, 'no-args-flattening', True)  # noqa: B010
-    return f
-
-def disablerIfNotFound(f):
-    @wraps(f)
-    def wrapped(*wrapped_args, **wrapped_kwargs):
-        kwargs = _get_callee_args(wrapped_args)[3]
-        disabler = kwargs.pop('disabler', False)
-        ret = f(*wrapped_args, **wrapped_kwargs)
-        if disabler and not ret.held_object.found():
-            return Disabler()
-        return ret
-    return wrapped
-
-class permittedKwargs:
-
-    def __init__(self, permitted):
-        self.permitted = permitted
-
-    def __call__(self, f):
-        @wraps(f)
-        def wrapped(*wrapped_args, **wrapped_kwargs):
-            s, node, args, kwargs, _ = _get_callee_args(wrapped_args)
-            for k in kwargs:
-                if k not in self.permitted:
-                    mlog.warning('''Passed invalid keyword argument "{}".'''.format(k), location=node)
-                    mlog.warning('This will become a hard error in the future.')
-            return f(*wrapped_args, **wrapped_kwargs)
-        return wrapped
-
-
-class FeatureCheckBase:
-    "Base class for feature version checks"
-
-    def __init__(self, feature_name, version):
-        self.feature_name = feature_name
-        self.feature_version = version
-
-    @staticmethod
-    def get_target_version(subproject):
-        # Don't do any checks if project() has not been parsed yet
-        if subproject not in mesonlib.project_meson_versions:
-            return ''
-        return mesonlib.project_meson_versions[subproject]
-
-    def use(self, subproject):
-        tv = self.get_target_version(subproject)
-        # No target version
-        if tv == '':
-            return
-        # Target version is new enough
-        if mesonlib.version_compare_condition_with_min(tv, self.feature_version):
-            return
-        # Feature is too new for target version, register it
-        if subproject not in self.feature_registry:
-            self.feature_registry[subproject] = {self.feature_version: set()}
-        register = self.feature_registry[subproject]
-        if self.feature_version not in register:
-            register[self.feature_version] = set()
-        if self.feature_name in register[self.feature_version]:
-            # Don't warn about the same feature multiple times
-            # FIXME: This is needed to prevent duplicate warnings, but also
-            # means we won't warn about a feature used in multiple places.
-            return
-        register[self.feature_version].add(self.feature_name)
-        self.log_usage_warning(tv)
-
-    @classmethod
-    def report(cls, subproject):
-        if subproject not in cls.feature_registry:
-            return
-        warning_str = cls.get_warning_str_prefix(cls.get_target_version(subproject))
-        fv = cls.feature_registry[subproject]
-        for version in sorted(fv.keys()):
-            warning_str += '\n * {}: {}'.format(version, fv[version])
-        mlog.warning(warning_str)
-
-    def __call__(self, f):
-        @wraps(f)
-        def wrapped(*wrapped_args, **wrapped_kwargs):
-            subproject = _get_callee_args(wrapped_args, want_subproject=True)[4]
-            if subproject is None:
-                raise AssertionError('{!r}'.format(wrapped_args))
-            self.use(subproject)
-            return f(*wrapped_args, **wrapped_kwargs)
-        return wrapped
-
-class FeatureNew(FeatureCheckBase):
-    """Checks for new features"""
-    # Class variable, shared across all instances
-    #
-    # Format: {subproject: {feature_version: set(feature_names)}}
-    feature_registry = {}
-
-    @staticmethod
-    def get_warning_str_prefix(tv):
-        return 'Project specifies a minimum meson_version \'{}\' but uses features which were added in newer versions:'.format(tv)
-
-    def log_usage_warning(self, tv):
-        mlog.warning('Project targeting \'{}\' but tried to use feature introduced '
-                     'in \'{}\': {}'.format(tv, self.feature_version, self.feature_name))
-
-class FeatureDeprecated(FeatureCheckBase):
-    """Checks for deprecated features"""
-    # Class variable, shared across all instances
-    #
-    # Format: {subproject: {feature_version: set(feature_names)}}
-    feature_registry = {}
-
-    @staticmethod
-    def get_warning_str_prefix(tv):
-        return 'Deprecated features used:'
-
-    def log_usage_warning(self, tv):
-        mlog.deprecation('Project targeting \'{}\' but tried to use feature '
-                         'deprecated since \'{}\': {}'
-                         ''.format(tv, self.feature_version, self.feature_name))
-
-
-class FeatureCheckKwargsBase:
-    def __init__(self, feature_name, feature_version, kwargs):
-        self.feature_name = feature_name
-        self.feature_version = feature_version
-        self.kwargs = kwargs
-
-    def __call__(self, f):
-        @wraps(f)
-        def wrapped(*wrapped_args, **wrapped_kwargs):
-            # Which FeatureCheck class to invoke
-            FeatureCheckClass = self.feature_check_class
-            kwargs, subproject = _get_callee_args(wrapped_args, want_subproject=True)[3:5]
-            if subproject is None:
-                raise AssertionError('{!r}'.format(wrapped_args))
-            for arg in self.kwargs:
-                if arg not in kwargs:
-                    continue
-                name = arg + ' arg in ' + self.feature_name
-                FeatureCheckClass(name, self.feature_version).use(subproject)
-            return f(*wrapped_args, **wrapped_kwargs)
-        return wrapped
-
-class FeatureNewKwargs(FeatureCheckKwargsBase):
-    feature_check_class = FeatureNew
-
-class FeatureDeprecatedKwargs(FeatureCheckKwargsBase):
-    feature_check_class = FeatureDeprecated
-
-
-class InterpreterException(mesonlib.MesonException):
-    pass
-
-class InvalidCode(InterpreterException):
-    pass
-
-class InvalidArguments(InterpreterException):
-    pass
-
-class SubdirDoneRequest(BaseException):
-    pass
-
-class ContinueRequest(BaseException):
-    pass
-
-class BreakRequest(BaseException):
-    pass
-
-class InterpreterObject:
-    def __init__(self):
-        self.methods = {}
-        # Current node set during a method call. This can be used as location
-        # when printing a warning message during a method call.
-        self.current_node = None
-
-    def method_call(self, method_name, args, kwargs):
-        if method_name in self.methods:
-            method = self.methods[method_name]
-            if not getattr(method, 'no-args-flattening', False):
-                args = flatten(args)
-            return method(args, kwargs)
-        raise InvalidCode('Unknown method "%s" in object.' % method_name)
-
-class MutableInterpreterObject(InterpreterObject):
-    def __init__(self):
-        super().__init__()
-
-class Disabler(InterpreterObject):
-    def __init__(self):
-        super().__init__()
-        self.methods.update({'found': self.found_method})
-
-    def found_method(self, args, kwargs):
-        return False
-
-def is_disabler(i) -> bool:
-    return isinstance(i, Disabler)
-
-def is_arg_disabled(arg) -> bool:
-    if is_disabler(arg):
-        return True
-    if isinstance(arg, list):
-        for i in arg:
-            if is_arg_disabled(i):
-                return True
-    return False
-
-def is_disabled(args, kwargs) -> bool:
-    for i in args:
-        if is_arg_disabled(i):
-            return True
-    for i in kwargs.values():
-        if is_arg_disabled(i):
-            return True
-    return False
-
-class InterpreterBase:
-    def __init__(self, source_root, subdir):
-        self.source_root = source_root
-        self.funcs = {}
-        self.builtin = {}
-        self.subdir = subdir
-        self.variables = {}
-        self.argument_depth = 0
-        self.current_lineno = -1
-        # Current node set during a function call. This can be used as location
-        # when printing a warning message during a method call.
-        self.current_node = None
-
-    def load_root_meson_file(self):
-        mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename)
-        if not os.path.isfile(mesonfile):
-            raise InvalidArguments('Missing Meson file in %s' % mesonfile)
-        with open(mesonfile, encoding='utf8') as mf:
-            code = mf.read()
-        if code.isspace():
-            raise InvalidCode('Builder file is empty.')
-        assert(isinstance(code, str))
-        try:
-            self.ast = mparser.Parser(code, self.subdir).parse()
-        except mesonlib.MesonException as me:
-            me.file = mesonfile
-            raise me
-
-    def join_path_strings(self, args):
-        return os.path.join(*args).replace('\\', '/')
-
-    def parse_project(self):
-        """
-        Parses project() and initializes languages, compilers etc. Do this
-        early because we need this before we parse the rest of the AST.
-        """
-        self.evaluate_codeblock(self.ast, end=1)
-
-    def sanity_check_ast(self):
-        if not isinstance(self.ast, mparser.CodeBlockNode):
-            raise InvalidCode('AST is of invalid type. Possibly a bug in the parser.')
-        if not self.ast.lines:
-            raise InvalidCode('No statements in code.')
-        first = self.ast.lines[0]
-        if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project':
-            raise InvalidCode('First statement must be a call to project')
-
-    def run(self):
-        # Evaluate everything after the first line, which is project() because
-        # we already parsed that in self.parse_project()
-        try:
-            self.evaluate_codeblock(self.ast, start=1)
-        except SubdirDoneRequest:
-            pass
-
-    def evaluate_codeblock(self, node, start=0, end=None):
-        if node is None:
-            return
-        if not isinstance(node, mparser.CodeBlockNode):
-            e = InvalidCode('Tried to execute a non-codeblock. Possibly a bug in the parser.')
-            e.lineno = node.lineno
-            e.colno = node.colno
-            raise e
-        statements = node.lines[start:end]
-        i = 0
-        while i < len(statements):
-            cur = statements[i]
-            try:
-                self.current_lineno = cur.lineno
-                self.evaluate_statement(cur)
-            except Exception as e:
-                if not hasattr(e, 'lineno'):
-                    e.lineno = cur.lineno
-                    e.colno = cur.colno
-                    e.file = os.path.join(self.subdir, 'meson.build')
-                raise e
-            i += 1 # In THE FUTURE jump over blocks and stuff.
-
-    def evaluate_statement(self, cur):
-        if isinstance(cur, mparser.FunctionNode):
-            return self.function_call(cur)
-        elif isinstance(cur, mparser.AssignmentNode):
-            return self.assignment(cur)
-        elif isinstance(cur, mparser.MethodNode):
-            return self.method_call(cur)
-        elif isinstance(cur, mparser.StringNode):
-            return cur.value
-        elif isinstance(cur, mparser.BooleanNode):
-            return cur.value
-        elif isinstance(cur, mparser.IfClauseNode):
-            return self.evaluate_if(cur)
-        elif isinstance(cur, mparser.IdNode):
-            return self.get_variable(cur.value)
-        elif isinstance(cur, mparser.ComparisonNode):
-            return self.evaluate_comparison(cur)
-        elif isinstance(cur, mparser.ArrayNode):
-            return self.evaluate_arraystatement(cur)
-        elif isinstance(cur, mparser.DictNode):
-            return self.evaluate_dictstatement(cur)
-        elif isinstance(cur, mparser.NumberNode):
-            return cur.value
-        elif isinstance(cur, mparser.AndNode):
-            return self.evaluate_andstatement(cur)
-        elif isinstance(cur, mparser.OrNode):
-            return self.evaluate_orstatement(cur)
-        elif isinstance(cur, mparser.NotNode):
-            return self.evaluate_notstatement(cur)
-        elif isinstance(cur, mparser.UMinusNode):
-            return self.evaluate_uminusstatement(cur)
-        elif isinstance(cur, mparser.ArithmeticNode):
-            return self.evaluate_arithmeticstatement(cur)
-        elif isinstance(cur, mparser.ForeachClauseNode):
-            return self.evaluate_foreach(cur)
-        elif isinstance(cur, mparser.PlusAssignmentNode):
-            return self.evaluate_plusassign(cur)
-        elif isinstance(cur, mparser.IndexNode):
-            return self.evaluate_indexing(cur)
-        elif isinstance(cur, mparser.TernaryNode):
-            return self.evaluate_ternary(cur)
-        elif isinstance(cur, mparser.ContinueNode):
-            raise ContinueRequest()
-        elif isinstance(cur, mparser.BreakNode):
-            raise BreakRequest()
-        elif self.is_elementary_type(cur):
-            return cur
-        else:
-            raise InvalidCode("Unknown statement.")
-
-    def evaluate_arraystatement(self, cur):
-        (arguments, kwargs) = self.reduce_arguments(cur.args)
-        if len(kwargs) > 0:
-            raise InvalidCode('Keyword arguments are invalid in array construction.')
-        return arguments
-
-    @FeatureNew('dict', '0.47.0')
-    def evaluate_dictstatement(self, cur):
-        (arguments, kwargs) = self.reduce_arguments(cur.args)
-        assert (not arguments)
-        result = {}
-        self.argument_depth += 1
-        for key, value in kwargs.items():
-            if not isinstance(key, mparser.StringNode):
-                FeatureNew('Dictionary entry using non literal key', '0.53.0').use(self.subproject)
-            key = self.evaluate_statement(key)
-            if not isinstance(key, str):
-                raise InvalidArguments('Key must be a string')
-            if key in result:
-                raise InvalidArguments('Duplicate dictionary key: {}'.format(key))
-            result[key] = value
-        self.argument_depth -= 1
-        return result
-
-    def evaluate_notstatement(self, cur):
-        v = self.evaluate_statement(cur.value)
-        if is_disabler(v):
-            return v
-        if not isinstance(v, bool):
-            raise InterpreterException('Argument to "not" is not a boolean.')
-        return not v
-
-    def evaluate_if(self, node):
-        assert(isinstance(node, mparser.IfClauseNode))
-        for i in node.ifs:
-            result = self.evaluate_statement(i.condition)
-            if is_disabler(result):
-                return result
-            if not(isinstance(result, bool)):
-                raise InvalidCode('If clause {!r} does not evaluate to true or false.'.format(result))
-            if result:
-                self.evaluate_codeblock(i.block)
-                return
-        if not isinstance(node.elseblock, mparser.EmptyNode):
-            self.evaluate_codeblock(node.elseblock)
-
-    def validate_comparison_types(self, val1, val2):
-        if type(val1) != type(val2):
-            return False
-        return True
-
-    def evaluate_in(self, val1, val2):
-        if not isinstance(val1, (str, int, float, ObjectHolder)):
-            raise InvalidArguments('lvalue of "in" operator must be a string, integer, float, or object')
-        if not isinstance(val2, (list, dict)):
-            raise InvalidArguments('rvalue of "in" operator must be an array or a dict')
-        return val1 in val2
-
-    def evaluate_comparison(self, node):
-        val1 = self.evaluate_statement(node.left)
-        if is_disabler(val1):
-            return val1
-        val2 = self.evaluate_statement(node.right)
-        if is_disabler(val2):
-            return val2
-        if node.ctype == 'in':
-            return self.evaluate_in(val1, val2)
-        elif node.ctype == 'notin':
-            return not self.evaluate_in(val1, val2)
-        valid = self.validate_comparison_types(val1, val2)
-        # Ordering comparisons of different types isn't allowed since PR #1810
-        # (0.41.0).  Since PR #2884 we also warn about equality comparisons of
-        # different types, which will one day become an error.
-        if not valid and (node.ctype == '==' or node.ctype == '!='):
-            mlog.warning('''Trying to compare values of different types ({}, {}) using {}.
-The result of this is undefined and will become a hard error in a future Meson release.'''
-                         .format(type(val1).__name__, type(val2).__name__, node.ctype), location=node)
-        if node.ctype == '==':
-            return val1 == val2
-        elif node.ctype == '!=':
-            return val1 != val2
-        elif not valid:
-            raise InterpreterException(
-                'Values of different types ({}, {}) cannot be compared using {}.'.format(type(val1).__name__,
-                                                                                         type(val2).__name__,
-                                                                                         node.ctype))
-        elif not self.is_elementary_type(val1):
-            raise InterpreterException('{} can only be compared for equality.'.format(node.left.value))
-        elif not self.is_elementary_type(val2):
-            raise InterpreterException('{} can only be compared for equality.'.format(node.right.value))
-        elif node.ctype == '<':
-            return val1 < val2
-        elif node.ctype == '<=':
-            return val1 <= val2
-        elif node.ctype == '>':
-            return val1 > val2
-        elif node.ctype == '>=':
-            return val1 >= val2
-        else:
-            raise InvalidCode('You broke my compare eval.')
-
-    def evaluate_andstatement(self, cur):
-        l = self.evaluate_statement(cur.left)
-        if is_disabler(l):
-            return l
-        if not isinstance(l, bool):
-            raise InterpreterException('First argument to "and" is not a boolean.')
-        if not l:
-            return False
-        r = self.evaluate_statement(cur.right)
-        if is_disabler(r):
-            return r
-        if not isinstance(r, bool):
-            raise InterpreterException('Second argument to "and" is not a boolean.')
-        return r
-
-    def evaluate_orstatement(self, cur):
-        l = self.evaluate_statement(cur.left)
-        if is_disabler(l):
-            return l
-        if not isinstance(l, bool):
-            raise InterpreterException('First argument to "or" is not a boolean.')
-        if l:
-            return True
-        r = self.evaluate_statement(cur.right)
-        if is_disabler(r):
-            return r
-        if not isinstance(r, bool):
-            raise InterpreterException('Second argument to "or" is not a boolean.')
-        return r
-
-    def evaluate_uminusstatement(self, cur):
-        v = self.evaluate_statement(cur.value)
-        if is_disabler(v):
-            return v
-        if not isinstance(v, int):
-            raise InterpreterException('Argument to negation is not an integer.')
-        return -v
-
-    @FeatureNew('/ with string arguments', '0.49.0')
-    def evaluate_path_join(self, l, r):
-        if not isinstance(l, str):
-            raise InvalidCode('The division operator can only append to a string.')
-        if not isinstance(r, str):
-            raise InvalidCode('The division operator can only append a string.')
-        return self.join_path_strings((l, r))
-
-    def evaluate_division(self, l, r):
-        if isinstance(l, str) or isinstance(r, str):
-            return self.evaluate_path_join(l, r)
-        if isinstance(l, int) and isinstance(r, int):
-            if r == 0:
-                raise InvalidCode('Division by zero.')
-            return l // r
-        raise InvalidCode('Division works only with strings or integers.')
-
-    def evaluate_arithmeticstatement(self, cur):
-        l = self.evaluate_statement(cur.left)
-        if is_disabler(l):
-            return l
-        r = self.evaluate_statement(cur.right)
-        if is_disabler(r):
-            return r
-
-        if cur.operation == 'add':
-            if isinstance(l, dict) and isinstance(r, dict):
-                return {**l, **r}
-            try:
-                return l + r
-            except Exception as e:
-                raise InvalidCode('Invalid use of addition: ' + str(e))
-        elif cur.operation == 'sub':
-            if not isinstance(l, int) or not isinstance(r, int):
-                raise InvalidCode('Subtraction works only with integers.')
-            return l - r
-        elif cur.operation == 'mul':
-            if not isinstance(l, int) or not isinstance(r, int):
-                raise InvalidCode('Multiplication works only with integers.')
-            return l * r
-        elif cur.operation == 'div':
-            return self.evaluate_division(l, r)
-        elif cur.operation == 'mod':
-            if not isinstance(l, int) or not isinstance(r, int):
-                raise InvalidCode('Modulo works only with integers.')
-            return l % r
-        else:
-            raise InvalidCode('You broke me.')
-
-    def evaluate_ternary(self, node):
-        assert(isinstance(node, mparser.TernaryNode))
-        result = self.evaluate_statement(node.condition)
-        if is_disabler(result):
-            return result
-        if not isinstance(result, bool):
-            raise InterpreterException('Ternary condition is not boolean.')
-        if result:
-            return self.evaluate_statement(node.trueblock)
-        else:
-            return self.evaluate_statement(node.falseblock)
-
-    def evaluate_foreach(self, node):
-        assert(isinstance(node, mparser.ForeachClauseNode))
-        items = self.evaluate_statement(node.items)
-
-        if isinstance(items, list):
-            if len(node.varnames) != 1:
-                raise InvalidArguments('Foreach on array does not unpack')
-            varname = node.varnames[0].value
-            for item in items:
-                self.set_variable(varname, item)
-                try:
-                    self.evaluate_codeblock(node.block)
-                except ContinueRequest:
-                    continue
-                except BreakRequest:
-                    break
-        elif isinstance(items, dict):
-            if len(node.varnames) != 2:
-                raise InvalidArguments('Foreach on dict unpacks key and value')
-            for key, value in items.items():
-                self.set_variable(node.varnames[0].value, key)
-                self.set_variable(node.varnames[1].value, value)
-                try:
-                    self.evaluate_codeblock(node.block)
-                except ContinueRequest:
-                    continue
-                except BreakRequest:
-                    break
-        else:
-            raise InvalidArguments('Items of foreach loop must be an array or a dict')
-
-    def evaluate_plusassign(self, node):
-        assert(isinstance(node, mparser.PlusAssignmentNode))
-        varname = node.var_name
-        addition = self.evaluate_statement(node.value)
-        if is_disabler(addition):
-            self.set_variable(varname, addition)
-            return
-        # Remember that all variables are immutable. We must always create a
-        # full new variable and then assign it.
-        old_variable = self.get_variable(varname)
-        if isinstance(old_variable, str):
-            if not isinstance(addition, str):
-                raise InvalidArguments('The += operator requires a string on the right hand side if the variable on the left is a string')
-            new_value = old_variable + addition
-        elif isinstance(old_variable, int):
-            if not isinstance(addition, int):
-                raise InvalidArguments('The += operator requires an int on the right hand side if the variable on the left is an int')
-            new_value = old_variable + addition
-        elif isinstance(old_variable, list):
-            if isinstance(addition, list):
-                new_value = old_variable + addition
-            else:
-                new_value = old_variable + [addition]
-        elif isinstance(old_variable, dict):
-            if not isinstance(addition, dict):
-                raise InvalidArguments('The += operator requires a dict on the right hand side if the variable on the left is a dict')
-            new_value = {**old_variable, **addition}
-        # Add other data types here.
-        else:
-            raise InvalidArguments('The += operator currently only works with arrays, dicts, strings or ints ')
-        self.set_variable(varname, new_value)
-
-    def evaluate_indexing(self, node):
-        assert(isinstance(node, mparser.IndexNode))
-        iobject = self.evaluate_statement(node.iobject)
-        if is_disabler(iobject):
-            return iobject
-        if not hasattr(iobject, '__getitem__'):
-            raise InterpreterException(
-                'Tried to index an object that doesn\'t support indexing.')
-        index = self.evaluate_statement(node.index)
-
-        if isinstance(iobject, dict):
-            if not isinstance(index, str):
-                raise InterpreterException('Key is not a string')
-            try:
-                return iobject[index]
-            except KeyError:
-                raise InterpreterException('Key %s is not in dict' % index)
-        else:
-            if not isinstance(index, int):
-                raise InterpreterException('Index value is not an integer.')
-            try:
-                return iobject[index]
-            except IndexError:
-                raise InterpreterException('Index %d out of bounds of array of size %d.' % (index, len(iobject)))
-
-    def function_call(self, node):
-        func_name = node.func_name
-        (posargs, kwargs) = self.reduce_arguments(node.args)
-        if is_disabled(posargs, kwargs) and func_name != 'set_variable' and func_name != 'is_disabler':
-            return Disabler()
-        if func_name in self.funcs:
-            func = self.funcs[func_name]
-            if not getattr(func, 'no-args-flattening', False):
-                posargs = flatten(posargs)
-
-            self.current_node = node
-            return func(node, posargs, kwargs)
-        else:
-            self.unknown_function_called(func_name)
-
-    def method_call(self, node):
-        invokable = node.source_object
-        if isinstance(invokable, mparser.IdNode):
-            object_name = invokable.value
-            obj = self.get_variable(object_name)
-        else:
-            obj = self.evaluate_statement(invokable)
-        method_name = node.name
-        args = node.args
-        if isinstance(obj, str):
-            return self.string_method_call(obj, method_name, args)
-        if isinstance(obj, bool):
-            return self.bool_method_call(obj, method_name, args)
-        if isinstance(obj, int):
-            return self.int_method_call(obj, method_name, args)
-        if isinstance(obj, list):
-            return self.array_method_call(obj, method_name, args)
-        if isinstance(obj, dict):
-            return self.dict_method_call(obj, method_name, args)
-        if isinstance(obj, mesonlib.File):
-            raise InvalidArguments('File object "%s" is not callable.' % obj)
-        if not isinstance(obj, InterpreterObject):
-            raise InvalidArguments('Variable "%s" is not callable.' % object_name)
-        (args, kwargs) = self.reduce_arguments(args)
-        # Special case. This is the only thing you can do with a disabler
-        # object. Every other use immediately returns the disabler object.
-        if isinstance(obj, Disabler):
-            if method_name == 'found':
-                return False
-            else:
-                return Disabler()
-        if is_disabled(args, kwargs):
-            return Disabler()
-        if method_name == 'extract_objects':
-            self.validate_extraction(obj.held_object)
-        obj.current_node = node
-        return obj.method_call(method_name, args, kwargs)
-
-    def bool_method_call(self, obj, method_name, args):
-        (posargs, kwargs) = self.reduce_arguments(args)
-        if is_disabled(posargs, kwargs):
-            return Disabler()
-        if method_name == 'to_string':
-            if not posargs:
-                if obj:
-                    return 'true'
-                else:
-                    return 'false'
-            elif len(posargs) == 2 and isinstance(posargs[0], str) and isinstance(posargs[1], str):
-                if obj:
-                    return posargs[0]
-                else:
-                    return posargs[1]
-            else:
-                raise InterpreterException('bool.to_string() must have either no arguments or exactly two string arguments that signify what values to return for true and false.')
-        elif method_name == 'to_int':
-            if obj:
-                return 1
-            else:
-                return 0
-        else:
-            raise InterpreterException('Unknown method "%s" for a boolean.' % method_name)
-
-    def int_method_call(self, obj, method_name, args):
-        (posargs, kwargs) = self.reduce_arguments(args)
-        if is_disabled(posargs, kwargs):
-            return Disabler()
-        if method_name == 'is_even':
-            if not posargs:
-                return obj % 2 == 0
-            else:
-                raise InterpreterException('int.is_even() must have no arguments.')
-        elif method_name == 'is_odd':
-            if not posargs:
-                return obj % 2 != 0
-            else:
-                raise InterpreterException('int.is_odd() must have no arguments.')
-        elif method_name == 'to_string':
-            if not posargs:
-                return str(obj)
-            else:
-                raise InterpreterException('int.to_string() must have no arguments.')
-        else:
-            raise InterpreterException('Unknown method "%s" for an integer.' % method_name)
-
-    @staticmethod
-    def _get_one_string_posarg(posargs, method_name):
-        if len(posargs) > 1:
-            m = '{}() must have zero or one arguments'
-            raise InterpreterException(m.format(method_name))
-        elif len(posargs) == 1:
-            s = posargs[0]
-            if not isinstance(s, str):
-                m = '{}() argument must be a string'
-                raise InterpreterException(m.format(method_name))
-            return s
-        return None
-
-    def string_method_call(self, obj, method_name, args):
-        (posargs, kwargs) = self.reduce_arguments(args)
-        if is_disabled(posargs, kwargs):
-            return Disabler()
-        if method_name == 'strip':
-            s = self._get_one_string_posarg(posargs, 'strip')
-            if s is not None:
-                return obj.strip(s)
-            return obj.strip()
-        elif method_name == 'format':
-            return self.format_string(obj, args)
-        elif method_name == 'to_upper':
-            return obj.upper()
-        elif method_name == 'to_lower':
-            return obj.lower()
-        elif method_name == 'underscorify':
-            return re.sub(r'[^a-zA-Z0-9]', '_', obj)
-        elif method_name == 'split':
-            s = self._get_one_string_posarg(posargs, 'split')
-            if s is not None:
-                return obj.split(s)
-            return obj.split()
-        elif method_name == 'startswith' or method_name == 'contains' or method_name == 'endswith':
-            s = posargs[0]
-            if not isinstance(s, str):
-                raise InterpreterException('Argument must be a string.')
-            if method_name == 'startswith':
-                return obj.startswith(s)
-            elif method_name == 'contains':
-                return obj.find(s) >= 0
-            return obj.endswith(s)
-        elif method_name == 'to_int':
-            try:
-                return int(obj)
-            except Exception:
-                raise InterpreterException('String {!r} cannot be converted to int'.format(obj))
-        elif method_name == 'join':
-            if len(posargs) != 1:
-                raise InterpreterException('Join() takes exactly one argument.')
-            strlist = posargs[0]
-            check_stringlist(strlist)
-            return obj.join(strlist)
-        elif method_name == 'version_compare':
-            if len(posargs) != 1:
-                raise InterpreterException('Version_compare() takes exactly one argument.')
-            cmpr = posargs[0]
-            if not isinstance(cmpr, str):
-                raise InterpreterException('Version_compare() argument must be a string.')
-            return mesonlib.version_compare(obj, cmpr)
-        raise InterpreterException('Unknown method "%s" for a string.' % method_name)
-
-    def format_string(self, templ, args):
-        if isinstance(args, mparser.ArgumentNode):
-            args = args.arguments
-        arg_strings = []
-        for arg in args:
-            arg = self.evaluate_statement(arg)
-            if isinstance(arg, bool): # Python boolean is upper case.
-                arg = str(arg).lower()
-            arg_strings.append(str(arg))
-
-        def arg_replace(match):
-            idx = int(match.group(1))
-            if idx >= len(arg_strings):
-                raise InterpreterException('Format placeholder @{}@ out of range.'.format(idx))
-            return arg_strings[idx]
-
-        return re.sub(r'@(\d+)@', arg_replace, templ)
-
-    def unknown_function_called(self, func_name):
-        raise InvalidCode('Unknown function "%s".' % func_name)
-
-    def array_method_call(self, obj, method_name, args):
-        (posargs, kwargs) = self.reduce_arguments(args)
-        if is_disabled(posargs, kwargs):
-            return Disabler()
-        if method_name == 'contains':
-            return self.check_contains(obj, posargs)
-        elif method_name == 'length':
-            return len(obj)
-        elif method_name == 'get':
-            index = posargs[0]
-            fallback = None
-            if len(posargs) == 2:
-                fallback = posargs[1]
-            elif len(posargs) > 2:
-                m = 'Array method \'get()\' only takes two arguments: the ' \
-                    'index and an optional fallback value if the index is ' \
-                    'out of range.'
-                raise InvalidArguments(m)
-            if not isinstance(index, int):
-                raise InvalidArguments('Array index must be a number.')
-            if index < -len(obj) or index >= len(obj):
-                if fallback is None:
-                    m = 'Array index {!r} is out of bounds for array of size {!r}.'
-                    raise InvalidArguments(m.format(index, len(obj)))
-                return fallback
-            return obj[index]
-        m = 'Arrays do not have a method called {!r}.'
-        raise InterpreterException(m.format(method_name))
-
-    def dict_method_call(self, obj, method_name, args):
-        (posargs, kwargs) = self.reduce_arguments(args)
-        if is_disabled(posargs, kwargs):
-            return Disabler()
-
-        if method_name in ('has_key', 'get'):
-            if method_name == 'has_key':
-                if len(posargs) != 1:
-                    raise InterpreterException('has_key() takes exactly one argument.')
-            else:
-                if len(posargs) not in (1, 2):
-                    raise InterpreterException('get() takes one or two arguments.')
-
-            key = posargs[0]
-            if not isinstance(key, (str)):
-                raise InvalidArguments('Dictionary key must be a string.')
-
-            has_key = key in obj
-
-            if method_name == 'has_key':
-                return has_key
-
-            if has_key:
-                return obj[key]
-
-            if len(posargs) == 2:
-                return posargs[1]
-
-            raise InterpreterException('Key {!r} is not in the dictionary.'.format(key))
-
-        if method_name == 'keys':
-            if len(posargs) != 0:
-                raise InterpreterException('keys() takes no arguments.')
-            return list(obj.keys())
-
-        raise InterpreterException('Dictionaries do not have a method called "%s".' % method_name)
-
-    def reduce_arguments(self, args):
-        assert(isinstance(args, mparser.ArgumentNode))
-        if args.incorrect_order():
-            raise InvalidArguments('All keyword arguments must be after positional arguments.')
-        self.argument_depth += 1
-        reduced_pos = [self.evaluate_statement(arg) for arg in args.arguments]
-        reduced_kw = {}
-        for key in args.kwargs.keys():
-            a = args.kwargs[key]
-            reduced_kw[key] = self.evaluate_statement(a)
-        self.argument_depth -= 1
-        final_kw = self.expand_default_kwargs(reduced_kw)
-        return reduced_pos, final_kw
-
-    def expand_default_kwargs(self, kwargs):
-        if 'kwargs' not in kwargs:
-            return kwargs
-        to_expand = kwargs.pop('kwargs')
-        if not isinstance(to_expand, dict):
-            raise InterpreterException('Value of "kwargs" must be dictionary.')
-        if 'kwargs' in to_expand:
-            raise InterpreterException('Kwargs argument must not contain a "kwargs" entry. Points for thinking meta, though. :P')
-        for k, v in to_expand.items():
-            if k in kwargs:
-                raise InterpreterException('Entry "{}" defined both as a keyword argument and in a "kwarg" entry.'.format(k))
-            kwargs[k] = v
-        return kwargs
-
-    def assignment(self, node):
-        assert(isinstance(node, mparser.AssignmentNode))
-        if self.argument_depth != 0:
-            raise InvalidArguments('''Tried to assign values inside an argument list.
-To specify a keyword argument, use : instead of =.''')
-        var_name = node.var_name
-        if not isinstance(var_name, str):
-            raise InvalidArguments('Tried to assign value to a non-variable.')
-        value = self.evaluate_statement(node.value)
-        if not self.is_assignable(value):
-            raise InvalidCode('Tried to assign an invalid value to variable.')
-        # For mutable objects we need to make a copy on assignment
-        if isinstance(value, MutableInterpreterObject):
-            value = copy.deepcopy(value)
-        self.set_variable(var_name, value)
-        return None
-
-    def set_variable(self, varname, variable):
-        if variable is None:
-            raise InvalidCode('Can not assign None to variable.')
-        if not isinstance(varname, str):
-            raise InvalidCode('First argument to set_variable must be a string.')
-        if not self.is_assignable(variable):
-            raise InvalidCode('Assigned value not of assignable type.')
-        if re.match('[_a-zA-Z][_0-9a-zA-Z]*$', varname) is None:
-            raise InvalidCode('Invalid variable name: ' + varname)
-        if varname in self.builtin:
-            raise InvalidCode('Tried to overwrite internal variable "%s"' % varname)
-        self.variables[varname] = variable
-
-    def get_variable(self, varname):
-        if varname in self.builtin:
-            return self.builtin[varname]
-        if varname in self.variables:
-            return self.variables[varname]
-        raise InvalidCode('Unknown variable "%s".' % varname)
-
-    def is_assignable(self, value):
-        return isinstance(value, (InterpreterObject, dependencies.Dependency,
-                                  str, int, list, dict, mesonlib.File))
-
-    def is_elementary_type(self, v):
-        return isinstance(v, (int, float, str, bool, list))
diff -Nru meson-0.53.2/mesonbuild/interpreter.py meson-0.61.2/mesonbuild/interpreter.py
--- meson-0.53.2/mesonbuild/interpreter.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/interpreter.py	1970-01-01 00:00:00.000000000 +0000
@@ -1,4486 +0,0 @@
-# Copyright 2012-2018 The Meson development team
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-
-#     http://www.apache.org/licenses/LICENSE-2.0
-
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from . import mparser
-from . import environment
-from . import coredata
-from . import dependencies
-from . import mlog
-from . import build
-from . import optinterpreter
-from . import compilers
-from .wrap import wrap, WrapMode
-from . import mesonlib
-from .mesonlib import FileMode, MachineChoice, Popen_safe, listify, extract_as_list, has_path_sep
-from .dependencies import ExternalProgram
-from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException
-from .depfile import DepFile
-from .interpreterbase import InterpreterBase
-from .interpreterbase import check_stringlist, flatten, noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening
-from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
-from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler, disablerIfNotFound
-from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs
-from .interpreterbase import ObjectHolder
-from .modules import ModuleReturnValue
-from .cmake import CMakeInterpreter
-
-from pathlib import Path, PurePath
-import os, shutil, uuid
-import re, shlex
-import subprocess
-import collections
-from itertools import chain
-import functools
-import typing as T
-
-import importlib
-
-permitted_method_kwargs = {
-    'partial_dependency': {'compile_args', 'link_args', 'links', 'includes',
-                           'sources'},
-}
-
-def stringifyUserArguments(args):
-    if isinstance(args, list):
-        return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
-    elif isinstance(args, dict):
-        return '{%s}' % ', '.join(['%s : %s' % (stringifyUserArguments(k), stringifyUserArguments(v)) for k, v in args.items()])
-    elif isinstance(args, int):
-        return str(args)
-    elif isinstance(args, str):
-        return "'%s'" % args
-    raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.')
-
-
-class OverrideProgram(dependencies.ExternalProgram):
-    pass
-
-
-class FeatureOptionHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, env, name, option):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, option)
-        if option.is_auto():
-            self.held_object = env.coredata.builtins['auto_features']
-        self.name = name
-        self.methods.update({'enabled': self.enabled_method,
-                             'disabled': self.disabled_method,
-                             'auto': self.auto_method,
-                             })
-
-    @noPosargs
-    @permittedKwargs({})
-    def enabled_method(self, args, kwargs):
-        return self.held_object.is_enabled()
-
-    @noPosargs
-    @permittedKwargs({})
-    def disabled_method(self, args, kwargs):
-        return self.held_object.is_disabled()
-
-    @noPosargs
-    @permittedKwargs({})
-    def auto_method(self, args, kwargs):
-        return self.held_object.is_auto()
-
-def extract_required_kwarg(kwargs, subproject, feature_check=None, default=True):
-    val = kwargs.get('required', default)
-    disabled = False
-    required = False
-    feature = None
-    if isinstance(val, FeatureOptionHolder):
-        if not feature_check:
-            feature_check = FeatureNew('User option "feature"', '0.47.0')
-        feature_check.use(subproject)
-        option = val.held_object
-        feature = val.name
-        if option.is_disabled():
-            disabled = True
-        elif option.is_enabled():
-            required = True
-    elif isinstance(val, bool):
-        required = val
-    else:
-        raise InterpreterException('required keyword argument must be boolean or a feature option')
-
-    # Keep boolean value in kwargs to simplify other places where this kwarg is
-    # checked.
-    kwargs['required'] = required
-
-    return disabled, required, feature
-
-def extract_search_dirs(kwargs):
-    search_dirs = mesonlib.stringlistify(kwargs.get('dirs', []))
-    search_dirs = [Path(d).expanduser() for d in search_dirs]
-    for d in search_dirs:
-        if mesonlib.is_windows() and d.root.startswith('\\'):
-            # a Unix-path starting with `/` that is not absolute on Windows.
-            # discard without failing for end-user ease of cross-platform directory arrays
-            continue
-        if not d.is_absolute():
-            raise InvalidCode('Search directory {} is not an absolute path.'.format(d))
-    return list(map(str, search_dirs))
-
-class TryRunResultHolder(InterpreterObject):
-    def __init__(self, res):
-        super().__init__()
-        self.res = res
-        self.methods.update({'returncode': self.returncode_method,
-                             'compiled': self.compiled_method,
-                             'stdout': self.stdout_method,
-                             'stderr': self.stderr_method,
-                             })
-
-    @noPosargs
-    @permittedKwargs({})
-    def returncode_method(self, args, kwargs):
-        return self.res.returncode
-
-    @noPosargs
-    @permittedKwargs({})
-    def compiled_method(self, args, kwargs):
-        return self.res.compiled
-
-    @noPosargs
-    @permittedKwargs({})
-    def stdout_method(self, args, kwargs):
-        return self.res.stdout
-
-    @noPosargs
-    @permittedKwargs({})
-    def stderr_method(self, args, kwargs):
-        return self.res.stderr
-
-class RunProcess(InterpreterObject):
-
-    def __init__(self, cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False, capture=True):
-        super().__init__()
-        if not isinstance(cmd, ExternalProgram):
-            raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
-        self.capture = capture
-        pc, self.stdout, self.stderr = self.run_command(cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
-        self.returncode = pc.returncode
-        self.methods.update({'returncode': self.returncode_method,
-                             'stdout': self.stdout_method,
-                             'stderr': self.stderr_method,
-                             })
-
-    def run_command(self, cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
-        command_array = cmd.get_command() + args
-        menv = {'MESON_SOURCE_ROOT': source_dir,
-                'MESON_BUILD_ROOT': build_dir,
-                'MESON_SUBDIR': subdir,
-                'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]),
-                }
-        if in_builddir:
-            cwd = os.path.join(build_dir, subdir)
-        else:
-            cwd = os.path.join(source_dir, subdir)
-        child_env = os.environ.copy()
-        child_env.update(menv)
-        child_env = env.get_env(child_env)
-        stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL
-        mlog.debug('Running command:', ' '.join(command_array))
-        try:
-            p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd)
-            if self.capture:
-                mlog.debug('--- stdout ---')
-                mlog.debug(o)
-            else:
-                o = ''
-                mlog.debug('--- stdout disabled ---')
-            mlog.debug('--- stderr ---')
-            mlog.debug(e)
-            mlog.debug('')
-
-            if check and p.returncode != 0:
-                raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
-
-            return p, o, e
-        except FileNotFoundError:
-            raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
-
-    @noPosargs
-    @permittedKwargs({})
-    def returncode_method(self, args, kwargs):
-        return self.returncode
-
-    @noPosargs
-    @permittedKwargs({})
-    def stdout_method(self, args, kwargs):
-        return self.stdout
-
-    @noPosargs
-    @permittedKwargs({})
-    def stderr_method(self, args, kwargs):
-        return self.stderr
-
-class ConfigureFileHolder(InterpreterObject, ObjectHolder):
-
-    def __init__(self, subdir, sourcename, targetname, configuration_data):
-        InterpreterObject.__init__(self)
-        obj = build.ConfigureFile(subdir, sourcename, targetname, configuration_data)
-        ObjectHolder.__init__(self, obj)
-
-
-class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder):
-    def __init__(self, initial_values=None):
-        MutableInterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, build.EnvironmentVariables())
-        self.methods.update({'set': self.set_method,
-                             'append': self.append_method,
-                             'prepend': self.prepend_method,
-                             })
-        if isinstance(initial_values, dict):
-            for k, v in initial_values.items():
-                self.set_method([k, v], {})
-        elif isinstance(initial_values, list):
-            for e in initial_values:
-                if '=' not in e:
-                    raise InterpreterException('Env var definition must be of type key=val.')
-                (k, val) = e.split('=', 1)
-                k = k.strip()
-                val = val.strip()
-                if ' ' in k:
-                    raise InterpreterException('Env var key must not have spaces in it.')
-                self.set_method([k, val], {})
-        elif initial_values:
-            raise AssertionError('Unsupported EnvironmentVariablesHolder initial_values')
-
-    def __repr__(self):
-        repr_str = "<{0}: {1}>"
-        return repr_str.format(self.__class__.__name__, self.held_object.envvars)
-
-    def add_var(self, method, args, kwargs):
-        if not isinstance(kwargs.get("separator", ""), str):
-            raise InterpreterException("EnvironmentVariablesHolder methods 'separator'"
-                                       " argument needs to be a string.")
-        if len(args) < 2:
-            raise InterpreterException("EnvironmentVariablesHolder methods require at least"
-                                       "2 arguments, first is the name of the variable and"
-                                       " following one are values")
-        # Warn when someone tries to use append() or prepend() on an env var
-        # which already has an operation set on it. People seem to think that
-        # multiple append/prepend operations stack, but they don't.
-        if method != self.held_object.set and self.held_object.has_name(args[0]):
-            mlog.warning('Overriding previous value of environment variable {!r} with a new one'
-                         .format(args[0]), location=self.current_node)
-        self.held_object.add_var(method, args[0], args[1:], kwargs)
-
-    @stringArgs
-    @permittedKwargs({'separator'})
-    def set_method(self, args, kwargs):
-        self.add_var(self.held_object.set, args, kwargs)
-
-    @stringArgs
-    @permittedKwargs({'separator'})
-    def append_method(self, args, kwargs):
-        self.add_var(self.held_object.append, args, kwargs)
-
-    @stringArgs
-    @permittedKwargs({'separator'})
-    def prepend_method(self, args, kwargs):
-        self.add_var(self.held_object.prepend, args, kwargs)
-
-
-class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
-    def __init__(self, pv, initial_values=None):
-        MutableInterpreterObject.__init__(self)
-        self.used = False # These objects become immutable after use in configure_file.
-        ObjectHolder.__init__(self, build.ConfigurationData(), pv)
-        self.methods.update({'set': self.set_method,
-                             'set10': self.set10_method,
-                             'set_quoted': self.set_quoted_method,
-                             'has': self.has_method,
-                             'get': self.get_method,
-                             '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 ConfigurationDataHolder initial_values')
-
-    def is_used(self):
-        return self.used
-
-    def mark_used(self):
-        self.used = True
-
-    def validate_args(self, args, kwargs):
-        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 = 'Setting a configuration data value to {!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.format(val), 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.')
-
-        return name, val, desc
-
-    @noArgsFlattening
-    def set_method(self, args, kwargs):
-        (name, val, desc) = self.validate_args(args, kwargs)
-        self.held_object.values[name] = (val, desc)
-
-    def set_quoted_method(self, args, kwargs):
-        (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.held_object.values[name] = ('"' + escaped_val + '"', desc)
-
-    def set10_method(self, args, kwargs):
-        (name, val, desc) = self.validate_args(args, kwargs)
-        if val:
-            self.held_object.values[name] = (1, desc)
-        else:
-            self.held_object.values[name] = (0, desc)
-
-    def has_method(self, args, kwargs):
-        return args[0] in self.held_object.values
-
-    @FeatureNew('configuration_data.get()', '0.38.0')
-    @noArgsFlattening
-    def get_method(self, args, kwargs):
-        if len(args) < 1 or len(args) > 2:
-            raise InterpreterException('Get method takes one or two arguments.')
-        name = args[0]
-        if name in self.held_object:
-            return self.held_object.get(name)[0]
-        if len(args) > 1:
-            return args[1]
-        raise InterpreterException('Entry %s not in configuration data.' % name)
-
-    @FeatureNew('configuration_data.get_unquoted()', '0.44.0')
-    def get_unquoted_method(self, args, kwargs):
-        if len(args) < 1 or len(args) > 2:
-            raise InterpreterException('Get method takes one or two arguments.')
-        name = args[0]
-        if name in self.held_object:
-            val = self.held_object.get(name)[0]
-        elif len(args) > 1:
-            val = args[1]
-        else:
-            raise InterpreterException('Entry %s not in configuration data.' % name)
-        if val[0] == '"' and val[-1] == '"':
-            return val[1:-1]
-        return val
-
-    def get(self, name):
-        return self.held_object.values[name] # (val, desc)
-
-    def keys(self):
-        return self.held_object.values.keys()
-
-    def merge_from_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Merge_from takes one positional argument.')
-        from_object = args[0]
-        if not isinstance(from_object, ConfigurationDataHolder):
-            raise InterpreterException('Merge_from argument must be a configuration data object.')
-        from_object = from_object.held_object
-        for k, v in from_object.values.items():
-            self.held_object.values[k] = v
-
-# Interpreter objects can not be pickled so we must have
-# these wrappers.
-
-class DependencyHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, dep, pv):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, dep, pv)
-        self.methods.update({'found': self.found_method,
-                             'type_name': self.type_name_method,
-                             'version': self.version_method,
-                             'name': self.name_method,
-                             'get_pkgconfig_variable': self.pkgconfig_method,
-                             'get_configtool_variable': self.configtool_method,
-                             'get_variable': self.variable_method,
-                             'partial_dependency': self.partial_dependency_method,
-                             'include_type': self.include_type_method,
-                             'as_system': self.as_system_method,
-                             })
-
-    def found(self):
-        return self.found_method([], {})
-
-    @noPosargs
-    @permittedKwargs({})
-    def type_name_method(self, args, kwargs):
-        return self.held_object.type_name
-
-    @noPosargs
-    @permittedKwargs({})
-    def found_method(self, args, kwargs):
-        if self.held_object.type_name == 'internal':
-            return True
-        return self.held_object.found()
-
-    @noPosargs
-    @permittedKwargs({})
-    def version_method(self, args, kwargs):
-        return self.held_object.get_version()
-
-    @noPosargs
-    @permittedKwargs({})
-    def name_method(self, args, kwargs):
-        return self.held_object.get_name()
-
-    @permittedKwargs({'define_variable', 'default'})
-    def pkgconfig_method(self, args, kwargs):
-        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)
-
-    @FeatureNew('dep.get_configtool_variable', '0.44.0')
-    @permittedKwargs({})
-    def configtool_method(self, args, kwargs):
-        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)
-
-    @FeatureNew('dep.partial_dependency', '0.46.0')
-    @noPosargs
-    @permittedKwargs(permitted_method_kwargs['partial_dependency'])
-    def partial_dependency_method(self, args, kwargs):
-        pdep = self.held_object.get_partial_dependency(**kwargs)
-        return DependencyHolder(pdep, self.subproject)
-
-    @FeatureNew('dep.get_variable', '0.51.0')
-    @noPosargs
-    @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'default_value', 'pkgconfig_define'})
-    def variable_method(self, args, kwargs):
-        return self.held_object.get_variable(**kwargs)
-
-    @FeatureNew('dep.include_type', '0.52.0')
-    @noPosargs
-    @permittedKwargs({})
-    def include_type_method(self, args, kwargs):
-        return self.held_object.get_include_type()
-
-    @FeatureNew('dep.as_system', '0.52.0')
-    @permittedKwargs({})
-    def as_system_method(self, args, kwargs):
-        args = listify(args)
-        new_is_system = 'system'
-        if len(args) > 1:
-            raise InterpreterException('as_system takes only one optional value')
-        if len(args) == 1:
-            new_is_system = args[0]
-        new_dep = self.held_object.generate_system_dependency(new_is_system)
-        return DependencyHolder(new_dep, self.subproject)
-
-class ExternalProgramHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, ep):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, ep)
-        self.methods.update({'found': self.found_method,
-                             'path': self.path_method})
-        self.cached_version = None
-
-    @noPosargs
-    @permittedKwargs({})
-    def found_method(self, args, kwargs):
-        return self.found()
-
-    @noPosargs
-    @permittedKwargs({})
-    def path_method(self, args, kwargs):
-        return self.held_object.get_path()
-
-    def found(self):
-        return isinstance(self.held_object, build.Executable) or self.held_object.found()
-
-    def get_command(self):
-        return self.held_object.get_command()
-
-    def get_name(self):
-        return self.held_object.get_name()
-
-    def get_version(self, interpreter):
-        if not self.cached_version:
-            raw_cmd = self.get_command() + ['--version']
-            cmd = [self, '--version']
-            res = interpreter.run_command_impl(interpreter.current_node, cmd, {}, True)
-            if res.returncode != 0:
-                m = 'Running {!r} failed'
-                raise InterpreterException(m.format(raw_cmd))
-            output = res.stdout.strip()
-            if not output:
-                output = res.stderr.strip()
-            match = re.search(r'([0-9][0-9\.]+)', output)
-            if not match:
-                m = 'Could not find a version number in output of {!r}'
-                raise InterpreterException(m.format(raw_cmd))
-            self.cached_version = match.group(1)
-        return self.cached_version
-
-class ExternalLibraryHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, el, pv):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, el, pv)
-        self.methods.update({'found': self.found_method,
-                             'type_name': self.type_name_method,
-                             'partial_dependency': self.partial_dependency_method,
-                             })
-
-    def found(self):
-        return self.held_object.found()
-
-    @noPosargs
-    @permittedKwargs({})
-    def type_name_method(self, args, kwargs):
-        return self.held_object.type_name
-
-    @noPosargs
-    @permittedKwargs({})
-    def found_method(self, args, kwargs):
-        return self.found()
-
-    def get_name(self):
-        return self.held_object.name
-
-    def get_compile_args(self):
-        return self.held_object.get_compile_args()
-
-    def get_link_args(self):
-        return self.held_object.get_link_args()
-
-    def get_exe_args(self):
-        return self.held_object.get_exe_args()
-
-    @FeatureNew('dep.partial_dependency', '0.46.0')
-    @noPosargs
-    @permittedKwargs(permitted_method_kwargs['partial_dependency'])
-    def partial_dependency_method(self, args, kwargs):
-        pdep = self.held_object.get_partial_dependency(**kwargs)
-        return DependencyHolder(pdep, self.subproject)
-
-class GeneratorHolder(InterpreterObject, ObjectHolder):
-    @FeatureNewKwargs('generator', '0.43.0', ['capture'])
-    def __init__(self, interp, args, kwargs):
-        self.interpreter = interp
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, build.Generator(args, kwargs), interp.subproject)
-        self.methods.update({'process': self.process_method})
-
-    @FeatureNewKwargs('generator.process', '0.45.0', ['preserve_path_from'])
-    @permittedKwargs({'extra_args', 'preserve_path_from'})
-    def process_method(self, args, kwargs):
-        extras = mesonlib.stringlistify(kwargs.get('extra_args', []))
-        if 'preserve_path_from' in kwargs:
-            preserve_path_from = kwargs['preserve_path_from']
-            if not isinstance(preserve_path_from, str):
-                raise InvalidArguments('Preserve_path_from must be a string.')
-            preserve_path_from = os.path.normpath(preserve_path_from)
-            if not os.path.isabs(preserve_path_from):
-                # This is a bit of a hack. Fix properly before merging.
-                raise InvalidArguments('Preserve_path_from must be an absolute path for now. Sorry.')
-        else:
-            preserve_path_from = None
-        gl = self.held_object.process_files('Generator', args, self.interpreter,
-                                            preserve_path_from, extra_args=extras)
-        return GeneratedListHolder(gl)
-
-
-class GeneratedListHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, arg1, extra_args=None):
-        InterpreterObject.__init__(self)
-        if isinstance(arg1, GeneratorHolder):
-            ObjectHolder.__init__(self, build.GeneratedList(arg1.held_object, extra_args if extra_args is not None else []))
-        else:
-            ObjectHolder.__init__(self, arg1)
-
-    def __repr__(self):
-        r = '<{}: {!r}>'
-        return r.format(self.__class__.__name__, self.held_object.get_outputs())
-
-    def add_file(self, a):
-        self.held_object.add_file(a)
-
-# A machine that's statically known from the cross file
-class MachineHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, machine_info):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, machine_info)
-        self.methods.update({'system': self.system_method,
-                             'cpu': self.cpu_method,
-                             'cpu_family': self.cpu_family_method,
-                             'endian': self.endian_method,
-                             })
-
-    @noPosargs
-    @permittedKwargs({})
-    def cpu_family_method(self, args, kwargs):
-        return self.held_object.cpu_family
-
-    @noPosargs
-    @permittedKwargs({})
-    def cpu_method(self, args, kwargs):
-        return self.held_object.cpu
-
-    @noPosargs
-    @permittedKwargs({})
-    def system_method(self, args, kwargs):
-        return self.held_object.system
-
-    @noPosargs
-    @permittedKwargs({})
-    def endian_method(self, args, kwargs):
-        return self.held_object.endian
-
-class IncludeDirsHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, idobj):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, idobj)
-
-class Headers(InterpreterObject):
-
-    def __init__(self, sources, kwargs):
-        InterpreterObject.__init__(self)
-        self.sources = sources
-        self.install_subdir = kwargs.get('subdir', '')
-        if os.path.isabs(self.install_subdir):
-            mlog.deprecation('Subdir keyword must not be an absolute path. This will be a hard error in the next release.')
-        self.custom_install_dir = kwargs.get('install_dir', None)
-        self.custom_install_mode = kwargs.get('install_mode', None)
-        if self.custom_install_dir is not None:
-            if not isinstance(self.custom_install_dir, str):
-                raise InterpreterException('Custom_install_dir must be a string.')
-
-    def set_install_subdir(self, subdir):
-        self.install_subdir = subdir
-
-    def get_install_subdir(self):
-        return self.install_subdir
-
-    def get_sources(self):
-        return self.sources
-
-    def get_custom_install_dir(self):
-        return self.custom_install_dir
-
-    def get_custom_install_mode(self):
-        return self.custom_install_mode
-
-class DataHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, data):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, data)
-
-    def get_source_subdir(self):
-        return self.held_object.source_subdir
-
-    def get_sources(self):
-        return self.held_object.sources
-
-    def get_install_dir(self):
-        return self.held_object.install_dir
-
-class InstallDir(InterpreterObject):
-    def __init__(self, src_subdir, inst_subdir, install_dir, install_mode, exclude, strip_directory):
-        InterpreterObject.__init__(self)
-        self.source_subdir = src_subdir
-        self.installable_subdir = inst_subdir
-        self.install_dir = install_dir
-        self.install_mode = install_mode
-        self.exclude = exclude
-        self.strip_directory = strip_directory
-
-class Man(InterpreterObject):
-
-    def __init__(self, sources, kwargs):
-        InterpreterObject.__init__(self)
-        self.sources = sources
-        self.validate_sources()
-        self.custom_install_dir = kwargs.get('install_dir', None)
-        self.custom_install_mode = kwargs.get('install_mode', None)
-        if self.custom_install_dir is not None and not isinstance(self.custom_install_dir, str):
-            raise InterpreterException('Custom_install_dir must be a string.')
-
-    def validate_sources(self):
-        for s in self.sources:
-            try:
-                num = int(s.split('.')[-1])
-            except (IndexError, ValueError):
-                num = 0
-            if num < 1 or num > 8:
-                raise InvalidArguments('Man file must have a file extension of a number between 1 and 8')
-
-    def get_custom_install_dir(self):
-        return self.custom_install_dir
-
-    def get_custom_install_mode(self):
-        return self.custom_install_mode
-
-    def get_sources(self):
-        return self.sources
-
-class GeneratedObjectsHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, held_object):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, held_object)
-
-class TargetHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, target, interp):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, target, interp.subproject)
-        self.interpreter = interp
-
-class BuildTargetHolder(TargetHolder):
-    def __init__(self, target, interp):
-        super().__init__(target, interp)
-        self.methods.update({'extract_objects': self.extract_objects_method,
-                             'extract_all_objects': self.extract_all_objects_method,
-                             'get_id': self.get_id_method,
-                             'outdir': self.outdir_method,
-                             'full_path': self.full_path_method,
-                             'private_dir_include': self.private_dir_include_method,
-                             })
-
-    def __repr__(self):
-        r = '<{} {}: {}>'
-        h = self.held_object
-        return r.format(self.__class__.__name__, h.get_id(), h.filename)
-
-    def is_cross(self):
-        return not self.held_object.environment.machines.matches_build_machine(self.held_object.for_machine)
-
-    @noPosargs
-    @permittedKwargs({})
-    def private_dir_include_method(self, args, kwargs):
-        return IncludeDirsHolder(build.IncludeDirs('', [], False,
-                                                   [self.interpreter.backend.get_target_private_dir(self.held_object)]))
-
-    @noPosargs
-    @permittedKwargs({})
-    def full_path_method(self, args, kwargs):
-        return self.interpreter.backend.get_target_filename_abs(self.held_object)
-
-    @noPosargs
-    @permittedKwargs({})
-    def outdir_method(self, args, kwargs):
-        return self.interpreter.backend.get_target_dir(self.held_object)
-
-    @permittedKwargs({})
-    def extract_objects_method(self, args, kwargs):
-        gobjs = self.held_object.extract_objects(args)
-        return GeneratedObjectsHolder(gobjs)
-
-    @FeatureNewKwargs('extract_all_objects', '0.46.0', ['recursive'])
-    @noPosargs
-    @permittedKwargs({'recursive'})
-    def extract_all_objects_method(self, args, kwargs):
-        recursive = kwargs.get('recursive', False)
-        gobjs = self.held_object.extract_all_objects(recursive)
-        if gobjs.objlist and 'recursive' not in kwargs:
-            mlog.warning('extract_all_objects called without setting recursive '
-                         'keyword argument. Meson currently defaults to '
-                         'non-recursive to maintain backward compatibility but '
-                         'the default will be changed in the future.',
-                         location=self.current_node)
-        return GeneratedObjectsHolder(gobjs)
-
-    @noPosargs
-    @permittedKwargs({})
-    def get_id_method(self, args, kwargs):
-        return self.held_object.get_id()
-
-class ExecutableHolder(BuildTargetHolder):
-    def __init__(self, target, interp):
-        super().__init__(target, interp)
-
-class StaticLibraryHolder(BuildTargetHolder):
-    def __init__(self, target, interp):
-        super().__init__(target, interp)
-
-class SharedLibraryHolder(BuildTargetHolder):
-    def __init__(self, target, interp):
-        super().__init__(target, interp)
-        # Set to True only when called from self.func_shared_lib().
-        target.shared_library_only = False
-
-class BothLibrariesHolder(BuildTargetHolder):
-    def __init__(self, shared_holder, static_holder, interp):
-        # FIXME: This build target always represents the shared library, but
-        # that should be configurable.
-        super().__init__(shared_holder.held_object, interp)
-        self.shared_holder = shared_holder
-        self.static_holder = static_holder
-        self.methods.update({'get_shared_lib': self.get_shared_lib_method,
-                             'get_static_lib': self.get_static_lib_method,
-                             })
-
-    def __repr__(self):
-        r = '<{} {}: {}, {}: {}>'
-        h1 = self.shared_holder.held_object
-        h2 = self.static_holder.held_object
-        return r.format(self.__class__.__name__, h1.get_id(), h1.filename, h2.get_id(), h2.filename)
-
-    @noPosargs
-    @permittedKwargs({})
-    def get_shared_lib_method(self, args, kwargs):
-        return self.shared_holder
-
-    @noPosargs
-    @permittedKwargs({})
-    def get_static_lib_method(self, args, kwargs):
-        return self.static_holder
-
-class SharedModuleHolder(BuildTargetHolder):
-    def __init__(self, target, interp):
-        super().__init__(target, interp)
-
-class JarHolder(BuildTargetHolder):
-    def __init__(self, target, interp):
-        super().__init__(target, interp)
-
-class CustomTargetIndexHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, object_to_hold):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, object_to_hold)
-
-class CustomTargetHolder(TargetHolder):
-    def __init__(self, target, interp):
-        super().__init__(target, interp)
-        self.methods.update({'full_path': self.full_path_method,
-                             })
-
-    def __repr__(self):
-        r = '<{} {}: {}>'
-        h = self.held_object
-        return r.format(self.__class__.__name__, h.get_id(), h.command)
-
-    @noPosargs
-    @permittedKwargs({})
-    def full_path_method(self, args, kwargs):
-        return self.interpreter.backend.get_target_filename_abs(self.held_object)
-
-    def __getitem__(self, index):
-        return CustomTargetIndexHolder(self.held_object[index])
-
-    def __setitem__(self, index, value):  # lgtm[py/unexpected-raise-in-special-method]
-        raise InterpreterException('Cannot set a member of a CustomTarget')
-
-    def __delitem__(self, index):  # lgtm[py/unexpected-raise-in-special-method]
-        raise InterpreterException('Cannot delete a member of a CustomTarget')
-
-    def outdir_include(self):
-        return IncludeDirsHolder(build.IncludeDirs('', [], False,
-                                                   [os.path.join('@BUILD_ROOT@', self.interpreter.backend.get_target_dir(self.held_object))]))
-
-class RunTargetHolder(TargetHolder):
-    def __init__(self, target, interp):
-        super().__init__(target, interp)
-
-    def __repr__(self):
-        r = '<{} {}: {}>'
-        h = self.held_object
-        return r.format(self.__class__.__name__, h.get_id(), h.command)
-
-class Test(InterpreterObject):
-    def __init__(self, name: str, project: str, suite: T.List[str], exe: build.Executable,
-                 depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]],
-                 is_parallel: bool, cmd_args: T.List[str], env: build.EnvironmentVariables,
-                 should_fail: bool, timeout: int, workdir: T.Optional[str], protocol: str,
-                 priority: int):
-        InterpreterObject.__init__(self)
-        self.name = name
-        self.suite = suite
-        self.project_name = project
-        self.exe = exe
-        self.depends = depends
-        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.protocol = protocol
-        self.priority = priority
-
-    def get_exe(self):
-        return self.exe
-
-    def get_name(self):
-        return self.name
-
-class SubprojectHolder(InterpreterObject, ObjectHolder):
-
-    def __init__(self, subinterpreter, subproject_dir, name):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, subinterpreter)
-        self.name = name
-        self.subproject_dir = subproject_dir
-        self.methods.update({'get_variable': self.get_variable_method,
-                             'found': self.found_method,
-                             })
-
-    @noPosargs
-    @permittedKwargs({})
-    def found_method(self, args, kwargs):
-        return self.found()
-
-    def found(self):
-        return self.held_object is not None
-
-    @permittedKwargs({})
-    @noArgsFlattening
-    def get_variable_method(self, args, kwargs):
-        if len(args) < 1 or len(args) > 2:
-            raise InterpreterException('Get_variable takes one or two arguments.')
-        if not self.found():
-            raise InterpreterException('Subproject "%s/%s" disabled can\'t get_variable on it.' % (
-                self.subproject_dir, self.name))
-        varname = args[0]
-        if not isinstance(varname, str):
-            raise InterpreterException('Get_variable first argument must be a string.')
-        try:
-            return self.held_object.variables[varname]
-        except KeyError:
-            pass
-
-        if len(args) == 2:
-            return args[1]
-
-        raise InvalidArguments('Requested variable "{0}" not found.'.format(varname))
-
-header_permitted_kwargs = set([
-    'required',
-    'prefix',
-    'no_builtin_args',
-    'include_directories',
-    'args',
-    'dependencies',
-])
-
-find_library_permitted_kwargs = set([
-    'has_headers',
-    'required',
-    'dirs',
-    'static',
-])
-
-find_library_permitted_kwargs |= set(['header_' + k for k in header_permitted_kwargs])
-
-class CompilerHolder(InterpreterObject):
-    def __init__(self, compiler, env, subproject):
-        InterpreterObject.__init__(self)
-        self.compiler = compiler
-        self.environment = env
-        self.subproject = subproject
-        self.methods.update({'compiles': self.compiles_method,
-                             'links': self.links_method,
-                             'get_id': self.get_id_method,
-                             'get_linker_id': self.get_linker_id_method,
-                             'compute_int': self.compute_int_method,
-                             'sizeof': self.sizeof_method,
-                             'get_define': self.get_define_method,
-                             'check_header': self.check_header_method,
-                             'has_header': self.has_header_method,
-                             'has_header_symbol': self.has_header_symbol_method,
-                             'run': self.run_method,
-                             'has_function': self.has_function_method,
-                             'has_member': self.has_member_method,
-                             'has_members': self.has_members_method,
-                             'has_type': self.has_type_method,
-                             'alignment': self.alignment_method,
-                             'version': self.version_method,
-                             'cmd_array': self.cmd_array_method,
-                             'find_library': self.find_library_method,
-                             'has_argument': self.has_argument_method,
-                             'has_function_attribute': self.has_func_attribute_method,
-                             'get_supported_function_attributes': self.get_supported_function_attributes_method,
-                             'has_multi_arguments': self.has_multi_arguments_method,
-                             'get_supported_arguments': self.get_supported_arguments_method,
-                             'first_supported_argument': self.first_supported_argument_method,
-                             'has_link_argument': self.has_link_argument_method,
-                             'has_multi_link_arguments': self.has_multi_link_arguments_method,
-                             'get_supported_link_arguments': self.get_supported_link_arguments_method,
-                             'first_supported_link_argument': self.first_supported_link_argument_method,
-                             'unittest_args': self.unittest_args_method,
-                             'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method,
-                             'get_argument_syntax': self.get_argument_syntax_method,
-                             })
-
-    def _dep_msg(self, deps, endl):
-        msg_single = 'with dependency {}'
-        msg_many = 'with dependencies {}'
-        if not deps:
-            return endl
-        if endl is None:
-            endl = ''
-        tpl = msg_many if len(deps) > 1 else msg_single
-        names = []
-        for d in deps:
-            if isinstance(d, dependencies.ExternalLibrary):
-                name = '-l' + d.name
-            else:
-                name = d.name
-            names.append(name)
-        return tpl.format(', '.join(names)) + endl
-
-    @noPosargs
-    @permittedKwargs({})
-    def version_method(self, args, kwargs):
-        return self.compiler.version
-
-    @noPosargs
-    @permittedKwargs({})
-    def cmd_array_method(self, args, kwargs):
-        return self.compiler.exelist
-
-    def determine_args(self, kwargs, mode='link'):
-        nobuiltins = kwargs.get('no_builtin_args', False)
-        if not isinstance(nobuiltins, bool):
-            raise InterpreterException('Type of no_builtin_args not a boolean.')
-        args = []
-        incdirs = extract_as_list(kwargs, 'include_directories')
-        for i in incdirs:
-            if not isinstance(i, IncludeDirsHolder):
-                raise InterpreterException('Include directories argument must be an include_directories object.')
-            for idir in i.held_object.get_incdirs():
-                idir = os.path.join(self.environment.get_source_dir(),
-                                    i.held_object.get_curdir(), idir)
-                args += self.compiler.get_include_args(idir, False)
-        if not nobuiltins:
-            for_machine = Interpreter.machine_from_native_kwarg(kwargs)
-            opts = self.environment.coredata.compiler_options[for_machine]
-            args += self.compiler.get_option_compile_args(opts)
-            if mode == 'link':
-                args += self.compiler.get_option_link_args(opts)
-        args += mesonlib.stringlistify(kwargs.get('args', []))
-        return args
-
-    def determine_dependencies(self, kwargs, endl=':'):
-        deps = kwargs.get('dependencies', None)
-        if deps is not None:
-            deps = listify(deps)
-            final_deps = []
-            for d in deps:
-                try:
-                    d = d.held_object
-                except Exception:
-                    pass
-                if isinstance(d, InternalDependency) or not isinstance(d, Dependency):
-                    raise InterpreterException('Dependencies must be external dependencies')
-                final_deps.append(d)
-            deps = final_deps
-        return deps, self._dep_msg(deps, endl)
-
-    @permittedKwargs({
-        'prefix',
-        'args',
-        'dependencies',
-    })
-    def alignment_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Alignment method takes exactly one positional argument.')
-        check_stringlist(args)
-        typename = args[0]
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of alignment must be a string.')
-        extra_args = mesonlib.stringlistify(kwargs.get('args', []))
-        deps, msg = self.determine_dependencies(kwargs)
-        result = self.compiler.alignment(typename, prefix, self.environment,
-                                         extra_args=extra_args,
-                                         dependencies=deps)
-        mlog.log('Checking for alignment of', mlog.bold(typename, True), msg, result)
-        return result
-
-    @permittedKwargs({
-        'name',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def run_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Run method takes exactly one positional argument.')
-        code = args[0]
-        if isinstance(code, mesonlib.File):
-            code = mesonlib.File.from_absolute_file(
-                code.rel_to_builddir(self.environment.source_dir))
-        elif not isinstance(code, str):
-            raise InvalidArguments('Argument must be string or file.')
-        testname = kwargs.get('name', '')
-        if not isinstance(testname, str):
-            raise InterpreterException('Testname argument must be a string.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs, endl=None)
-        result = self.compiler.run(code, self.environment, extra_args=extra_args,
-                                   dependencies=deps)
-        if len(testname) > 0:
-            if not result.compiled:
-                h = mlog.red('DID NOT COMPILE')
-            elif result.returncode == 0:
-                h = mlog.green('YES')
-            else:
-                h = mlog.red('NO (%d)' % result.returncode)
-            mlog.log('Checking if', mlog.bold(testname, True), msg, 'runs:', h)
-        return TryRunResultHolder(result)
-
-    @noPosargs
-    @permittedKwargs({})
-    def get_id_method(self, args, kwargs):
-        return self.compiler.get_id()
-
-    @noPosargs
-    @permittedKwargs({})
-    @FeatureNew('compiler.get_linker_id', '0.53.0')
-    def get_linker_id_method(self, args, kwargs):
-        return self.compiler.get_linker_id()
-
-    @noPosargs
-    @permittedKwargs({})
-    def symbols_have_underscore_prefix_method(self, args, kwargs):
-        '''
-        Check if the compiler prefixes _ (underscore) to global C symbols
-        See: https://en.wikipedia.org/wiki/Name_mangling#C
-        '''
-        return self.compiler.symbols_have_underscore_prefix(self.environment)
-
-    @noPosargs
-    @permittedKwargs({})
-    def unittest_args_method(self, args, kwargs):
-        '''
-        This function is deprecated and should not be used.
-        It can be removed in a future version of Meson.
-        '''
-        if not hasattr(self.compiler, 'get_feature_args'):
-            raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language()))
-        build_to_src = os.path.relpath(self.environment.get_source_dir(), self.environment.get_build_dir())
-        return self.compiler.get_feature_args({'unittest': 'true'}, build_to_src)
-
-    @permittedKwargs({
-        'prefix',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def has_member_method(self, args, kwargs):
-        if len(args) != 2:
-            raise InterpreterException('Has_member takes exactly two arguments.')
-        check_stringlist(args)
-        typename, membername = args
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of has_member must be a string.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        had, cached = self.compiler.has_members(typename, [membername], prefix,
-                                                self.environment,
-                                                extra_args=extra_args,
-                                                dependencies=deps)
-        cached = mlog.blue('(cached)') if cached else ''
-        if had:
-            hadtxt = mlog.green('YES')
-        else:
-            hadtxt = mlog.red('NO')
-        mlog.log('Checking whether type', mlog.bold(typename, True),
-                 'has member', mlog.bold(membername, True), msg, hadtxt, cached)
-        return had
-
-    @permittedKwargs({
-        'prefix',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def has_members_method(self, args, kwargs):
-        if len(args) < 2:
-            raise InterpreterException('Has_members needs at least two arguments.')
-        check_stringlist(args)
-        typename, *membernames = args
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of has_members must be a string.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        had, cached = self.compiler.has_members(typename, membernames, prefix,
-                                                self.environment,
-                                                extra_args=extra_args,
-                                                dependencies=deps)
-        cached = mlog.blue('(cached)') if cached else ''
-        if had:
-            hadtxt = mlog.green('YES')
-        else:
-            hadtxt = mlog.red('NO')
-        members = mlog.bold(', '.join(['"{}"'.format(m) for m in membernames]))
-        mlog.log('Checking whether type', mlog.bold(typename, True),
-                 'has members', members, msg, hadtxt, cached)
-        return had
-
-    @permittedKwargs({
-        'prefix',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def has_function_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Has_function takes exactly one argument.')
-        check_stringlist(args)
-        funcname = args[0]
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of has_function must be a string.')
-        extra_args = self.determine_args(kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        had, cached = self.compiler.has_function(funcname, prefix, self.environment,
-                                                 extra_args=extra_args,
-                                                 dependencies=deps)
-        cached = mlog.blue('(cached)') if cached else ''
-        if had:
-            hadtxt = mlog.green('YES')
-        else:
-            hadtxt = mlog.red('NO')
-        mlog.log('Checking for function', mlog.bold(funcname, True), msg, hadtxt, cached)
-        return had
-
-    @permittedKwargs({
-        'prefix',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def has_type_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Has_type takes exactly one argument.')
-        check_stringlist(args)
-        typename = args[0]
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of has_type must be a string.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        had, cached = self.compiler.has_type(typename, prefix, self.environment,
-                                             extra_args=extra_args, dependencies=deps)
-        cached = mlog.blue('(cached)') if cached else ''
-        if had:
-            hadtxt = mlog.green('YES')
-        else:
-            hadtxt = mlog.red('NO')
-        mlog.log('Checking for type', mlog.bold(typename, True), msg, hadtxt, cached)
-        return had
-
-    @FeatureNew('compiler.compute_int', '0.40.0')
-    @permittedKwargs({
-        'prefix',
-        'low',
-        'high',
-        'guess',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def compute_int_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Compute_int takes exactly one argument.')
-        check_stringlist(args)
-        expression = args[0]
-        prefix = kwargs.get('prefix', '')
-        low = kwargs.get('low', None)
-        high = kwargs.get('high', None)
-        guess = kwargs.get('guess', None)
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of compute_int must be a string.')
-        if low is not None and not isinstance(low, int):
-            raise InterpreterException('Low argument of compute_int must be an int.')
-        if high is not None and not isinstance(high, int):
-            raise InterpreterException('High argument of compute_int must be an int.')
-        if guess is not None and not isinstance(guess, int):
-            raise InterpreterException('Guess argument of compute_int must be an int.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        res = self.compiler.compute_int(expression, low, high, guess, prefix,
-                                        self.environment, extra_args=extra_args,
-                                        dependencies=deps)
-        mlog.log('Computing int of', mlog.bold(expression, True), msg, res)
-        return res
-
-    @permittedKwargs({
-        'prefix',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def sizeof_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Sizeof takes exactly one argument.')
-        check_stringlist(args)
-        element = args[0]
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of sizeof must be a string.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        esize = self.compiler.sizeof(element, prefix, self.environment,
-                                     extra_args=extra_args, dependencies=deps)
-        mlog.log('Checking for size of', mlog.bold(element, True), msg, esize)
-        return esize
-
-    @FeatureNew('compiler.get_define', '0.40.0')
-    @permittedKwargs({
-        'prefix',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def get_define_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('get_define() takes exactly one argument.')
-        check_stringlist(args)
-        element = args[0]
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of get_define() must be a string.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        value, cached = self.compiler.get_define(element, prefix, self.environment,
-                                                 extra_args=extra_args,
-                                                 dependencies=deps)
-        cached = mlog.blue('(cached)') if cached else ''
-        mlog.log('Fetching value of define', mlog.bold(element, True), msg, value, cached)
-        return value
-
-    @permittedKwargs({
-        'name',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def compiles_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('compiles method takes exactly one argument.')
-        code = args[0]
-        if isinstance(code, mesonlib.File):
-            code = mesonlib.File.from_absolute_file(
-                code.rel_to_builddir(self.environment.source_dir))
-        elif not isinstance(code, str):
-            raise InvalidArguments('Argument must be string or file.')
-        testname = kwargs.get('name', '')
-        if not isinstance(testname, str):
-            raise InterpreterException('Testname argument must be a string.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs, endl=None)
-        result, cached = self.compiler.compiles(code, self.environment,
-                                                extra_args=extra_args,
-                                                dependencies=deps)
-        if len(testname) > 0:
-            if result:
-                h = mlog.green('YES')
-            else:
-                h = mlog.red('NO')
-            cached = mlog.blue('(cached)') if cached else ''
-            mlog.log('Checking if', mlog.bold(testname, True), msg, 'compiles:', h, cached)
-        return result
-
-    @permittedKwargs({
-        'name',
-        'no_builtin_args',
-        'include_directories',
-        'args',
-        'dependencies',
-    })
-    def links_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('links method takes exactly one argument.')
-        code = args[0]
-        if isinstance(code, mesonlib.File):
-            code = mesonlib.File.from_absolute_file(
-                code.rel_to_builddir(self.environment.source_dir))
-        elif not isinstance(code, str):
-            raise InvalidArguments('Argument must be string or file.')
-        testname = kwargs.get('name', '')
-        if not isinstance(testname, str):
-            raise InterpreterException('Testname argument must be a string.')
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs, endl=None)
-        result, cached = self.compiler.links(code, self.environment,
-                                             extra_args=extra_args,
-                                             dependencies=deps)
-        cached = mlog.blue('(cached)') if cached else ''
-        if len(testname) > 0:
-            if result:
-                h = mlog.green('YES')
-            else:
-                h = mlog.red('NO')
-            mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h, cached)
-        return result
-
-    @FeatureNew('compiler.check_header', '0.47.0')
-    @FeatureNewKwargs('compiler.check_header', '0.50.0', ['required'])
-    @permittedKwargs(header_permitted_kwargs)
-    def check_header_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('check_header method takes exactly one argument.')
-        check_stringlist(args)
-        hname = args[0]
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of has_header must be a string.')
-        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
-        if disabled:
-            mlog.log('Check usable header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled')
-            return False
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        haz, cached = self.compiler.check_header(hname, prefix, self.environment,
-                                                 extra_args=extra_args,
-                                                 dependencies=deps)
-        cached = mlog.blue('(cached)') if cached else ''
-        if required and not haz:
-            raise InterpreterException('{} header {!r} not usable'.format(self.compiler.get_display_language(), hname))
-        elif haz:
-            h = mlog.green('YES')
-        else:
-            h = mlog.red('NO')
-        mlog.log('Check usable header', mlog.bold(hname, True), msg, h, cached)
-        return haz
-
-    @FeatureNewKwargs('compiler.has_header', '0.50.0', ['required'])
-    @permittedKwargs(header_permitted_kwargs)
-    def has_header_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('has_header method takes exactly one argument.')
-        check_stringlist(args)
-        hname = args[0]
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of has_header must be a string.')
-        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
-        if disabled:
-            mlog.log('Has header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled')
-            return False
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        haz, cached = self.compiler.has_header(hname, prefix, self.environment,
-                                               extra_args=extra_args, dependencies=deps)
-        cached = mlog.blue('(cached)') if cached else ''
-        if required and not haz:
-            raise InterpreterException('{} header {!r} not found'.format(self.compiler.get_display_language(), hname))
-        elif haz:
-            h = mlog.green('YES')
-        else:
-            h = mlog.red('NO')
-        mlog.log('Has header', mlog.bold(hname, True), msg, h, cached)
-        return haz
-
-    @FeatureNewKwargs('compiler.has_header_symbol', '0.50.0', ['required'])
-    @permittedKwargs(header_permitted_kwargs)
-    def has_header_symbol_method(self, args, kwargs):
-        if len(args) != 2:
-            raise InterpreterException('has_header_symbol method takes exactly two arguments.')
-        check_stringlist(args)
-        hname, symbol = args
-        prefix = kwargs.get('prefix', '')
-        if not isinstance(prefix, str):
-            raise InterpreterException('Prefix argument of has_header_symbol must be a string.')
-        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
-        if disabled:
-            mlog.log('Header <{0}> has symbol'.format(hname), mlog.bold(symbol, True), 'skipped: feature', mlog.bold(feature), 'disabled')
-            return False
-        extra_args = functools.partial(self.determine_args, kwargs)
-        deps, msg = self.determine_dependencies(kwargs)
-        haz, cached = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment,
-                                                      extra_args=extra_args,
-                                                      dependencies=deps)
-        if required and not haz:
-            raise InterpreterException('{} symbol {} not found in header {}'.format(self.compiler.get_display_language(), symbol, hname))
-        elif haz:
-            h = mlog.green('YES')
-        else:
-            h = mlog.red('NO')
-        cached = mlog.blue('(cached)') if cached else ''
-        mlog.log('Header <{0}> has symbol'.format(hname), mlog.bold(symbol, True), msg, h, cached)
-        return haz
-
-    def notfound_library(self, libname):
-        lib = dependencies.ExternalLibrary(libname, None,
-                                           self.environment,
-                                           self.compiler.language,
-                                           silent=True)
-        return ExternalLibraryHolder(lib, self.subproject)
-
-    @FeatureNewKwargs('compiler.find_library', '0.51.0', ['static'])
-    @FeatureNewKwargs('compiler.find_library', '0.50.0', ['has_headers'])
-    @FeatureNewKwargs('compiler.find_library', '0.49.0', ['disabler'])
-    @disablerIfNotFound
-    @permittedKwargs(find_library_permitted_kwargs)
-    def find_library_method(self, args, kwargs):
-        # TODO add dependencies support?
-        if len(args) != 1:
-            raise InterpreterException('find_library method takes one argument.')
-        libname = args[0]
-        if not isinstance(libname, str):
-            raise InterpreterException('Library name not a string.')
-
-        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
-        if disabled:
-            mlog.log('Library', mlog.bold(libname), 'skipped: feature', mlog.bold(feature), 'disabled')
-            return self.notfound_library(libname)
-
-        has_header_kwargs = {k[7:]: v for k, v in kwargs.items() if k.startswith('header_')}
-        has_header_kwargs['required'] = required
-        headers = mesonlib.stringlistify(kwargs.get('has_headers', []))
-        for h in headers:
-            if not self.has_header_method([h], has_header_kwargs):
-                return self.notfound_library(libname)
-
-        search_dirs = extract_search_dirs(kwargs)
-
-        libtype = mesonlib.LibType.PREFER_SHARED
-        if 'static' in kwargs:
-            if not isinstance(kwargs['static'], bool):
-                raise InterpreterException('static must be a boolean')
-            libtype = mesonlib.LibType.STATIC if kwargs['static'] else mesonlib.LibType.SHARED
-        linkargs = self.compiler.find_library(libname, self.environment, search_dirs, libtype)
-        if required and not linkargs:
-            raise InterpreterException(
-                '{} library {!r} not found'.format(self.compiler.get_display_language(), libname))
-        lib = dependencies.ExternalLibrary(libname, linkargs, self.environment,
-                                           self.compiler.language)
-        return ExternalLibraryHolder(lib, self.subproject)
-
-    @permittedKwargs({})
-    def has_argument_method(self, args, kwargs):
-        args = mesonlib.stringlistify(args)
-        if len(args) != 1:
-            raise InterpreterException('has_argument takes exactly one argument.')
-        return self.has_multi_arguments_method(args, kwargs)
-
-    @permittedKwargs({})
-    def has_multi_arguments_method(self, args, kwargs):
-        args = mesonlib.stringlistify(args)
-        result, cached = self.compiler.has_multi_arguments(args, self.environment)
-        if result:
-            h = mlog.green('YES')
-        else:
-            h = mlog.red('NO')
-        cached = mlog.blue('(cached)') if cached else ''
-        mlog.log(
-            'Compiler for {} supports arguments {}:'.format(
-                self.compiler.get_display_language(), ' '.join(args)),
-            h, cached)
-        return result
-
-    @FeatureNew('compiler.get_supported_arguments', '0.43.0')
-    @permittedKwargs({})
-    def get_supported_arguments_method(self, args, kwargs):
-        args = mesonlib.stringlistify(args)
-        supported_args = []
-        for arg in args:
-            if self.has_argument_method(arg, kwargs):
-                supported_args.append(arg)
-        return supported_args
-
-    @permittedKwargs({})
-    def first_supported_argument_method(self, args, kwargs):
-        for i in mesonlib.stringlistify(args):
-            if self.has_argument_method(i, kwargs):
-                mlog.log('First supported argument:', mlog.bold(i))
-                return [i]
-        mlog.log('First supported argument:', mlog.red('None'))
-        return []
-
-    @FeatureNew('compiler.has_link_argument', '0.46.0')
-    @permittedKwargs({})
-    def has_link_argument_method(self, args, kwargs):
-        args = mesonlib.stringlistify(args)
-        if len(args) != 1:
-            raise InterpreterException('has_link_argument takes exactly one argument.')
-        return self.has_multi_link_arguments_method(args, kwargs)
-
-    @FeatureNew('compiler.has_multi_link_argument', '0.46.0')
-    @permittedKwargs({})
-    def has_multi_link_arguments_method(self, args, kwargs):
-        args = mesonlib.stringlistify(args)
-        result, cached = self.compiler.has_multi_link_arguments(args, self.environment)
-        cached = mlog.blue('(cached)') if cached else ''
-        if result:
-            h = mlog.green('YES')
-        else:
-            h = mlog.red('NO')
-        mlog.log(
-            'Compiler for {} supports link arguments {}:'.format(
-                self.compiler.get_display_language(), ' '.join(args)),
-            h, cached)
-        return result
-
-    @FeatureNew('compiler.get_supported_link_arguments_method', '0.46.0')
-    @permittedKwargs({})
-    def get_supported_link_arguments_method(self, args, kwargs):
-        args = mesonlib.stringlistify(args)
-        supported_args = []
-        for arg in args:
-            if self.has_link_argument_method(arg, kwargs):
-                supported_args.append(arg)
-        return supported_args
-
-    @FeatureNew('compiler.first_supported_link_argument_method', '0.46.0')
-    @permittedKwargs({})
-    def first_supported_link_argument_method(self, args, kwargs):
-        for i in mesonlib.stringlistify(args):
-            if self.has_link_argument_method(i, kwargs):
-                mlog.log('First supported link argument:', mlog.bold(i))
-                return [i]
-        mlog.log('First supported link argument:', mlog.red('None'))
-        return []
-
-    @FeatureNew('compiler.has_function_attribute', '0.48.0')
-    @permittedKwargs({})
-    def has_func_attribute_method(self, args, kwargs):
-        args = mesonlib.stringlistify(args)
-        if len(args) != 1:
-            raise InterpreterException('has_func_attribute takes exactly one argument.')
-        result, cached = self.compiler.has_func_attribute(args[0], self.environment)
-        cached = mlog.blue('(cached)') if cached else ''
-        h = mlog.green('YES') if result else mlog.red('NO')
-        mlog.log('Compiler for {} supports function attribute {}:'.format(self.compiler.get_display_language(), args[0]), h, cached)
-        return result
-
-    @FeatureNew('compiler.get_supported_function_attributes', '0.48.0')
-    @permittedKwargs({})
-    def get_supported_function_attributes_method(self, args, kwargs):
-        args = mesonlib.stringlistify(args)
-        return [a for a in args if self.has_func_attribute_method(a, kwargs)]
-
-    @FeatureNew('compiler.get_argument_syntax_method', '0.49.0')
-    @noPosargs
-    @noKwargs
-    def get_argument_syntax_method(self, args, kwargs):
-        return self.compiler.get_argument_syntax()
-
-
-ModuleState = collections.namedtuple('ModuleState', [
-    'source_root', 'build_to_src', 'subproject', 'subdir', 'current_lineno', 'environment',
-    'project_name', 'project_version', 'backend', 'targets',
-    'data', 'headers', 'man', 'global_args', 'project_args', 'build_machine',
-    'host_machine', 'target_machine', 'current_node'])
-
-class ModuleHolder(InterpreterObject, ObjectHolder):
-    def __init__(self, modname, module, interpreter):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, module)
-        self.modname = modname
-        self.interpreter = interpreter
-
-    def method_call(self, method_name, args, kwargs):
-        try:
-            fn = getattr(self.held_object, method_name)
-        except AttributeError:
-            raise InvalidArguments('Module %s does not have method %s.' % (self.modname, method_name))
-        if method_name.startswith('_'):
-            raise InvalidArguments('Function {!r} in module {!r} is private.'.format(method_name, self.modname))
-        if not getattr(fn, 'no-args-flattening', False):
-            args = flatten(args)
-        # This is not 100% reliable but we can't use hash()
-        # because the Build object contains dicts and lists.
-        num_targets = len(self.interpreter.build.targets)
-        state = ModuleState(
-            source_root = self.interpreter.environment.get_source_dir(),
-            build_to_src=mesonlib.relpath(self.interpreter.environment.get_source_dir(),
-                                          self.interpreter.environment.get_build_dir()),
-            subproject=self.interpreter.subproject,
-            subdir=self.interpreter.subdir,
-            current_lineno=self.interpreter.current_lineno,
-            environment=self.interpreter.environment,
-            project_name=self.interpreter.build.project_name,
-            project_version=self.interpreter.build.dep_manifest[self.interpreter.active_projectname],
-            # The backend object is under-used right now, but we will need it:
-            # https://github.com/mesonbuild/meson/issues/1419
-            backend=self.interpreter.backend,
-            targets=self.interpreter.build.targets,
-            data=self.interpreter.build.data,
-            headers=self.interpreter.build.get_headers(),
-            man=self.interpreter.build.get_man(),
-            #global_args_for_build = self.interpreter.build.global_args.build,
-            global_args = self.interpreter.build.global_args.host,
-            #project_args_for_build = self.interpreter.build.projects_args.build.get(self.interpreter.subproject, {}),
-            project_args = self.interpreter.build.projects_args.host.get(self.interpreter.subproject, {}),
-            build_machine=self.interpreter.builtin['build_machine'].held_object,
-            host_machine=self.interpreter.builtin['host_machine'].held_object,
-            target_machine=self.interpreter.builtin['target_machine'].held_object,
-            current_node=self.current_node
-        )
-        if self.held_object.is_snippet(method_name):
-            value = fn(self.interpreter, state, args, kwargs)
-            return self.interpreter.holderify(value)
-        else:
-            value = fn(state, args, kwargs)
-            if num_targets != len(self.interpreter.build.targets):
-                raise InterpreterException('Extension module altered internal state illegally.')
-            return self.interpreter.module_method_callback(value)
-
-
-class Summary:
-    def __init__(self, project_name, project_version):
-        self.project_name = project_name
-        self.project_version = project_version
-        self.sections = collections.defaultdict(dict)
-        self.max_key_len = 0
-
-    def add_section(self, section, values, kwargs):
-        bool_yn = kwargs.get('bool_yn', False)
-        if not isinstance(bool_yn, bool):
-            raise InterpreterException('bool_yn keyword argument must be boolean')
-        for k, v in values.items():
-            if k in self.sections[section]:
-                raise InterpreterException('Summary section {!r} already have key {!r}'.format(section, k))
-            formatted_values = []
-            for i in listify(v):
-                if not isinstance(i, (str, int)):
-                    m = 'Summary value in section {!r}, key {!r}, must be string, integer or boolean'
-                    raise InterpreterException(m.format(section, k))
-                if bool_yn and isinstance(i, bool):
-                    formatted_values.append(mlog.green('YES') if i else mlog.red('NO'))
-                else:
-                    formatted_values.append(i)
-            if not formatted_values:
-                formatted_values = ['']
-            self.sections[section][k] = formatted_values
-            self.max_key_len = max(self.max_key_len, len(k))
-
-    def dump(self):
-        mlog.log(self.project_name, mlog.normal_cyan(self.project_version))
-        for section, values in self.sections.items():
-            mlog.log('')  # newline
-            if section:
-                mlog.log(' ', mlog.bold(section))
-            for k, v in values.items():
-                indent = self.max_key_len - len(k) + 3
-                mlog.log(' ' * indent, k + ':', v[0])
-                indent = self.max_key_len + 5
-                for i in v[1:]:
-                    mlog.log(' ' * indent, i)
-        mlog.log('')  # newline
-
-
-class MesonMain(InterpreterObject):
-    def __init__(self, build, interpreter):
-        InterpreterObject.__init__(self)
-        self.build = build
-        self.interpreter = interpreter
-        self._found_source_scripts = {}
-        self.methods.update({'get_compiler': self.get_compiler_method,
-                             'is_cross_build': self.is_cross_build_method,
-                             'has_exe_wrapper': self.has_exe_wrapper_method,
-                             'is_unity': self.is_unity_method,
-                             'is_subproject': self.is_subproject_method,
-                             'current_source_dir': self.current_source_dir_method,
-                             'current_build_dir': self.current_build_dir_method,
-                             'source_root': self.source_root_method,
-                             'build_root': self.build_root_method,
-                             'add_install_script': self.add_install_script_method,
-                             'add_postconf_script': self.add_postconf_script_method,
-                             'add_dist_script': self.add_dist_script_method,
-                             'install_dependency_manifest': self.install_dependency_manifest_method,
-                             'override_find_program': self.override_find_program_method,
-                             'project_version': self.project_version_method,
-                             'project_license': self.project_license_method,
-                             'version': self.version_method,
-                             'project_name': self.project_name_method,
-                             'get_cross_property': self.get_cross_property_method,
-                             'backend': self.backend_method,
-                             })
-
-    def _find_source_script(self, name, args):
-        # Prefer scripts in the current source directory
-        search_dir = os.path.join(self.interpreter.environment.source_dir,
-                                  self.interpreter.subdir)
-        key = (name, search_dir)
-        if key in self._found_source_scripts:
-            found = self._found_source_scripts[key]
-        else:
-            found = dependencies.ExternalProgram(name, search_dir=search_dir)
-            if found.found():
-                self._found_source_scripts[key] = found
-            else:
-                m = 'Script or command {!r} not found or not executable'
-                raise InterpreterException(m.format(name))
-        return build.RunScript(found.get_command(), args)
-
-    @permittedKwargs({})
-    def add_install_script_method(self, args, kwargs):
-        if len(args) < 1:
-            raise InterpreterException('add_install_script takes one or more arguments')
-        check_stringlist(args, 'add_install_script args must be strings')
-        script = self._find_source_script(args[0], args[1:])
-        self.build.install_scripts.append(script)
-
-    @permittedKwargs({})
-    def add_postconf_script_method(self, args, kwargs):
-        if len(args) < 1:
-            raise InterpreterException('add_postconf_script takes one or more arguments')
-        check_stringlist(args, 'add_postconf_script arguments must be strings')
-        script = self._find_source_script(args[0], args[1:])
-        self.build.postconf_scripts.append(script)
-
-    @permittedKwargs({})
-    def add_dist_script_method(self, args, kwargs):
-        if len(args) < 1:
-            raise InterpreterException('add_dist_script takes one or more arguments')
-        if len(args) > 1:
-            FeatureNew('Calling "add_dist_script" with multiple arguments', '0.49.0').use(self.interpreter.subproject)
-        check_stringlist(args, 'add_dist_script argument must be a string')
-        if self.interpreter.subproject != '':
-            raise InterpreterException('add_dist_script may not be used in a subproject.')
-        script = self._find_source_script(args[0], args[1:])
-        self.build.dist_scripts.append(script)
-
-    @noPosargs
-    @permittedKwargs({})
-    def current_source_dir_method(self, args, kwargs):
-        src = self.interpreter.environment.source_dir
-        sub = self.interpreter.subdir
-        if sub == '':
-            return src
-        return os.path.join(src, sub)
-
-    @noPosargs
-    @permittedKwargs({})
-    def current_build_dir_method(self, args, kwargs):
-        src = self.interpreter.environment.build_dir
-        sub = self.interpreter.subdir
-        if sub == '':
-            return src
-        return os.path.join(src, sub)
-
-    @noPosargs
-    @permittedKwargs({})
-    def backend_method(self, args, kwargs):
-        return self.interpreter.backend.name
-
-    @noPosargs
-    @permittedKwargs({})
-    def source_root_method(self, args, kwargs):
-        return self.interpreter.environment.source_dir
-
-    @noPosargs
-    @permittedKwargs({})
-    def build_root_method(self, args, kwargs):
-        return self.interpreter.environment.build_dir
-
-    @noPosargs
-    @permittedKwargs({})
-    def has_exe_wrapper_method(self, args, kwargs):
-        if self.is_cross_build_method(None, None) and \
-           self.build.environment.need_exe_wrapper():
-            if self.build.environment.exe_wrapper is None:
-                return False
-        # We return True when exe_wrap is defined, when it's not needed, and
-        # when we're compiling natively. The last two are semantically confusing.
-        # Need to revisit this.
-        return True
-
-    @noPosargs
-    @permittedKwargs({})
-    def is_cross_build_method(self, args, kwargs):
-        return self.build.environment.is_cross_build()
-
-    @permittedKwargs({'native'})
-    def get_compiler_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('get_compiler_method must have one and only one argument.')
-        cname = args[0]
-        for_machine = Interpreter.machine_from_native_kwarg(kwargs)
-        clist = self.interpreter.coredata.compilers[for_machine]
-        if cname in clist:
-            return CompilerHolder(clist[cname], self.build.environment, self.interpreter.subproject)
-        raise InterpreterException('Tried to access compiler for unspecified language "%s".' % cname)
-
-    @noPosargs
-    @permittedKwargs({})
-    def is_unity_method(self, args, kwargs):
-        optval = self.interpreter.environment.coredata.get_builtin_option('unity')
-        if optval == 'on' or (optval == 'subprojects' and self.interpreter.is_subproject()):
-            return True
-        return False
-
-    @noPosargs
-    @permittedKwargs({})
-    def is_subproject_method(self, args, kwargs):
-        return self.interpreter.is_subproject()
-
-    @permittedKwargs({})
-    def install_dependency_manifest_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Must specify manifest install file name')
-        if not isinstance(args[0], str):
-            raise InterpreterException('Argument must be a string.')
-        self.build.dep_manifest_name = args[0]
-
-    @FeatureNew('meson.override_find_program', '0.46.0')
-    @permittedKwargs({})
-    def override_find_program_method(self, args, kwargs):
-        if len(args) != 2:
-            raise InterpreterException('Override needs two arguments')
-        name, exe = args
-        if not isinstance(name, str):
-            raise InterpreterException('First argument must be a string')
-        if hasattr(exe, 'held_object'):
-            exe = exe.held_object
-        if isinstance(exe, mesonlib.File):
-            abspath = exe.absolute_path(self.interpreter.environment.source_dir,
-                                        self.interpreter.environment.build_dir)
-            if not os.path.exists(abspath):
-                raise InterpreterException('Tried to override %s with a file that does not exist.' % name)
-            exe = OverrideProgram(abspath)
-        if not isinstance(exe, (dependencies.ExternalProgram, build.Executable)):
-            raise InterpreterException('Second argument must be an external program or executable.')
-        self.interpreter.add_find_program_override(name, exe)
-
-    @noPosargs
-    @permittedKwargs({})
-    def project_version_method(self, args, kwargs):
-        return self.build.dep_manifest[self.interpreter.active_projectname]['version']
-
-    @FeatureNew('meson.project_license()', '0.45.0')
-    @noPosargs
-    @permittedKwargs({})
-    def project_license_method(self, args, kwargs):
-        return self.build.dep_manifest[self.interpreter.active_projectname]['license']
-
-    @noPosargs
-    @permittedKwargs({})
-    def version_method(self, args, kwargs):
-        return coredata.version
-
-    @noPosargs
-    @permittedKwargs({})
-    def project_name_method(self, args, kwargs):
-        return self.interpreter.active_projectname
-
-    @noArgsFlattening
-    @permittedKwargs({})
-    def get_cross_property_method(self, args, kwargs):
-        if len(args) < 1 or len(args) > 2:
-            raise InterpreterException('Must have one or two arguments.')
-        propname = args[0]
-        if not isinstance(propname, str):
-            raise InterpreterException('Property name must be string.')
-        try:
-            props = self.interpreter.environment.properties.host
-            return props[propname]
-        except Exception:
-            if len(args) == 2:
-                return args[1]
-            raise InterpreterException('Unknown cross property: %s.' % propname)
-
-
-known_library_kwargs = (
-    build.known_shlib_kwargs |
-    build.known_stlib_kwargs
-)
-
-known_build_target_kwargs = (
-    known_library_kwargs |
-    build.known_exe_kwargs |
-    build.known_jar_kwargs |
-    {'target_type'}
-)
-
-_base_test_args = {'args', 'depends', 'env', 'should_fail', 'timeout', 'workdir', 'suite', 'priority', 'protocol'}
-
-permitted_kwargs = {'add_global_arguments': {'language', 'native'},
-                    'add_global_link_arguments': {'language', 'native'},
-                    'add_languages': {'required'},
-                    'add_project_link_arguments': {'language', 'native'},
-                    'add_project_arguments': {'language', 'native'},
-                    'add_test_setup': {'exe_wrapper', 'gdb', 'timeout_multiplier', 'env', 'is_default'},
-                    'benchmark': _base_test_args,
-                    'build_target': known_build_target_kwargs,
-                    'configure_file': {'input',
-                                       'output',
-                                       'configuration',
-                                       'command',
-                                       'copy',
-                                       'depfile',
-                                       'install_dir',
-                                       'install_mode',
-                                       'capture',
-                                       'install',
-                                       'format',
-                                       'output_format',
-                                       'encoding'},
-                    'custom_target': {'input',
-                                      'output',
-                                      'command',
-                                      'install',
-                                      'install_dir',
-                                      'install_mode',
-                                      'build_always',
-                                      'capture',
-                                      'depends',
-                                      'depend_files',
-                                      'depfile',
-                                      'build_by_default',
-                                      'build_always_stale',
-                                      'console'},
-                    'dependency': {'default_options',
-                                   'embed',
-                                   'fallback',
-                                   'language',
-                                   'main',
-                                   'method',
-                                   'modules',
-                                   'cmake_module_path',
-                                   'optional_modules',
-                                   'native',
-                                   'not_found_message',
-                                   'required',
-                                   'static',
-                                   'version',
-                                   'private_headers',
-                                   'cmake_args',
-                                   'include_type',
-                                   },
-                    'declare_dependency': {'include_directories',
-                                           'link_with',
-                                           'sources',
-                                           'dependencies',
-                                           'compile_args',
-                                           'link_args',
-                                           'link_whole',
-                                           'version',
-                                           },
-                    'executable': build.known_exe_kwargs,
-                    'find_program': {'required', 'native', 'version', 'dirs'},
-                    'generator': {'arguments',
-                                  'output',
-                                  'depends',
-                                  'depfile',
-                                  'capture',
-                                  'preserve_path_from'},
-                    'include_directories': {'is_system'},
-                    'install_data': {'install_dir', 'install_mode', 'rename', 'sources'},
-                    'install_headers': {'install_dir', 'install_mode', 'subdir'},
-                    'install_man': {'install_dir', 'install_mode'},
-                    'install_subdir': {'exclude_files', 'exclude_directories', 'install_dir', 'install_mode', 'strip_directory'},
-                    'jar': build.known_jar_kwargs,
-                    'project': {'version', 'meson_version', 'default_options', 'license', 'subproject_dir'},
-                    'run_command': {'check', 'capture', 'env'},
-                    'run_target': {'command', 'depends'},
-                    'shared_library': build.known_shlib_kwargs,
-                    'shared_module': build.known_shmod_kwargs,
-                    'static_library': build.known_stlib_kwargs,
-                    'both_libraries': known_library_kwargs,
-                    'library': known_library_kwargs,
-                    'subdir': {'if_found'},
-                    'subproject': {'version', 'default_options', 'required'},
-                    'test': set.union(_base_test_args, {'is_parallel'}),
-                    'vcs_tag': {'input', 'output', 'fallback', 'command', 'replace_string'},
-                    }
-
-
-class Interpreter(InterpreterBase):
-
-    def __init__(self, build, backend=None, subproject='', subdir='', subproject_dir='subprojects',
-                 modules = None, default_project_options=None, mock=False, ast=None):
-        super().__init__(build.environment.get_source_dir(), subdir)
-        self.an_unpicklable_object = mesonlib.an_unpicklable_object
-        self.build = build
-        self.environment = build.environment
-        self.coredata = self.environment.get_coredata()
-        self.backend = backend
-        self.subproject = subproject
-        self.summary = {}
-        if modules is None:
-            self.modules = {}
-        else:
-            self.modules = modules
-        # Subproject directory is usually the name of the subproject, but can
-        # be different for dependencies provided by wrap files.
-        self.subproject_directory_name = subdir.split(os.path.sep)[-1]
-        self.subproject_dir = subproject_dir
-        self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt')
-        if not mock and ast is None:
-            self.load_root_meson_file()
-            self.sanity_check_ast()
-        elif ast is not None:
-            self.ast = ast
-            self.sanity_check_ast()
-        self.builtin.update({'meson': MesonMain(build, self)})
-        self.generators = []
-        self.visited_subdirs = {}
-        self.project_args_frozen = False
-        self.global_args_frozen = False  # implies self.project_args_frozen
-        self.subprojects = {}
-        self.subproject_stack = []
-        self.configure_file_outputs = {}
-        # Passed from the outside, only used in subprojects.
-        if default_project_options:
-            self.default_project_options = default_project_options.copy()
-        else:
-            self.default_project_options = {}
-        self.project_default_options = {}
-        self.build_func_dict()
-        # build_def_files needs to be defined before parse_project is called
-        self.build_def_files = [os.path.join(self.subdir, environment.build_filename)]
-        if not mock:
-            self.parse_project()
-
-        # Re-initialize machine descriptions. We can do a better job now because we
-        # have the compilers needed to gain more knowledge, so wipe out old
-        # inference and start over.
-        machines = self.build.environment.machines.miss_defaulting()
-        machines.build = environment.detect_machine_info(self.coredata.compilers.build)
-        self.build.environment.machines = machines.default_missing()
-        assert self.build.environment.machines.build.cpu is not None
-        assert self.build.environment.machines.host.cpu is not None
-        assert self.build.environment.machines.target.cpu is not None
-
-        self.builtin['build_machine'] = \
-            MachineHolder(self.build.environment.machines.build)
-        self.builtin['host_machine'] = \
-            MachineHolder(self.build.environment.machines.host)
-        self.builtin['target_machine'] = \
-            MachineHolder(self.build.environment.machines.target)
-
-    def get_non_matching_default_options(self):
-        env = self.environment
-        for def_opt_name, def_opt_value in self.project_default_options.items():
-            for opts in env.coredata.get_all_options():
-                cur_opt_value = opts.get(def_opt_name)
-                if cur_opt_value is not None:
-                    def_opt_value = env.coredata.validate_option_value(def_opt_name, def_opt_value)
-                    if def_opt_value != cur_opt_value.value:
-                        yield (def_opt_name, def_opt_value, cur_opt_value)
-
-    def build_func_dict(self):
-        self.funcs.update({'add_global_arguments': self.func_add_global_arguments,
-                           'add_project_arguments': self.func_add_project_arguments,
-                           'add_global_link_arguments': self.func_add_global_link_arguments,
-                           'add_project_link_arguments': self.func_add_project_link_arguments,
-                           'add_test_setup': self.func_add_test_setup,
-                           'add_languages': self.func_add_languages,
-                           'alias_target': self.func_alias_target,
-                           'assert': self.func_assert,
-                           'benchmark': self.func_benchmark,
-                           'build_target': self.func_build_target,
-                           'configuration_data': self.func_configuration_data,
-                           'configure_file': self.func_configure_file,
-                           'custom_target': self.func_custom_target,
-                           'declare_dependency': self.func_declare_dependency,
-                           'dependency': self.func_dependency,
-                           'disabler': self.func_disabler,
-                           'environment': self.func_environment,
-                           'error': self.func_error,
-                           'executable': self.func_executable,
-                           'generator': self.func_generator,
-                           'gettext': self.func_gettext,
-                           'get_option': self.func_get_option,
-                           'get_variable': self.func_get_variable,
-                           'files': self.func_files,
-                           'find_library': self.func_find_library,
-                           'find_program': self.func_find_program,
-                           'include_directories': self.func_include_directories,
-                           'import': self.func_import,
-                           'install_data': self.func_install_data,
-                           'install_headers': self.func_install_headers,
-                           'install_man': self.func_install_man,
-                           'install_subdir': self.func_install_subdir,
-                           'is_disabler': self.func_is_disabler,
-                           'is_variable': self.func_is_variable,
-                           'jar': self.func_jar,
-                           'join_paths': self.func_join_paths,
-                           'library': self.func_library,
-                           'message': self.func_message,
-                           'warning': self.func_warning,
-                           'option': self.func_option,
-                           'project': self.func_project,
-                           'run_target': self.func_run_target,
-                           'run_command': self.func_run_command,
-                           'set_variable': self.func_set_variable,
-                           'subdir': self.func_subdir,
-                           'subdir_done': self.func_subdir_done,
-                           'subproject': self.func_subproject,
-                           'summary': self.func_summary,
-                           'shared_library': self.func_shared_lib,
-                           'shared_module': self.func_shared_module,
-                           'static_library': self.func_static_lib,
-                           'both_libraries': self.func_both_lib,
-                           'test': self.func_test,
-                           'vcs_tag': self.func_vcs_tag
-                           })
-        if 'MESON_UNIT_TEST' in os.environ:
-            self.funcs.update({'exception': self.func_exception})
-
-    def holderify(self, item):
-        if isinstance(item, list):
-            return [self.holderify(x) for x in item]
-        if isinstance(item, dict):
-            return {k: self.holderify(v) for k, v in item.items()}
-
-        if isinstance(item, build.CustomTarget):
-            return CustomTargetHolder(item, self)
-        elif isinstance(item, (int, str, bool)) or item is None:
-            return item
-        elif isinstance(item, build.Executable):
-            return ExecutableHolder(item, self)
-        elif isinstance(item, build.GeneratedList):
-            return GeneratedListHolder(item)
-        elif isinstance(item, build.RunTarget):
-            raise RuntimeError('This is not a pipe.')
-        elif isinstance(item, build.RunScript):
-            raise RuntimeError('Do not do this.')
-        elif isinstance(item, build.Data):
-            return DataHolder(item)
-        elif isinstance(item, dependencies.Dependency):
-            return DependencyHolder(item, self.subproject)
-        elif isinstance(item, dependencies.ExternalProgram):
-            return ExternalProgramHolder(item)
-        elif hasattr(item, 'held_object'):
-            return item
-        else:
-            raise InterpreterException('Module returned a value of unknown type.')
-
-    def process_new_values(self, invalues):
-        invalues = listify(invalues)
-        for v in invalues:
-            if isinstance(v, (RunTargetHolder, CustomTargetHolder, BuildTargetHolder)):
-                v = v.held_object
-
-            if isinstance(v, (build.BuildTarget, build.CustomTarget, build.RunTarget)):
-                self.add_target(v.name, v)
-            elif isinstance(v, list):
-                self.module_method_callback(v)
-            elif isinstance(v, build.GeneratedList):
-                pass
-            elif isinstance(v, build.RunScript):
-                self.build.install_scripts.append(v)
-            elif isinstance(v, build.Data):
-                self.build.data.append(v)
-            elif isinstance(v, dependencies.ExternalProgram):
-                return ExternalProgramHolder(v)
-            elif isinstance(v, dependencies.InternalDependency):
-                # FIXME: This is special cased and not ideal:
-                # The first source is our new VapiTarget, the rest are deps
-                self.process_new_values(v.sources[0])
-            elif hasattr(v, 'held_object'):
-                pass
-            elif isinstance(v, (int, str, bool)):
-                pass
-            else:
-                raise InterpreterException('Module returned a value of unknown type.')
-
-    def module_method_callback(self, return_object):
-        if not isinstance(return_object, ModuleReturnValue):
-            raise InterpreterException('Bug in module, it returned an invalid object')
-        invalues = return_object.new_objects
-        self.process_new_values(invalues)
-        return self.holderify(return_object.return_value)
-
-    def get_build_def_files(self):
-        return self.build_def_files
-
-    def add_build_def_file(self, f):
-        # Use relative path for files within source directory, and absolute path
-        # for system files. Skip files within build directory. Also skip not regular
-        # files (e.g. /dev/stdout) Normalize the path to avoid duplicates, this
-        # is especially important to convert '/' to '\' on Windows.
-        if isinstance(f, mesonlib.File):
-            if f.is_built:
-                return
-            f = os.path.normpath(f.relative_name())
-        elif os.path.isfile(f) and not f.startswith('/dev'):
-            srcdir = self.environment.get_source_dir()
-            builddir = self.environment.get_build_dir()
-            f = os.path.normpath(f)
-            rel_path = mesonlib.relpath(f, start=srcdir)
-            if not rel_path.startswith('..'):
-                f = rel_path
-            elif not mesonlib.relpath(f, start=builddir).startswith('..'):
-                return
-        else:
-            return
-        if f not in self.build_def_files:
-            self.build_def_files.append(f)
-
-    def get_variables(self):
-        return self.variables
-
-    def check_stdlibs(self):
-        for for_machine in MachineChoice:
-            props = self.build.environment.properties[for_machine]
-            for l in self.coredata.compilers[for_machine].keys():
-                try:
-                    di = mesonlib.stringlistify(props.get_stdlib(l))
-                    if len(di) != 2:
-                        raise InterpreterException('Stdlib definition for %s should have exactly two elements.'
-                                                   % l)
-                    projname, depname = di
-                    subproj = self.do_subproject(projname, 'meson', {})
-                    self.build.stdlibs.host[l] = subproj.get_variable_method([depname], {})
-                except KeyError:
-                    pass
-                except InvalidArguments:
-                    pass
-
-    @stringArgs
-    @noKwargs
-    def func_import(self, node, args, kwargs):
-        if len(args) != 1:
-            raise InvalidCode('Import takes one argument.')
-        modname = args[0]
-        if modname.startswith('unstable-'):
-            plainname = modname.split('-', 1)[1]
-            mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node)
-            modname = 'unstable_' + plainname
-        if modname not in self.modules:
-            try:
-                module = importlib.import_module('mesonbuild.modules.' + modname)
-            except ImportError:
-                raise InvalidArguments('Module "%s" does not exist' % (modname, ))
-            self.modules[modname] = module.initialize(self)
-        return ModuleHolder(modname, self.modules[modname], self)
-
-    @stringArgs
-    @noKwargs
-    def func_files(self, node, args, kwargs):
-        return [mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, fname) for fname in args]
-
-    @FeatureNewKwargs('declare_dependency', '0.46.0', ['link_whole'])
-    @permittedKwargs(permitted_kwargs['declare_dependency'])
-    @noPosargs
-    def func_declare_dependency(self, node, args, kwargs):
-        version = kwargs.get('version', self.project_version)
-        if not isinstance(version, str):
-            raise InterpreterException('Version must be a string.')
-        incs = self.extract_incdirs(kwargs)
-        libs = extract_as_list(kwargs, 'link_with', unholder=True)
-        libs_whole = extract_as_list(kwargs, 'link_whole', unholder=True)
-        sources = extract_as_list(kwargs, 'sources')
-        sources = listify(self.source_strings_to_files(sources), unholder=True)
-        deps = extract_as_list(kwargs, 'dependencies', unholder=True)
-        compile_args = mesonlib.stringlistify(kwargs.get('compile_args', []))
-        link_args = mesonlib.stringlistify(kwargs.get('link_args', []))
-        final_deps = []
-        for d in deps:
-            try:
-                d = d.held_object
-            except Exception:
-                pass
-            if not isinstance(d, (dependencies.Dependency, dependencies.ExternalLibrary, dependencies.InternalDependency)):
-                raise InterpreterException('Dependencies must be external deps')
-            final_deps.append(d)
-        for l in libs:
-            if isinstance(l, dependencies.Dependency):
-                raise InterpreterException('''Entries in "link_with" may only be self-built targets,
-external dependencies (including libraries) must go to "dependencies".''')
-        dep = dependencies.InternalDependency(version, incs, compile_args,
-                                              link_args, libs, libs_whole, sources, final_deps)
-        return DependencyHolder(dep, self.subproject)
-
-    @noKwargs
-    def func_assert(self, node, args, kwargs):
-        if len(args) == 1:
-            FeatureNew('assert function without message argument', '0.53.0').use(self.subproject)
-            value = args[0]
-            message = None
-        elif len(args) == 2:
-            value, message = args
-            if not isinstance(message, str):
-                raise InterpreterException('Assert message not a string.')
-        else:
-            raise InterpreterException('Assert takes between one and two arguments')
-        if not isinstance(value, bool):
-            raise InterpreterException('Assert value not bool.')
-        if not value:
-            if message is None:
-                from .ast import AstPrinter
-                printer = AstPrinter()
-                node.args.arguments[0].accept(printer)
-                message = printer.result
-            raise InterpreterException('Assert failed: ' + message)
-
-    def validate_arguments(self, args, argcount, arg_types):
-        if argcount is not None:
-            if argcount != len(args):
-                raise InvalidArguments('Expected %d arguments, got %d.' %
-                                       (argcount, len(args)))
-        for actual, wanted in zip(args, arg_types):
-            if wanted is not None:
-                if not isinstance(actual, wanted):
-                    raise InvalidArguments('Incorrect argument type.')
-
-    @FeatureNewKwargs('run_command', '0.50.0', ['env'])
-    @FeatureNewKwargs('run_command', '0.47.0', ['check', 'capture'])
-    @permittedKwargs(permitted_kwargs['run_command'])
-    def func_run_command(self, node, args, kwargs):
-        return self.run_command_impl(node, args, kwargs)
-
-    def run_command_impl(self, node, args, kwargs, in_builddir=False):
-        if len(args) < 1:
-            raise InterpreterException('Not enough arguments')
-        cmd, *cargs = args
-        capture = kwargs.get('capture', True)
-        srcdir = self.environment.get_source_dir()
-        builddir = self.environment.get_build_dir()
-
-        check = kwargs.get('check', False)
-        if not isinstance(check, bool):
-            raise InterpreterException('Check must be boolean.')
-
-        env = self.unpack_env_kwarg(kwargs)
-
-        m = 'must be a string, or the output of find_program(), files() '\
-            'or configure_file(), or a compiler object; not {!r}'
-        expanded_args = []
-        if isinstance(cmd, ExternalProgramHolder):
-            cmd = cmd.held_object
-            if isinstance(cmd, build.Executable):
-                progname = node.args.arguments[0].value
-                msg = 'Program {!r} was overridden with the compiled executable {!r}'\
-                      ' and therefore cannot be used during configuration'
-                raise InterpreterException(msg.format(progname, cmd.description()))
-            if not cmd.found():
-                raise InterpreterException('command {!r} not found or not executable'.format(cmd))
-        elif isinstance(cmd, CompilerHolder):
-            exelist = cmd.compiler.get_exelist()
-            cmd = exelist[0]
-            prog = ExternalProgram(cmd, silent=True)
-            if not prog.found():
-                raise InterpreterException('Program {!r} not found '
-                                           'or not executable'.format(cmd))
-            cmd = prog
-            expanded_args = exelist[1:]
-        else:
-            if isinstance(cmd, mesonlib.File):
-                cmd = cmd.absolute_path(srcdir, builddir)
-            elif not isinstance(cmd, str):
-                raise InterpreterException('First argument ' + m.format(cmd))
-            # Prefer scripts in the current source directory
-            search_dir = os.path.join(srcdir, self.subdir)
-            prog = ExternalProgram(cmd, silent=True, search_dir=search_dir)
-            if not prog.found():
-                raise InterpreterException('Program or command {!r} not found '
-                                           'or not executable'.format(cmd))
-            cmd = prog
-        for a in listify(cargs):
-            if isinstance(a, str):
-                expanded_args.append(a)
-            elif isinstance(a, mesonlib.File):
-                expanded_args.append(a.absolute_path(srcdir, builddir))
-            elif isinstance(a, ExternalProgramHolder):
-                expanded_args.append(a.held_object.get_path())
-            else:
-                raise InterpreterException('Arguments ' + m.format(a))
-        # If any file that was used as an argument to the command
-        # changes, we must re-run the configuration step.
-        self.add_build_def_file(cmd.get_path())
-        for a in expanded_args:
-            if not os.path.isabs(a):
-                a = os.path.join(builddir if in_builddir else srcdir, self.subdir, a)
-            self.add_build_def_file(a)
-        return RunProcess(cmd, expanded_args, env, srcdir, builddir, self.subdir,
-                          self.environment.get_build_command() + ['introspect'],
-                          in_builddir=in_builddir, check=check, capture=capture)
-
-    @stringArgs
-    def func_gettext(self, nodes, args, kwargs):
-        raise InterpreterException('Gettext() function has been moved to module i18n. Import it and use i18n.gettext() instead')
-
-    def func_option(self, nodes, args, kwargs):
-        raise InterpreterException('Tried to call option() in build description file. All options must be in the option file.')
-
-    @FeatureNewKwargs('subproject', '0.38.0', ['default_options'])
-    @permittedKwargs(permitted_kwargs['subproject'])
-    @stringArgs
-    def func_subproject(self, nodes, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Subproject takes exactly one argument')
-        dirname = args[0]
-        return self.do_subproject(dirname, 'meson', kwargs)
-
-    def disabled_subproject(self, dirname, feature=None):
-        sub = SubprojectHolder(None, self.subproject_dir, dirname)
-        if feature:
-            sub.disabled_feature = feature
-        self.subprojects[dirname] = sub
-        return sub
-
-    def do_subproject(self, dirname: str, method: str, kwargs):
-        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
-        if disabled:
-            mlog.log('Subproject', mlog.bold(dirname), ':', 'skipped: feature', mlog.bold(feature), 'disabled')
-            return self.disabled_subproject(dirname, feature)
-
-        default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
-        default_options = coredata.create_options_dict(default_options)
-        if dirname == '':
-            raise InterpreterException('Subproject dir name must not be empty.')
-        if dirname[0] == '.':
-            raise InterpreterException('Subproject dir name must not start with a period.')
-        if '..' in dirname:
-            raise InterpreterException('Subproject name must not contain a ".." path segment.')
-        if os.path.isabs(dirname):
-            raise InterpreterException('Subproject name must not be an absolute path.')
-        if has_path_sep(dirname):
-            mlog.warning('Subproject name has a path separator. This may cause unexpected behaviour.',
-                         location=self.current_node)
-        if dirname in self.subproject_stack:
-            fullstack = self.subproject_stack + [dirname]
-            incpath = ' => '.join(fullstack)
-            raise InvalidCode('Recursive include of subprojects: %s.' % incpath)
-        if dirname in self.subprojects:
-            subproject = self.subprojects[dirname]
-            if required and not subproject.found():
-                raise InterpreterException('Subproject "%s/%s" required but not found.' % (
-                                           self.subproject_dir, dirname))
-            return subproject
-
-        subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir)
-        r = wrap.Resolver(subproject_dir_abs, self.coredata.get_builtin_option('wrap_mode'))
-        try:
-            resolved = r.resolve(dirname, method)
-        except wrap.WrapException as e:
-            subprojdir = os.path.join(self.subproject_dir, r.directory)
-            if isinstance(e, wrap.WrapNotFoundException):
-                # if the reason subproject execution failed was because
-                # the directory doesn't exist, try to give some helpful
-                # advice if it's a nested subproject that needs
-                # promotion...
-                self.print_nested_info(dirname)
-            if not required:
-                mlog.log(e)
-                mlog.log('Subproject ', mlog.bold(subprojdir), 'is buildable:', mlog.red('NO'), '(disabling)')
-                return self.disabled_subproject(dirname)
-            raise e
-
-        subdir = os.path.join(self.subproject_dir, resolved)
-        subdir_abs = os.path.join(subproject_dir_abs, resolved)
-        os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True)
-        self.global_args_frozen = True
-
-        mlog.log()
-        with mlog.nested():
-            mlog.log('Executing subproject', mlog.bold(dirname), 'method', mlog.bold(method), '\n')
-        try:
-            if method == 'meson':
-                return self._do_subproject_meson(dirname, subdir, default_options, kwargs)
-            elif method == 'cmake':
-                return self._do_subproject_cmake(dirname, subdir, subdir_abs, default_options, kwargs)
-            else:
-                raise InterpreterException('The method {} is invalid for the subproject {}'.format(method, dirname))
-        # Invalid code is always an error
-        except InvalidCode:
-            raise
-        except Exception as e:
-            if not required:
-                with mlog.nested():
-                    # Suppress the 'ERROR:' prefix because this exception is not
-                    # fatal and VS CI treat any logs with "ERROR:" as fatal.
-                    mlog.exception(e, prefix=mlog.yellow('Exception:'))
-                mlog.log('\nSubproject', mlog.bold(dirname), 'is buildable:', mlog.red('NO'), '(disabling)')
-                return self.disabled_subproject(dirname)
-            raise e
-
-    def _do_subproject_meson(self, dirname, subdir, default_options, kwargs, ast=None, build_def_files=None):
-        with mlog.nested():
-            new_build = self.build.copy()
-            subi = Interpreter(new_build, self.backend, dirname, subdir, self.subproject_dir,
-                               self.modules, default_options, ast=ast)
-            subi.subprojects = self.subprojects
-
-            subi.subproject_stack = self.subproject_stack + [dirname]
-            current_active = self.active_projectname
-            subi.run()
-            mlog.log('Subproject', mlog.bold(dirname), 'finished.')
-
-        mlog.log()
-
-        if 'version' in kwargs:
-            pv = subi.project_version
-            wanted = kwargs['version']
-            if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]:
-                raise InterpreterException('Subproject %s version is %s but %s required.' % (dirname, pv, wanted))
-        self.active_projectname = current_active
-        self.subprojects.update(subi.subprojects)
-        self.subprojects[dirname] = SubprojectHolder(subi, self.subproject_dir, dirname)
-        # Duplicates are possible when subproject uses files from project root
-        if build_def_files:
-            self.build_def_files = list(set(self.build_def_files + build_def_files))
-        else:
-            self.build_def_files = list(set(self.build_def_files + subi.build_def_files))
-        self.build.merge(subi.build)
-        self.build.subprojects[dirname] = subi.project_version
-        self.summary.update(subi.summary)
-        return self.subprojects[dirname]
-
-    def _do_subproject_cmake(self, dirname, subdir, subdir_abs, default_options, kwargs):
-        with mlog.nested():
-            new_build = self.build.copy()
-            prefix = self.coredata.builtins['prefix'].value
-            cmake_options = mesonlib.stringlistify(kwargs.get('cmake_options', []))
-            cm_int = CMakeInterpreter(new_build, subdir, subdir_abs, prefix, new_build.environment, self.backend)
-            cm_int.initialise(cmake_options)
-            cm_int.analyse()
-
-            # Generate a meson ast and execute it with the normal do_subproject_meson
-            ast = cm_int.pretend_to_be_meson()
-
-            mlog.log()
-            with mlog.nested():
-                mlog.log('Processing generated meson AST')
-
-                # Debug print the generated meson file
-                from .ast import AstIndentationGenerator, AstPrinter
-                printer = AstPrinter()
-                ast.accept(AstIndentationGenerator())
-                ast.accept(printer)
-                printer.post_process()
-                meson_filename = os.path.join(self.build.environment.get_build_dir(), subdir, 'meson.build')
-                with open(meson_filename, "w") as f:
-                    f.write(printer.result)
-
-                mlog.log('Build file:', meson_filename)
-                mlog.cmd_ci_include(meson_filename)
-                mlog.log()
-
-            result = self._do_subproject_meson(dirname, subdir, default_options, kwargs, ast, cm_int.bs_files)
-            result.cm_interpreter = cm_int
-
-        mlog.log()
-        return result
-
-    def get_option_internal(self, optname):
-        for opts in chain(
-                [self.coredata.base_options, compilers.base_options, self.coredata.builtins],
-                self.coredata.get_prefixed_options_per_machine(self.coredata.builtins_per_machine),
-                self.coredata.get_prefixed_options_per_machine(self.coredata.compiler_options),
-        ):
-            v = opts.get(optname)
-            if v is not None:
-                return v
-
-        raw_optname = optname
-        if self.is_subproject():
-            optname = self.subproject + ':' + optname
-
-        try:
-            opt = self.coredata.user_options[optname]
-            if opt.yielding and ':' in optname and raw_optname in self.coredata.user_options:
-                popt = self.coredata.user_options[raw_optname]
-                if type(opt) is type(popt):
-                    opt = popt
-                else:
-                    # Get class name, then option type as a string
-                    opt_type = opt.__class__.__name__[4:][:-6].lower()
-                    popt_type = popt.__class__.__name__[4:][:-6].lower()
-                    # This is not a hard error to avoid dependency hell, the workaround
-                    # when this happens is to simply set the subproject's option directly.
-                    mlog.warning('Option {0!r} of type {1!r} in subproject {2!r} cannot yield '
-                                 'to parent option of type {3!r}, ignoring parent value. '
-                                 'Use -D{2}:{0}=value to set the value for this option manually'
-                                 '.'.format(raw_optname, opt_type, self.subproject, popt_type),
-                                 location=self.current_node)
-            return opt
-        except KeyError:
-            pass
-
-        raise InterpreterException('Tried to access unknown option "%s".' % optname)
-
-    @stringArgs
-    @noKwargs
-    def func_get_option(self, nodes, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Argument required for get_option.')
-        optname = args[0]
-        if ':' in optname:
-            raise InterpreterException('Having a colon in option name is forbidden, '
-                                       'projects are not allowed to directly access '
-                                       'options of other subprojects.')
-        opt = self.get_option_internal(optname)
-        if isinstance(opt, coredata.UserFeatureOption):
-            return FeatureOptionHolder(self.environment, optname, opt)
-        elif isinstance(opt, coredata.UserOption):
-            return opt.value
-        return opt
-
-    @noKwargs
-    def func_configuration_data(self, node, args, kwargs):
-        if len(args) > 1:
-            raise InterpreterException('configuration_data takes only one optional positional arguments')
-        elif len(args) == 1:
-            FeatureNew('configuration_data dictionary', '0.49.0').use(self.subproject)
-            initial_values = args[0]
-            if not isinstance(initial_values, dict):
-                raise InterpreterException('configuration_data first argument must be a dictionary')
-        else:
-            initial_values = {}
-        return ConfigurationDataHolder(self.subproject, initial_values)
-
-    def set_backend(self):
-        # The backend is already set when parsing subprojects
-        if self.backend is not None:
-            return
-        backend = self.coredata.get_builtin_option('backend')
-        from .backend import backends
-        self.backend = backends.get_backend_from_name(backend, self.build)
-
-        if self.backend is None:
-            raise InterpreterException('Unknown backend "%s".' % backend)
-        if backend != self.backend.name:
-            if self.backend.name.startswith('vs'):
-                mlog.log('Auto detected Visual Studio backend:', mlog.bold(self.backend.name))
-            self.coredata.set_builtin_option('backend', self.backend.name)
-
-        # Only init backend options on first invocation otherwise it would
-        # override values previously set from command line.
-        if self.environment.first_invocation:
-            self.coredata.init_backend_options(backend)
-
-        options = {k: v for k, v in self.environment.cmd_line_options.items() if k.startswith('backend_')}
-        self.coredata.set_options(options)
-
-    @stringArgs
-    @permittedKwargs(permitted_kwargs['project'])
-    def func_project(self, node, args, kwargs):
-        if len(args) < 1:
-            raise InvalidArguments('Not enough arguments to project(). Needs at least the project name.')
-        proj_name, *proj_langs = args
-        if ':' in proj_name:
-            raise InvalidArguments("Project name {!r} must not contain ':'".format(proj_name))
-
-        if 'meson_version' in kwargs:
-            cv = coredata.version
-            pv = kwargs['meson_version']
-            if not mesonlib.version_compare(cv, pv):
-                raise InterpreterException('Meson version is %s but project requires %s' % (cv, pv))
-
-        if os.path.exists(self.option_file):
-            oi = optinterpreter.OptionInterpreter(self.subproject)
-            oi.process(self.option_file)
-            self.coredata.merge_user_options(oi.options)
-
-        # Do not set default_options on reconfigure otherwise it would override
-        # values previously set from command line. That means that changing
-        # default_options in a project will trigger a reconfigure but won't
-        # have any effect.
-        self.project_default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
-        self.project_default_options = coredata.create_options_dict(self.project_default_options)
-        if self.environment.first_invocation:
-            default_options = self.project_default_options
-            default_options.update(self.default_project_options)
-        else:
-            default_options = {}
-        self.coredata.set_default_options(default_options, self.subproject, self.environment)
-
-        if not self.is_subproject():
-            self.build.project_name = proj_name
-        self.active_projectname = proj_name
-        self.project_version = kwargs.get('version', 'undefined')
-        if self.build.project_version is None:
-            self.build.project_version = self.project_version
-        proj_license = mesonlib.stringlistify(kwargs.get('license', 'unknown'))
-        self.build.dep_manifest[proj_name] = {'version': self.project_version,
-                                              'license': proj_license}
-        if self.subproject in self.build.projects:
-            raise InvalidCode('Second call to project().')
-        if not self.is_subproject() and 'subproject_dir' in kwargs:
-            spdirname = kwargs['subproject_dir']
-            if not isinstance(spdirname, str):
-                raise InterpreterException('Subproject_dir must be a string')
-            if os.path.isabs(spdirname):
-                raise InterpreterException('Subproject_dir must not be an absolute path.')
-            if spdirname.startswith('.'):
-                raise InterpreterException('Subproject_dir must not begin with a period.')
-            if '..' in spdirname:
-                raise InterpreterException('Subproject_dir must not contain a ".." segment.')
-            self.subproject_dir = spdirname
-
-        self.build.subproject_dir = self.subproject_dir
-
-        mesonlib.project_meson_versions[self.subproject] = ''
-        if 'meson_version' in kwargs:
-            mesonlib.project_meson_versions[self.subproject] = kwargs['meson_version']
-
-        self.build.projects[self.subproject] = proj_name
-        mlog.log('Project name:', mlog.bold(proj_name))
-        mlog.log('Project version:', mlog.bold(self.project_version))
-        self.add_languages(proj_langs, True)
-        self.set_backend()
-        if not self.is_subproject():
-            self.check_stdlibs()
-
-    @permittedKwargs(permitted_kwargs['add_languages'])
-    @stringArgs
-    def func_add_languages(self, node, args, kwargs):
-        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
-        if disabled:
-            for lang in sorted(args, key=compilers.sort_clink):
-                mlog.log('Compiler for language', mlog.bold(lang), 'skipped: feature', mlog.bold(feature), 'disabled')
-            return False
-        return self.add_languages(args, required)
-
-    def get_message_string_arg(self, node):
-        # reduce arguments again to avoid flattening posargs
-        (posargs, _) = self.reduce_arguments(node.args)
-        if len(posargs) != 1:
-            raise InvalidArguments('Expected 1 argument, got %d' % len(posargs))
-
-        arg = posargs[0]
-        if isinstance(arg, list):
-            argstr = stringifyUserArguments(arg)
-        elif isinstance(arg, dict):
-            argstr = stringifyUserArguments(arg)
-        elif isinstance(arg, str):
-            argstr = arg
-        elif isinstance(arg, int):
-            argstr = str(arg)
-        else:
-            raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.')
-
-        return argstr
-
-    @noKwargs
-    def func_message(self, node, args, kwargs):
-        argstr = self.get_message_string_arg(node)
-        self.message_impl(argstr)
-
-    def message_impl(self, argstr):
-        mlog.log(mlog.bold('Message:'), argstr)
-
-    @noArgsFlattening
-    @permittedKwargs({'section', 'bool_yn'})
-    @FeatureNew('summary', '0.53.0')
-    def func_summary(self, node, args, kwargs):
-        if len(args) == 1:
-            if not isinstance(args[0], dict):
-                raise InterpreterException('Summary first argument must be dictionary.')
-            values = args[0]
-        elif len(args) == 2:
-            if not isinstance(args[0], str):
-                raise InterpreterException('Summary first argument must be string.')
-            values = {args[0]: args[1]}
-        else:
-            raise InterpreterException('Summary accepts at most 2 arguments.')
-        section = kwargs.get('section', '')
-        if not isinstance(section, str):
-            raise InterpreterException('Summary\'s section keyword argument must be string.')
-        self.summary_impl(section, values, kwargs)
-
-    def summary_impl(self, section, values, kwargs):
-        if self.subproject not in self.summary:
-            self.summary[self.subproject] = Summary(self.active_projectname, self.project_version)
-        self.summary[self.subproject].add_section(section, values, kwargs)
-
-    def _print_summary(self):
-        # Add automatic 'Supbrojects' section in main project.
-        all_subprojects = collections.OrderedDict()
-        for name, subp in sorted(self.subprojects.items()):
-            value = subp.found()
-            if not value and hasattr(subp, 'disabled_feature'):
-                value = 'Feature {!r} disabled'.format(subp.disabled_feature)
-            all_subprojects[name] = value
-        if all_subprojects:
-            self.summary_impl('Subprojects', all_subprojects, {'bool_yn': True})
-        # Print all summaries, main project last.
-        mlog.log('')  # newline
-        main_summary = self.summary.pop('', None)
-        for _, summary in sorted(self.summary.items()):
-            summary.dump()
-        if main_summary:
-            main_summary.dump()
-
-    @FeatureNew('warning', '0.44.0')
-    @noKwargs
-    def func_warning(self, node, args, kwargs):
-        argstr = self.get_message_string_arg(node)
-        mlog.warning(argstr, location=node)
-
-    @noKwargs
-    def func_error(self, node, args, kwargs):
-        self.validate_arguments(args, 1, [str])
-        raise InterpreterException('Problem encountered: ' + args[0])
-
-    @noKwargs
-    def func_exception(self, node, args, kwargs):
-        self.validate_arguments(args, 0, [])
-        raise Exception()
-
-    def add_languages(self, args: T.Sequence[str], required: bool) -> bool:
-        success = self.add_languages_for(args, required, MachineChoice.BUILD)
-        success &= self.add_languages_for(args, required, MachineChoice.HOST)
-        if not self.coredata.is_cross_build():
-            self.coredata.copy_build_options_from_regular_ones()
-        return success
-
-    def add_languages_for(self, args, required, for_machine: MachineChoice):
-        success = True
-        for lang in sorted(args, key=compilers.sort_clink):
-            lang = lang.lower()
-            clist = self.coredata.compilers[for_machine]
-            machine_name = for_machine.get_lower_case_name()
-            if lang in clist:
-                comp = clist[lang]
-            else:
-                try:
-                    comp = self.environment.detect_compiler_for(lang, for_machine)
-                    if comp is None:
-                        raise InvalidArguments('Tried to use unknown language "%s".' % lang)
-                    comp.sanity_check(self.environment.get_scratch_dir(), self.environment)
-                except Exception:
-                    if not required:
-                        mlog.log('Compiler for language',
-                                 mlog.bold(lang), 'for the', machine_name,
-                                 'machine not found.')
-                        success = False
-                        continue
-                    else:
-                        raise
-
-            if for_machine == MachineChoice.HOST or self.environment.is_cross_build():
-                logger_fun = mlog.log
-            else:
-                logger_fun = mlog.debug
-            logger_fun(comp.get_display_language(), 'compiler for the', machine_name, 'machine:',
-                       mlog.bold(' '.join(comp.get_exelist())), comp.get_version_string())
-            if comp.linker is not None:
-                logger_fun(comp.get_display_language(), 'linker for the', machine_name, 'machine:',
-                           mlog.bold(' '.join(comp.linker.get_exelist())), comp.linker.id, comp.linker.version)
-            self.build.ensure_static_linker(comp)
-
-        langs = self.coredata.compilers[for_machine].keys()
-        if 'vala' in langs:
-            if 'c' not in langs:
-                raise InterpreterException('Compiling Vala requires C. Add C to your project languages and rerun Meson.')
-
-        return success
-
-    def program_from_file_for(self, for_machine, prognames, silent):
-        bins = self.environment.binaries[for_machine]
-        for p in prognames:
-            if hasattr(p, 'held_object'):
-                p = p.held_object
-            if isinstance(p, mesonlib.File):
-                continue # Always points to a local (i.e. self generated) file.
-            if not isinstance(p, str):
-                raise InterpreterException('Executable name must be a string')
-            prog = ExternalProgram.from_bin_list(bins, p)
-            if prog.found():
-                return ExternalProgramHolder(prog)
-        return None
-
-    def program_from_system(self, args, search_dirs, silent=False):
-        # Search for scripts relative to current subdir.
-        # Do not cache found programs because find_program('foobar')
-        # might give different results when run from different source dirs.
-        source_dir = os.path.join(self.environment.get_source_dir(), self.subdir)
-        for exename in args:
-            if isinstance(exename, mesonlib.File):
-                if exename.is_built:
-                    search_dir = os.path.join(self.environment.get_build_dir(),
-                                              exename.subdir)
-                else:
-                    search_dir = os.path.join(self.environment.get_source_dir(),
-                                              exename.subdir)
-                exename = exename.fname
-                extra_search_dirs = []
-            elif isinstance(exename, str):
-                search_dir = source_dir
-                extra_search_dirs = search_dirs
-            else:
-                raise InvalidArguments('find_program only accepts strings and '
-                                       'files, not {!r}'.format(exename))
-            extprog = dependencies.ExternalProgram(exename, search_dir=search_dir,
-                                                   extra_search_dirs=extra_search_dirs,
-                                                   silent=silent)
-            progobj = ExternalProgramHolder(extprog)
-            if progobj.found():
-                return progobj
-
-    def program_from_overrides(self, command_names, silent=False):
-        for name in command_names:
-            if not isinstance(name, str):
-                continue
-            if name in self.build.find_overrides:
-                exe = self.build.find_overrides[name]
-                if not silent:
-                    mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'),
-                             '(overridden: %s)' % exe.description())
-                return ExternalProgramHolder(exe)
-        return None
-
-    def store_name_lookups(self, command_names):
-        for name in command_names:
-            if isinstance(name, str):
-                self.build.searched_programs.add(name)
-
-    def add_find_program_override(self, name, exe):
-        if name in self.build.searched_programs:
-            raise InterpreterException('Tried to override finding of executable "%s" which has already been found.'
-                                       % name)
-        if name in self.build.find_overrides:
-            raise InterpreterException('Tried to override executable "%s" which has already been overridden.'
-                                       % name)
-        self.build.find_overrides[name] = exe
-
-    # TODO update modules to always pass `for_machine`. It is bad-form to assume
-    # the host machine.
-    def find_program_impl(self, args, for_machine: MachineChoice = MachineChoice.HOST,
-                          required=True, silent=True, wanted='', search_dirs=None):
-        if not isinstance(args, list):
-            args = [args]
-
-        progobj = self.program_from_overrides(args, silent=silent)
-        if progobj is None:
-            progobj = self.program_from_file_for(for_machine, args, silent=silent)
-        if progobj is None:
-            progobj = self.program_from_system(args, search_dirs, silent=silent)
-        if progobj is None and args[0].endswith('python3'):
-            prog = dependencies.ExternalProgram('python3', mesonlib.python_command, silent=True)
-            progobj = ExternalProgramHolder(prog)
-        if required and (progobj is None or not progobj.found()):
-            raise InvalidArguments('Program(s) {!r} not found or not executable'.format(args))
-        if progobj is None:
-            return ExternalProgramHolder(dependencies.NonExistingExternalProgram())
-        # Only store successful lookups
-        self.store_name_lookups(args)
-        if wanted:
-            version = progobj.get_version(self)
-            is_found, not_found, found = mesonlib.version_compare_many(version, wanted)
-            if not is_found:
-                mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'),
-                         'found {!r} but need:'.format(version),
-                         ', '.join(["'{}'".format(e) for e in not_found]))
-                if required:
-                    m = 'Invalid version of program, need {!r} {!r} found {!r}.'
-                    raise InvalidArguments(m.format(progobj.get_name(), not_found, version))
-                return ExternalProgramHolder(dependencies.NonExistingExternalProgram())
-        return progobj
-
-    @FeatureNewKwargs('find_program', '0.53.0', ['dirs'])
-    @FeatureNewKwargs('find_program', '0.52.0', ['version'])
-    @FeatureNewKwargs('find_program', '0.49.0', ['disabler'])
-    @disablerIfNotFound
-    @permittedKwargs(permitted_kwargs['find_program'])
-    def func_find_program(self, node, args, kwargs):
-        if not args:
-            raise InterpreterException('No program name specified.')
-
-        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
-        if disabled:
-            mlog.log('Program', mlog.bold(' '.join(args)), 'skipped: feature', mlog.bold(feature), 'disabled')
-            return ExternalProgramHolder(dependencies.NonExistingExternalProgram())
-
-        search_dirs = extract_search_dirs(kwargs)
-        wanted = mesonlib.stringlistify(kwargs.get('version', []))
-        for_machine = self.machine_from_native_kwarg(kwargs)
-        return self.find_program_impl(args, for_machine, required=required,
-                                      silent=False, wanted=wanted,
-                                      search_dirs=search_dirs)
-
-    def func_find_library(self, node, args, kwargs):
-        raise InvalidCode('find_library() is removed, use meson.get_compiler(\'name\').find_library() instead.\n'
-                          'Look here for documentation: http://mesonbuild.com/Reference-manual.html#compiler-object\n'
-                          'Look here for example: http://mesonbuild.com/howtox.html#add-math-library-lm-portably\n'
-                          )
-
-    def _find_cached_dep(self, name, kwargs):
-        # Check if we want this as a build-time / build machine or runt-time /
-        # host machine dep.
-        for_machine = self.machine_from_native_kwarg(kwargs)
-
-        identifier = dependencies.get_dep_identifier(name, kwargs)
-        cached_dep = self.coredata.deps[for_machine].get(identifier)
-        if cached_dep:
-            if not cached_dep.found():
-                mlog.log('Dependency', mlog.bold(name),
-                         'found:', mlog.red('NO'), mlog.blue('(cached)'))
-                return identifier, cached_dep
-
-            # Verify the cached dep version match
-            wanted_vers = mesonlib.stringlistify(kwargs.get('version', []))
-            found_vers = cached_dep.get_version()
-            if not wanted_vers or mesonlib.version_compare_many(found_vers, wanted_vers)[0]:
-                info = [mlog.blue('(cached)')]
-                if found_vers:
-                    info = [mlog.normal_cyan(found_vers), *info]
-                mlog.log('Dependency', mlog.bold(name),
-                         'found:', mlog.green('YES'), *info)
-                return identifier, cached_dep
-
-        return identifier, None
-
-    @staticmethod
-    def check_subproject_version(wanted, found):
-        if not wanted:
-            return True
-        if found == 'undefined' or not mesonlib.version_compare_many(found, wanted)[0]:
-            return False
-        return True
-
-    def notfound_dependency(self):
-        return DependencyHolder(NotFoundDependency(self.environment), self.subproject)
-
-    def get_subproject_dep(self, display_name, dirname, varname, kwargs):
-        dep = self.notfound_dependency()
-        try:
-            subproject = self.subprojects[dirname]
-            if subproject.found():
-                dep = self.subprojects[dirname].get_variable_method([varname], {})
-        except InvalidArguments:
-            pass
-
-        if not isinstance(dep, DependencyHolder):
-            raise InvalidCode('Fetched variable {!r} in the subproject {!r} is '
-                              'not a dependency object.'.format(varname, dirname))
-
-        required = kwargs.get('required', True)
-        wanted = mesonlib.stringlistify(kwargs.get('version', []))
-        subproj_path = os.path.join(self.subproject_dir, dirname)
-
-        if not dep.found():
-            if required:
-                raise DependencyException('Could not find dependency {} in subproject {}'
-                                          ''.format(varname, dirname))
-            # If the dependency is not required, don't raise an exception
-            mlog.log('Dependency', mlog.bold(display_name), 'from subproject',
-                     mlog.bold(subproj_path), 'found:', mlog.red('NO'))
-            return dep
-
-        found = dep.held_object.get_version()
-        if not self.check_subproject_version(wanted, found):
-            if required:
-                raise DependencyException('Version {} of subproject dependency {} already '
-                                          'cached, requested incompatible version {} for '
-                                          'dep {}'.format(found, dirname, wanted, display_name))
-
-            mlog.log('Dependency', mlog.bold(display_name), 'from subproject',
-                     mlog.bold(subproj_path), 'found:', mlog.red('NO'),
-                     'found', mlog.normal_cyan(found), 'but need:',
-                     mlog.bold(', '.join(["'{}'".format(e) for e in wanted])))
-            return self.notfound_dependency()
-
-        found = mlog.normal_cyan(found) if found else None
-        mlog.log('Dependency', mlog.bold(display_name), 'from subproject',
-                 mlog.bold(subproj_path), 'found:', mlog.green('YES'), found)
-        return dep
-
-    def _handle_featurenew_dependencies(self, name):
-        'Do a feature check on dependencies used by this subproject'
-        if name == 'mpi':
-            FeatureNew('MPI Dependency', '0.42.0').use(self.subproject)
-        elif name == 'pcap':
-            FeatureNew('Pcap Dependency', '0.42.0').use(self.subproject)
-        elif name == 'vulkan':
-            FeatureNew('Vulkan Dependency', '0.42.0').use(self.subproject)
-        elif name == 'libwmf':
-            FeatureNew('LibWMF Dependency', '0.44.0').use(self.subproject)
-        elif name == 'openmp':
-            FeatureNew('OpenMP Dependency', '0.46.0').use(self.subproject)
-
-    @FeatureNewKwargs('dependency', '0.52.0', ['include_type'])
-    @FeatureNewKwargs('dependency', '0.50.0', ['not_found_message', 'cmake_module_path', 'cmake_args'])
-    @FeatureNewKwargs('dependency', '0.49.0', ['disabler'])
-    @FeatureNewKwargs('dependency', '0.40.0', ['method'])
-    @FeatureNewKwargs('dependency', '0.38.0', ['default_options'])
-    @disablerIfNotFound
-    @permittedKwargs(permitted_kwargs['dependency'])
-    def func_dependency(self, node, args, kwargs):
-        self.validate_arguments(args, 1, [str])
-        name = args[0]
-        display_name = name if name else '(anonymous)'
-        not_found_message = kwargs.get('not_found_message', '')
-        if not isinstance(not_found_message, str):
-            raise InvalidArguments('The not_found_message must be a string.')
-        try:
-            d = self.dependency_impl(name, display_name, kwargs)
-        except Exception:
-            if not_found_message:
-                self.message_impl(not_found_message)
-            raise
-        if not d.found() and not_found_message:
-            self.message_impl(not_found_message)
-        return d
-
-    def dependency_impl(self, name, display_name, kwargs):
-        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
-        if disabled:
-            mlog.log('Dependency', mlog.bold(display_name), 'skipped: feature', mlog.bold(feature), 'disabled')
-            return self.notfound_dependency()
-
-        has_fallback = 'fallback' in kwargs
-        if 'default_options' in kwargs and not has_fallback:
-            mlog.warning('The "default_options" keyworg argument does nothing without a "fallback" keyword argument.',
-                         location=self.current_node)
-
-        # writing just "dependency('')" is an error, because it can only fail
-        if name == '' and required and not has_fallback:
-            raise InvalidArguments('Dependency is both required and not-found')
-
-        if '<' in name or '>' in name or '=' in name:
-            raise InvalidArguments('Characters <, > and = are forbidden in dependency names. To specify'
-                                   'version\n requirements use the \'version\' keyword argument instead.')
-
-        identifier, cached_dep = self._find_cached_dep(name, kwargs)
-        if cached_dep:
-            if required and not cached_dep.found():
-                m = 'Dependency {!r} was already checked and was not found'
-                raise DependencyException(m.format(display_name))
-            return DependencyHolder(cached_dep, self.subproject)
-
-        # If the dependency has already been configured, possibly by
-        # a higher level project, try to use it first.
-        if has_fallback:
-            dirname, varname = self.get_subproject_infos(kwargs)
-            if dirname in self.subprojects:
-                return self.get_subproject_dep(name, dirname, varname, kwargs)
-
-        wrap_mode = self.coredata.get_builtin_option('wrap_mode')
-        forcefallback = wrap_mode == WrapMode.forcefallback and has_fallback
-        if name != '' and not forcefallback:
-            self._handle_featurenew_dependencies(name)
-            kwargs['required'] = required and not has_fallback
-            dep = dependencies.find_external_dependency(name, self.environment, kwargs)
-
-            kwargs['required'] = required
-            # Only store found-deps in the cache
-            # Never add fallback deps to self.coredata.deps since we
-            # cannot cache them. They must always be evaluated else
-            # we won't actually read all the build files.
-            if dep.found():
-                for_machine = self.machine_from_native_kwarg(kwargs)
-                self.coredata.deps[for_machine].put(identifier, dep)
-                return DependencyHolder(dep, self.subproject)
-
-        if has_fallback:
-            return self.dependency_fallback(display_name, kwargs)
-
-        return self.notfound_dependency()
-
-    @FeatureNew('disabler', '0.44.0')
-    @noKwargs
-    @noPosargs
-    def func_disabler(self, node, args, kwargs):
-        return Disabler()
-
-    def print_nested_info(self, dependency_name):
-        message = ['Dependency', mlog.bold(dependency_name), 'not found but it is available in a sub-subproject.\n' +
-                   'To use it in the current project, promote it by going in the project source\n'
-                   'root and issuing']
-        sprojs = mesonlib.detect_subprojects('subprojects', self.source_root)
-        if dependency_name not in sprojs:
-            return
-        found = sprojs[dependency_name]
-        if len(found) > 1:
-            message.append('one of the following commands:')
-        else:
-            message.append('the following command:')
-        command_templ = '\nmeson wrap promote {}'
-        for l in found:
-            message.append(mlog.bold(command_templ.format(l[len(self.source_root) + 1:])))
-        mlog.warning(*message, location=self.current_node)
-
-    def get_subproject_infos(self, kwargs):
-        fbinfo = kwargs['fallback']
-        check_stringlist(fbinfo)
-        if len(fbinfo) != 2:
-            raise InterpreterException('Fallback info must have exactly two items.')
-        return fbinfo
-
-    def dependency_fallback(self, display_name, kwargs):
-        if self.coredata.get_builtin_option('wrap_mode') == WrapMode.nofallback:
-            mlog.log('Not looking for a fallback subproject for the dependency',
-                     mlog.bold(display_name), 'because:\nUse of fallback'
-                     'dependencies is disabled.')
-            return self.notfound_dependency()
-        elif self.coredata.get_builtin_option('wrap_mode') == WrapMode.forcefallback:
-            mlog.log('Looking for a fallback subproject for the dependency',
-                     mlog.bold(display_name), 'because:\nUse of fallback dependencies is forced.')
-        else:
-            mlog.log('Looking for a fallback subproject for the dependency',
-                     mlog.bold(display_name))
-        dirname, varname = self.get_subproject_infos(kwargs)
-        sp_kwargs = {
-            'default_options': kwargs.get('default_options', []),
-            'required': kwargs.get('required', True),
-        }
-        self.do_subproject(dirname, 'meson', sp_kwargs)
-        return self.get_subproject_dep(display_name, dirname, varname, kwargs)
-
-    @FeatureNewKwargs('executable', '0.42.0', ['implib'])
-    @permittedKwargs(permitted_kwargs['executable'])
-    def func_executable(self, node, args, kwargs):
-        return self.build_target(node, args, kwargs, ExecutableHolder)
-
-    @permittedKwargs(permitted_kwargs['static_library'])
-    def func_static_lib(self, node, args, kwargs):
-        return self.build_target(node, args, kwargs, StaticLibraryHolder)
-
-    @permittedKwargs(permitted_kwargs['shared_library'])
-    def func_shared_lib(self, node, args, kwargs):
-        holder = self.build_target(node, args, kwargs, SharedLibraryHolder)
-        holder.held_object.shared_library_only = True
-        return holder
-
-    @permittedKwargs(permitted_kwargs['both_libraries'])
-    def func_both_lib(self, node, args, kwargs):
-        return self.build_both_libraries(node, args, kwargs)
-
-    @FeatureNew('shared_module', '0.37.0')
-    @permittedKwargs(permitted_kwargs['shared_module'])
-    def func_shared_module(self, node, args, kwargs):
-        return self.build_target(node, args, kwargs, SharedModuleHolder)
-
-    @permittedKwargs(permitted_kwargs['library'])
-    def func_library(self, node, args, kwargs):
-        return self.build_library(node, args, kwargs)
-
-    @permittedKwargs(permitted_kwargs['jar'])
-    def func_jar(self, node, args, kwargs):
-        return self.build_target(node, args, kwargs, JarHolder)
-
-    @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options'])
-    @permittedKwargs(permitted_kwargs['build_target'])
-    def func_build_target(self, node, args, kwargs):
-        if 'target_type' not in kwargs:
-            raise InterpreterException('Missing target_type keyword argument')
-        target_type = kwargs.pop('target_type')
-        if target_type == 'executable':
-            return self.build_target(node, args, kwargs, ExecutableHolder)
-        elif target_type == 'shared_library':
-            return self.build_target(node, args, kwargs, SharedLibraryHolder)
-        elif target_type == 'shared_module':
-            FeatureNew('build_target(target_type: \'shared_module\')',
-                       '0.51.0').use(self.subproject)
-            return self.build_target(node, args, kwargs, SharedModuleHolder)
-        elif target_type == 'static_library':
-            return self.build_target(node, args, kwargs, StaticLibraryHolder)
-        elif target_type == 'both_libraries':
-            return self.build_both_libraries(node, args, kwargs)
-        elif target_type == 'library':
-            return self.build_library(node, args, kwargs)
-        elif target_type == 'jar':
-            return self.build_target(node, args, kwargs, JarHolder)
-        else:
-            raise InterpreterException('Unknown target_type.')
-
-    @permittedKwargs(permitted_kwargs['vcs_tag'])
-    def func_vcs_tag(self, node, args, kwargs):
-        if 'input' not in kwargs or 'output' not in kwargs:
-            raise InterpreterException('Keyword arguments input and output must exist')
-        if 'fallback' not in kwargs:
-            FeatureNew('T.Optional fallback in vcs_tag', '0.41.0').use(self.subproject)
-        fallback = kwargs.pop('fallback', self.project_version)
-        if not isinstance(fallback, str):
-            raise InterpreterException('Keyword argument fallback must be a string.')
-        replace_string = kwargs.pop('replace_string', '@VCS_TAG@')
-        regex_selector = '(.*)' # default regex selector for custom command: use complete output
-        vcs_cmd = kwargs.get('command', None)
-        if vcs_cmd and not isinstance(vcs_cmd, list):
-            vcs_cmd = [vcs_cmd]
-        source_dir = os.path.normpath(os.path.join(self.environment.get_source_dir(), self.subdir))
-        if vcs_cmd:
-            # Is the command an executable in path or maybe a script in the source tree?
-            vcs_cmd[0] = shutil.which(vcs_cmd[0]) or os.path.join(source_dir, vcs_cmd[0])
-        else:
-            vcs = mesonlib.detect_vcs(source_dir)
-            if vcs:
-                mlog.log('Found %s repository at %s' % (vcs['name'], vcs['wc_dir']))
-                vcs_cmd = vcs['get_rev'].split()
-                regex_selector = vcs['rev_regex']
-            else:
-                vcs_cmd = [' '] # executing this cmd will fail in vcstagger.py and force to use the fallback string
-        # vcstagger.py parameters: infile, outfile, fallback, source_dir, replace_string, regex_selector, command...
-        kwargs['command'] = self.environment.get_build_command() + \
-            ['--internal',
-             'vcstagger',
-             '@INPUT0@',
-             '@OUTPUT0@',
-             fallback,
-             source_dir,
-             replace_string,
-             regex_selector] + vcs_cmd
-        kwargs.setdefault('build_by_default', True)
-        kwargs.setdefault('build_always_stale', True)
-        return self._func_custom_target_impl(node, [kwargs['output']], kwargs)
-
-    @FeatureNew('subdir_done', '0.46.0')
-    @stringArgs
-    def func_subdir_done(self, node, args, kwargs):
-        if len(kwargs) > 0:
-            raise InterpreterException('exit does not take named arguments')
-        if len(args) > 0:
-            raise InterpreterException('exit does not take any arguments')
-        raise SubdirDoneRequest()
-
-    @stringArgs
-    @FeatureNewKwargs('custom_target', '0.48.0', ['console'])
-    @FeatureNewKwargs('custom_target', '0.47.0', ['install_mode', 'build_always_stale'])
-    @FeatureNewKwargs('custom_target', '0.40.0', ['build_by_default'])
-    @permittedKwargs(permitted_kwargs['custom_target'])
-    def func_custom_target(self, node, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('custom_target: Only one positional argument is allowed, and it must be a string name')
-        if 'depfile' in kwargs and ('@BASENAME@' in kwargs['depfile'] or '@PLAINNAME@' in kwargs['depfile']):
-            FeatureNew('substitutions in custom_target depfile', '0.47.0').use(self.subproject)
-        return self._func_custom_target_impl(node, args, kwargs)
-
-    def _func_custom_target_impl(self, node, args, kwargs):
-        'Implementation-only, without FeatureNew checks, for internal use'
-        name = args[0]
-        kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs)
-        if 'input' in kwargs:
-            try:
-                kwargs['input'] = self.source_strings_to_files(extract_as_list(kwargs, 'input'))
-            except mesonlib.MesonException:
-                mlog.warning('''Custom target input \'%s\' can\'t be converted to File object(s).
-This will become a hard error in the future.''' % kwargs['input'], location=self.current_node)
-        tg = CustomTargetHolder(build.CustomTarget(name, self.subdir, self.subproject, kwargs, backend=self.backend), self)
-        self.add_target(name, tg.held_object)
-        return tg
-
-    @permittedKwargs(permitted_kwargs['run_target'])
-    def func_run_target(self, node, args, kwargs):
-        if len(args) > 1:
-            raise InvalidCode('Run_target takes only one positional argument: the target name.')
-        elif len(args) == 1:
-            if 'command' not in kwargs:
-                raise InterpreterException('Missing "command" keyword argument')
-            all_args = extract_as_list(kwargs, 'command')
-            deps = extract_as_list(kwargs, 'depends', unholder=True)
-        else:
-            raise InterpreterException('Run_target needs at least one positional argument.')
-
-        cleaned_args = []
-        for i in listify(all_args, unholder=True):
-            if not isinstance(i, (str, build.BuildTarget, build.CustomTarget, dependencies.ExternalProgram, mesonlib.File)):
-                mlog.debug('Wrong type:', str(i))
-                raise InterpreterException('Invalid argument to run_target.')
-            if isinstance(i, dependencies.ExternalProgram) and not i.found():
-                raise InterpreterException('Tried to use non-existing executable {!r}'.format(i.name))
-            cleaned_args.append(i)
-        name = args[0]
-        if not isinstance(name, str):
-            raise InterpreterException('First argument must be a string.')
-        cleaned_deps = []
-        for d in deps:
-            if not isinstance(d, (build.BuildTarget, build.CustomTarget)):
-                raise InterpreterException('Depends items must be build targets.')
-            cleaned_deps.append(d)
-        command, *cmd_args = cleaned_args
-        tg = RunTargetHolder(build.RunTarget(name, command, cmd_args, cleaned_deps, self.subdir, self.subproject), self)
-        self.add_target(name, tg.held_object)
-        full_name = (self.subproject, name)
-        assert(full_name not in self.build.run_target_names)
-        self.build.run_target_names.add(full_name)
-        return tg
-
-    @FeatureNew('alias_target', '0.52.0')
-    @noKwargs
-    def func_alias_target(self, node, args, kwargs):
-        if len(args) < 2:
-            raise InvalidCode('alias_target takes at least 2 arguments.')
-        name = args[0]
-        if not isinstance(name, str):
-            raise InterpreterException('First argument must be a string.')
-        deps = listify(args[1:], unholder=True)
-        for d in deps:
-            if not isinstance(d, (build.BuildTarget, build.CustomTarget)):
-                raise InterpreterException('Depends items must be build targets.')
-        tg = RunTargetHolder(build.AliasTarget(name, deps, self.subdir, self.subproject), self)
-        self.add_target(name, tg.held_object)
-        return tg
-
-    @permittedKwargs(permitted_kwargs['generator'])
-    def func_generator(self, node, args, kwargs):
-        gen = GeneratorHolder(self, args, kwargs)
-        self.generators.append(gen)
-        return gen
-
-    @FeatureNewKwargs('benchmark', '0.46.0', ['depends'])
-    @FeatureNewKwargs('benchmark', '0.52.0', ['priority'])
-    @permittedKwargs(permitted_kwargs['benchmark'])
-    def func_benchmark(self, node, args, kwargs):
-        # is_parallel isn't valid here, so make sure it isn't passed
-        if 'is_parallel' in kwargs:
-            del kwargs['is_parallel']
-        self.add_test(node, args, kwargs, False)
-
-    @FeatureNewKwargs('test', '0.46.0', ['depends'])
-    @FeatureNewKwargs('test', '0.52.0', ['priority'])
-    @permittedKwargs(permitted_kwargs['test'])
-    def func_test(self, node, args, kwargs):
-        self.add_test(node, args, kwargs, True)
-
-    def unpack_env_kwarg(self, kwargs) -> build.EnvironmentVariables:
-        envlist = kwargs.get('env', EnvironmentVariablesHolder())
-        if isinstance(envlist, EnvironmentVariablesHolder):
-            env = envlist.held_object
-        elif isinstance(envlist, dict):
-            FeatureNew('environment dictionary', '0.52.0').use(self.subproject)
-            env = EnvironmentVariablesHolder(envlist)
-            env = env.held_object
-        else:
-            envlist = listify(envlist)
-            # Convert from array to environment object
-            env = EnvironmentVariablesHolder(envlist)
-            env = env.held_object
-        return env
-
-    def add_test(self, node, args, kwargs, is_base_test):
-        if len(args) != 2:
-            raise InterpreterException('Incorrect number of arguments')
-        if not isinstance(args[0], str):
-            raise InterpreterException('First argument of test must be a string.')
-        exe = args[1]
-        if not isinstance(exe, (ExecutableHolder, JarHolder, ExternalProgramHolder)):
-            if isinstance(exe, mesonlib.File):
-                exe = self.func_find_program(node, args[1], {})
-            else:
-                raise InterpreterException('Second argument must be executable.')
-        par = kwargs.get('is_parallel', True)
-        if not isinstance(par, bool):
-            raise InterpreterException('Keyword argument is_parallel must be a boolean.')
-        cmd_args = extract_as_list(kwargs, 'args', unholder=True)
-        for i in cmd_args:
-            if not isinstance(i, (str, mesonlib.File, build.Target)):
-                raise InterpreterException('Command line arguments must be strings, files or targets.')
-        env = self.unpack_env_kwarg(kwargs)
-        should_fail = kwargs.get('should_fail', False)
-        if not isinstance(should_fail, bool):
-            raise InterpreterException('Keyword argument should_fail must be a boolean.')
-        timeout = kwargs.get('timeout', 30)
-        if 'workdir' in kwargs:
-            workdir = kwargs['workdir']
-            if not isinstance(workdir, str):
-                raise InterpreterException('Workdir keyword argument must be a string.')
-            if not os.path.isabs(workdir):
-                raise InterpreterException('Workdir keyword argument must be an absolute path.')
-        else:
-            workdir = None
-        if not isinstance(timeout, int):
-            raise InterpreterException('Timeout must be an integer.')
-        protocol = kwargs.get('protocol', 'exitcode')
-        if protocol not in ('exitcode', 'tap'):
-            raise InterpreterException('Protocol must be "exitcode" or "tap".')
-        suite = []
-        prj = self.subproject if self.is_subproject() else self.build.project_name
-        for s in mesonlib.stringlistify(kwargs.get('suite', '')):
-            if len(s) > 0:
-                s = ':' + s
-            suite.append(prj.replace(' ', '_').replace(':', '_') + s)
-        depends = extract_as_list(kwargs, 'depends', unholder=True)
-        for dep in depends:
-            if not isinstance(dep, (build.CustomTarget, build.BuildTarget)):
-                raise InterpreterException('Depends items must be build targets.')
-        priority = kwargs.get('priority', 0)
-        if not isinstance(priority, int):
-            raise InterpreterException('Keyword argument priority must be an integer.')
-        t = Test(args[0], prj, suite, exe.held_object, depends, par, cmd_args,
-                 env, should_fail, timeout, workdir, protocol, priority)
-        if is_base_test:
-            self.build.tests.append(t)
-            mlog.debug('Adding test', mlog.bold(args[0], True))
-        else:
-            self.build.benchmarks.append(t)
-            mlog.debug('Adding benchmark', mlog.bold(args[0], True))
-
-    @FeatureNewKwargs('install_headers', '0.47.0', ['install_mode'])
-    @permittedKwargs(permitted_kwargs['install_headers'])
-    def func_install_headers(self, node, args, kwargs):
-        source_files = self.source_strings_to_files(args)
-        kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs)
-        h = Headers(source_files, kwargs)
-        self.build.headers.append(h)
-        return h
-
-    @FeatureNewKwargs('install_man', '0.47.0', ['install_mode'])
-    @permittedKwargs(permitted_kwargs['install_man'])
-    def func_install_man(self, node, args, kwargs):
-        fargs = self.source_strings_to_files(args)
-        kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs)
-        m = Man(fargs, kwargs)
-        self.build.man.append(m)
-        return m
-
-    @FeatureNewKwargs('subdir', '0.44.0', ['if_found'])
-    @permittedKwargs(permitted_kwargs['subdir'])
-    def func_subdir(self, node, args, kwargs):
-        self.validate_arguments(args, 1, [str])
-        mesonlib.check_direntry_issues(args)
-        if '..' in args[0]:
-            raise InvalidArguments('Subdir contains ..')
-        if self.subdir == '' and args[0] == self.subproject_dir:
-            raise InvalidArguments('Must not go into subprojects dir with subdir(), use subproject() instead.')
-        if self.subdir == '' and args[0].startswith('meson-'):
-            raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().')
-        for i in mesonlib.extract_as_list(kwargs, 'if_found'):
-            if not hasattr(i, 'found_method'):
-                raise InterpreterException('Object used in if_found does not have a found method.')
-            if not i.found_method([], {}):
-                return
-        prev_subdir = self.subdir
-        subdir = os.path.join(prev_subdir, args[0])
-        if os.path.isabs(subdir):
-            raise InvalidArguments('Subdir argument must be a relative path.')
-        absdir = os.path.join(self.environment.get_source_dir(), subdir)
-        symlinkless_dir = os.path.realpath(absdir)
-        if symlinkless_dir in self.visited_subdirs:
-            raise InvalidArguments('Tried to enter directory "%s", which has already been visited.'
-                                   % subdir)
-        self.visited_subdirs[symlinkless_dir] = True
-        self.subdir = subdir
-        os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True)
-        buildfilename = os.path.join(self.subdir, environment.build_filename)
-        self.build_def_files.append(buildfilename)
-        absname = os.path.join(self.environment.get_source_dir(), buildfilename)
-        if not os.path.isfile(absname):
-            self.subdir = prev_subdir
-            raise InterpreterException('Non-existent build file {!r}'.format(buildfilename))
-        with open(absname, encoding='utf8') as f:
-            code = f.read()
-        assert(isinstance(code, str))
-        try:
-            codeblock = mparser.Parser(code, self.subdir).parse()
-        except mesonlib.MesonException as me:
-            me.file = buildfilename
-            raise me
-        try:
-            self.evaluate_codeblock(codeblock)
-        except SubdirDoneRequest:
-            pass
-        self.subdir = prev_subdir
-
-    def _get_kwarg_install_mode(self, kwargs):
-        if kwargs.get('install_mode', None) is None:
-            return None
-        install_mode = []
-        mode = mesonlib.typeslistify(kwargs.get('install_mode', []), (str, int))
-        for m in mode:
-            # We skip any arguments that are set to `false`
-            if m is False:
-                m = None
-            install_mode.append(m)
-        if len(install_mode) > 3:
-            raise InvalidArguments('Keyword argument install_mode takes at '
-                                   'most 3 arguments.')
-        if len(install_mode) > 0 and install_mode[0] is not None and \
-           not isinstance(install_mode[0], str):
-            raise InvalidArguments('Keyword argument install_mode requires the '
-                                   'permissions arg to be a string or false')
-        return FileMode(*install_mode)
-
-    @FeatureNewKwargs('install_data', '0.46.0', ['rename'])
-    @FeatureNewKwargs('install_data', '0.38.0', ['install_mode'])
-    @permittedKwargs(permitted_kwargs['install_data'])
-    def func_install_data(self, node, args, kwargs):
-        kwsource = mesonlib.stringlistify(kwargs.get('sources', []))
-        raw_sources = args + kwsource
-        sources = []
-        source_strings = []
-        for s in raw_sources:
-            if isinstance(s, mesonlib.File):
-                sources.append(s)
-            elif isinstance(s, str):
-                source_strings.append(s)
-            else:
-                raise InvalidArguments('Argument {!r} must be string or file.'.format(s))
-        sources += self.source_strings_to_files(source_strings)
-        install_dir = kwargs.get('install_dir', None)
-        if not isinstance(install_dir, (str, type(None))):
-            raise InvalidArguments('Keyword argument install_dir not a string.')
-        install_mode = self._get_kwarg_install_mode(kwargs)
-        rename = kwargs.get('rename', None)
-        data = DataHolder(build.Data(sources, install_dir, install_mode, rename))
-        self.build.data.append(data.held_object)
-        return data
-
-    @FeatureNewKwargs('install_subdir', '0.42.0', ['exclude_files', 'exclude_directories'])
-    @FeatureNewKwargs('install_subdir', '0.38.0', ['install_mode'])
-    @permittedKwargs(permitted_kwargs['install_subdir'])
-    @stringArgs
-    def func_install_subdir(self, node, args, kwargs):
-        if len(args) != 1:
-            raise InvalidArguments('Install_subdir requires exactly one argument.')
-        subdir = args[0]
-        if 'install_dir' not in kwargs:
-            raise InvalidArguments('Missing keyword argument install_dir')
-        install_dir = kwargs['install_dir']
-        if not isinstance(install_dir, str):
-            raise InvalidArguments('Keyword argument install_dir not a string.')
-        if 'strip_directory' in kwargs:
-            if not isinstance(kwargs['strip_directory'], bool):
-                raise InterpreterException('"strip_directory" keyword must be a boolean.')
-            strip_directory = kwargs['strip_directory']
-        else:
-            strip_directory = False
-        if 'exclude_files' in kwargs:
-            exclude = extract_as_list(kwargs, 'exclude_files')
-            for f in exclude:
-                if not isinstance(f, str):
-                    raise InvalidArguments('Exclude argument not a string.')
-                elif os.path.isabs(f):
-                    raise InvalidArguments('Exclude argument cannot be absolute.')
-            exclude_files = set(exclude)
-        else:
-            exclude_files = set()
-        if 'exclude_directories' in kwargs:
-            exclude = extract_as_list(kwargs, 'exclude_directories')
-            for d in exclude:
-                if not isinstance(d, str):
-                    raise InvalidArguments('Exclude argument not a string.')
-                elif os.path.isabs(d):
-                    raise InvalidArguments('Exclude argument cannot be absolute.')
-            exclude_directories = set(exclude)
-        else:
-            exclude_directories = set()
-        exclude = (exclude_files, exclude_directories)
-        install_mode = self._get_kwarg_install_mode(kwargs)
-        idir = InstallDir(self.subdir, subdir, install_dir, install_mode, exclude, strip_directory)
-        self.build.install_dirs.append(idir)
-        return idir
-
-    @FeatureNewKwargs('configure_file', '0.47.0', ['copy', 'output_format', 'install_mode', 'encoding'])
-    @FeatureNewKwargs('configure_file', '0.46.0', ['format'])
-    @FeatureNewKwargs('configure_file', '0.41.0', ['capture'])
-    @FeatureNewKwargs('configure_file', '0.50.0', ['install'])
-    @FeatureNewKwargs('configure_file', '0.52.0', ['depfile'])
-    @permittedKwargs(permitted_kwargs['configure_file'])
-    def func_configure_file(self, node, args, kwargs):
-        if len(args) > 0:
-            raise InterpreterException("configure_file takes only keyword arguments.")
-        if 'output' not in kwargs:
-            raise InterpreterException('Required keyword argument "output" not defined.')
-        actions = set(['configuration', 'command', 'copy']).intersection(kwargs.keys())
-        if len(actions) == 0:
-            raise InterpreterException('Must specify an action with one of these '
-                                       'keyword arguments: \'configuration\', '
-                                       '\'command\', or \'copy\'.')
-        elif len(actions) == 2:
-            raise InterpreterException('Must not specify both {!r} and {!r} '
-                                       'keyword arguments since they are '
-                                       'mutually exclusive.'.format(*actions))
-        elif len(actions) == 3:
-            raise InterpreterException('Must specify one of {!r}, {!r}, and '
-                                       '{!r} keyword arguments since they are '
-                                       'mutually exclusive.'.format(*actions))
-        if 'capture' in kwargs:
-            if not isinstance(kwargs['capture'], bool):
-                raise InterpreterException('"capture" keyword must be a boolean.')
-            if 'command' not in kwargs:
-                raise InterpreterException('"capture" keyword requires "command" keyword.')
-
-        if 'format' in kwargs:
-            fmt = kwargs['format']
-            if not isinstance(fmt, str):
-                raise InterpreterException('"format" keyword must be a string.')
-        else:
-            fmt = 'meson'
-
-        if fmt not in ('meson', 'cmake', 'cmake@'):
-            raise InterpreterException('"format" possible values are "meson", "cmake" or "cmake@".')
-
-        if 'output_format' in kwargs:
-            output_format = kwargs['output_format']
-            if not isinstance(output_format, str):
-                raise InterpreterException('"output_format" keyword must be a string.')
-        else:
-            output_format = 'c'
-
-        if output_format not in ('c', 'nasm'):
-            raise InterpreterException('"format" possible values are "c" or "nasm".')
-
-        if 'depfile' in kwargs:
-            depfile = kwargs['depfile']
-            if not isinstance(depfile, str):
-                raise InterpreterException('depfile file name must be a string')
-        else:
-            depfile = None
-
-        # Validate input
-        inputs = self.source_strings_to_files(extract_as_list(kwargs, 'input'))
-        inputs_abs = []
-        for f in inputs:
-            if isinstance(f, mesonlib.File):
-                inputs_abs.append(f.absolute_path(self.environment.source_dir,
-                                                  self.environment.build_dir))
-                self.add_build_def_file(f)
-            else:
-                raise InterpreterException('Inputs can only be strings or file objects')
-        # Validate output
-        output = kwargs['output']
-        if not isinstance(output, str):
-            raise InterpreterException('Output file name must be a string')
-        if inputs_abs:
-            values = mesonlib.get_filenames_templates_dict(inputs_abs, None)
-            outputs = mesonlib.substitute_values([output], values)
-            output = outputs[0]
-            if depfile:
-                depfile = mesonlib.substitute_values([depfile], values)[0]
-        ofile_rpath = os.path.join(self.subdir, output)
-        if ofile_rpath in self.configure_file_outputs:
-            mesonbuildfile = os.path.join(self.subdir, 'meson.build')
-            current_call = "{}:{}".format(mesonbuildfile, self.current_lineno)
-            first_call = "{}:{}".format(mesonbuildfile, self.configure_file_outputs[ofile_rpath])
-            mlog.warning('Output file', mlog.bold(ofile_rpath, True), 'for configure_file() at', current_call, 'overwrites configure_file() output at', first_call)
-        else:
-            self.configure_file_outputs[ofile_rpath] = self.current_lineno
-        if os.path.dirname(output) != '':
-            raise InterpreterException('Output file name must not contain a subdirectory.')
-        (ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output))
-        ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname)
-        # Perform the appropriate action
-        if 'configuration' in kwargs:
-            conf = kwargs['configuration']
-            if isinstance(conf, dict):
-                FeatureNew('configure_file.configuration dictionary', '0.49.0').use(self.subproject)
-                conf = ConfigurationDataHolder(self.subproject, conf)
-            elif not isinstance(conf, ConfigurationDataHolder):
-                raise InterpreterException('Argument "configuration" is not of type configuration_data')
-            mlog.log('Configuring', mlog.bold(output), 'using configuration')
-            if len(inputs) > 1:
-                raise InterpreterException('At most one input file can given in configuration mode')
-            if inputs:
-                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.held_object,
-                                          fmt, file_encoding)
-                if missing_variables:
-                    var_list = ", ".join(map(repr, sorted(missing_variables)))
-                    mlog.warning(
-                        "The variable(s) %s in the input file '%s' are not "
-                        "present in the given configuration data." % (
-                            var_list, inputs[0]), location=node)
-                if confdata_useless:
-                    ifbase = os.path.basename(inputs_abs[0])
-                    mlog.warning('Got an empty configuration_data() object and found no '
-                                 'substitutions in the input file {!r}. If you want to '
-                                 'copy a file to the build dir, use the \'copy:\' keyword '
-                                 'argument added in 0.47.0'.format(ifbase), location=node)
-            else:
-                mesonlib.dump_conf_header(ofile_abs, conf.held_object, output_format)
-            conf.mark_used()
-        elif 'command' in kwargs:
-            if len(inputs) > 1:
-                FeatureNew('multiple inputs in configure_file()', '0.52.0').use(self.subproject)
-            # We use absolute paths for input and output here because the cwd
-            # that the command is run from is 'unspecified', so it could change.
-            # Currently it's builddir/subdir for in_builddir else srcdir/subdir.
-            values = mesonlib.get_filenames_templates_dict(inputs_abs, [ofile_abs])
-            if depfile:
-                depfile = os.path.join(self.environment.get_scratch_dir(), depfile)
-                values['@DEPFILE@'] = depfile
-            # Substitute @INPUT@, @OUTPUT@, etc here.
-            cmd = mesonlib.substitute_values(kwargs['command'], values)
-            mlog.log('Configuring', mlog.bold(output), 'with command')
-            res = self.run_command_impl(node, cmd,  {}, True)
-            if res.returncode != 0:
-                raise InterpreterException('Running configure command failed.\n%s\n%s' %
-                                           (res.stdout, res.stderr))
-            if 'capture' in kwargs and kwargs['capture']:
-                dst_tmp = ofile_abs + '~'
-                file_encoding = kwargs.setdefault('encoding', 'utf-8')
-                with open(dst_tmp, 'w', encoding=file_encoding) as f:
-                    f.writelines(res.stdout)
-                if inputs_abs:
-                    shutil.copymode(inputs_abs[0], dst_tmp)
-                mesonlib.replace_if_different(ofile_abs, dst_tmp)
-            if depfile:
-                mlog.log('Reading depfile:', mlog.bold(depfile))
-                with open(depfile, 'r') as f:
-                    df = DepFile(f.readlines())
-                    deps = df.get_all_dependencies(ofile_fname)
-                    for dep in deps:
-                        self.add_build_def_file(dep)
-
-        elif 'copy' in kwargs:
-            if len(inputs_abs) != 1:
-                raise InterpreterException('Exactly one input file must be given in copy mode')
-            os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
-            shutil.copyfile(inputs_abs[0], ofile_abs)
-            shutil.copystat(inputs_abs[0], ofile_abs)
-        else:
-            # Not reachable
-            raise AssertionError
-        # Install file if requested, we check for the empty string
-        # for backwards compatibility. That was the behaviour before
-        # 0.45.0 so preserve it.
-        idir = kwargs.get('install_dir', '')
-        if idir is False:
-            idir = ''
-            mlog.deprecation('Please use the new `install:` kwarg instead of passing '
-                             '`false` to `install_dir:`', location=node)
-        if not isinstance(idir, str):
-            if isinstance(idir, list) and len(idir) == 0:
-                mlog.deprecation('install_dir: kwarg must be a string and not an empty array. '
-                                 'Please use the install: kwarg to enable or disable installation. '
-                                 'This will be a hard error in the next release.')
-            else:
-                raise InterpreterException('"install_dir" must be a string')
-        install = kwargs.get('install', idir != '')
-        if not isinstance(install, bool):
-            raise InterpreterException('"install" must be a boolean')
-        if install:
-            if not idir:
-                raise InterpreterException('"install_dir" must be specified '
-                                           'when "install" in a configure_file '
-                                           'is true')
-            cfile = mesonlib.File.from_built_file(ofile_path, ofile_fname)
-            install_mode = self._get_kwarg_install_mode(kwargs)
-            self.build.data.append(build.Data([cfile], idir, install_mode))
-        return mesonlib.File.from_built_file(self.subdir, output)
-
-    def extract_incdirs(self, kwargs):
-        prospectives = listify(kwargs.get('include_directories', []), unholder=True)
-        result = []
-        for p in prospectives:
-            if isinstance(p, build.IncludeDirs):
-                result.append(p)
-            elif isinstance(p, str):
-                result.append(self.build_incdir_object([p]).held_object)
-            else:
-                raise InterpreterException('Include directory objects can only be created from strings or include directories.')
-        return result
-
-    @permittedKwargs(permitted_kwargs['include_directories'])
-    @stringArgs
-    def func_include_directories(self, node, args, kwargs):
-        return self.build_incdir_object(args, kwargs.get('is_system', False))
-
-    def build_incdir_object(self, incdir_strings, is_system=False):
-        if not isinstance(is_system, bool):
-            raise InvalidArguments('Is_system must be boolean.')
-        src_root = self.environment.get_source_dir()
-        build_root = self.environment.get_build_dir()
-        absbase_src = os.path.join(src_root, self.subdir)
-        absbase_build = os.path.join(build_root, self.subdir)
-
-        for a in incdir_strings:
-            if a.startswith(src_root):
-                raise InvalidArguments('''Tried to form an absolute path to a source dir. You should not do that but use
-relative paths instead.
-
-To get include path to any directory relative to the current dir do
-
-incdir = include_directories(dirname)
-
-After this incdir will contain both the current source dir as well as the
-corresponding build dir. It can then be used in any subdirectory and
-Meson will take care of all the busywork to make paths work.
-
-Dirname can even be '.' to mark the current directory. Though you should
-remember that the current source and build directories are always
-put in the include directories by default so you only need to do
-include_directories('.') if you intend to use the result in a
-different subdirectory.
-''')
-            absdir_src = os.path.join(absbase_src, a)
-            absdir_build = os.path.join(absbase_build, a)
-            if not os.path.isdir(absdir_src) and not os.path.isdir(absdir_build):
-                raise InvalidArguments('Include dir %s does not exist.' % a)
-        i = IncludeDirsHolder(build.IncludeDirs(self.subdir, incdir_strings, is_system))
-        return i
-
-    @permittedKwargs(permitted_kwargs['add_test_setup'])
-    @stringArgs
-    def func_add_test_setup(self, node, args, kwargs):
-        if len(args) != 1:
-            raise InterpreterException('Add_test_setup needs one argument for the setup name.')
-        setup_name = args[0]
-        if re.fullmatch('([_a-zA-Z][_0-9a-zA-Z]*:)?[_a-zA-Z][_0-9a-zA-Z]*', setup_name) is None:
-            raise InterpreterException('Setup name may only contain alphanumeric characters.')
-        if ":" not in setup_name:
-            setup_name = (self.subproject if self.subproject else self.build.project_name) + ":" + setup_name
-        try:
-            inp = extract_as_list(kwargs, 'exe_wrapper', unholder=True)
-            exe_wrapper = []
-            for i in inp:
-                if isinstance(i, str):
-                    exe_wrapper.append(i)
-                elif isinstance(i, dependencies.ExternalProgram):
-                    if not i.found():
-                        raise InterpreterException('Tried to use non-found executable.')
-                    exe_wrapper += i.get_command()
-                else:
-                    raise InterpreterException('Exe wrapper can only contain strings or external binaries.')
-        except KeyError:
-            exe_wrapper = None
-        gdb = kwargs.get('gdb', False)
-        if not isinstance(gdb, bool):
-            raise InterpreterException('Gdb option must be a boolean')
-        timeout_multiplier = kwargs.get('timeout_multiplier', 1)
-        if not isinstance(timeout_multiplier, int):
-            raise InterpreterException('Timeout multiplier must be a number.')
-        is_default = kwargs.get('is_default', False)
-        if not isinstance(is_default, bool):
-            raise InterpreterException('is_default option must be a boolean')
-        if is_default:
-            if self.build.test_setup_default_name is not None:
-                raise InterpreterException('\'%s\' is already set as default. '
-                                           'is_default can be set to true only once' % self.build.test_setup_default_name)
-            self.build.test_setup_default_name = setup_name
-        env = self.unpack_env_kwarg(kwargs)
-        self.build.test_setups[setup_name] = build.TestSetup(exe_wrapper, gdb, timeout_multiplier, env)
-
-    @permittedKwargs(permitted_kwargs['add_global_arguments'])
-    @stringArgs
-    def func_add_global_arguments(self, node, args, kwargs):
-        for_machine = self.machine_from_native_kwarg(kwargs)
-        self.add_global_arguments(node, self.build.global_args[for_machine], args, kwargs)
-
-    @permittedKwargs(permitted_kwargs['add_global_link_arguments'])
-    @stringArgs
-    def func_add_global_link_arguments(self, node, args, kwargs):
-        for_machine = self.machine_from_native_kwarg(kwargs)
-        self.add_global_arguments(node, self.build.global_link_args[for_machine], args, kwargs)
-
-    @permittedKwargs(permitted_kwargs['add_project_arguments'])
-    @stringArgs
-    def func_add_project_arguments(self, node, args, kwargs):
-        for_machine = self.machine_from_native_kwarg(kwargs)
-        self.add_project_arguments(node, self.build.projects_args[for_machine], args, kwargs)
-
-    @permittedKwargs(permitted_kwargs['add_project_link_arguments'])
-    @stringArgs
-    def func_add_project_link_arguments(self, node, args, kwargs):
-        for_machine = self.machine_from_native_kwarg(kwargs)
-        self.add_project_arguments(node, self.build.projects_link_args[for_machine], args, kwargs)
-
-    def warn_about_builtin_args(self, args):
-        warnargs = ('/W1', '/W2', '/W3', '/W4', '/Wall', '-Wall', '-Wextra', '-Wpedantic')
-        optargs = ('-O0', '-O2', '-O3', '-Os', '/O1', '/O2', '/Os')
-        for arg in args:
-            if arg in warnargs:
-                mlog.warning('Consider using the built-in warning_level option instead of using "{}".'.format(arg),
-                             location=self.current_node)
-            elif arg in optargs:
-                mlog.warning('Consider using the built-in optimization level instead of using "{}".'.format(arg),
-                             location=self.current_node)
-            elif arg == '-g':
-                mlog.warning('Consider using the built-in debug option instead of using "{}".'.format(arg),
-                             location=self.current_node)
-            elif arg == '-pipe':
-                mlog.warning("You don't need to add -pipe, Meson will use it automatically when it is available.",
-                             location=self.current_node)
-            elif arg.startswith('-fsanitize'):
-                mlog.warning('Consider using the built-in option for sanitizers instead of using "{}".'.format(arg),
-                             location=self.current_node)
-            elif arg.startswith('-std=') or arg.startswith('/std:'):
-                mlog.warning('Consider using the built-in option for language standard version instead of using "{}".'.format(arg),
-                             location=self.current_node)
-
-    def add_global_arguments(self, node, argsdict, args, kwargs):
-        if self.is_subproject():
-            msg = 'Function \'{}\' cannot be used in subprojects because ' \
-                  'there is no way to make that reliable.\nPlease only call ' \
-                  'this if is_subproject() returns false. Alternatively, ' \
-                  'define a variable that\ncontains your language-specific ' \
-                  'arguments and add it to the appropriate *_args kwarg ' \
-                  'in each target.'.format(node.func_name)
-            raise InvalidCode(msg)
-        frozen = self.project_args_frozen or self.global_args_frozen
-        self.add_arguments(node, argsdict, frozen, args, kwargs)
-
-    def add_project_arguments(self, node, argsdict, args, kwargs):
-        if self.subproject not in argsdict:
-            argsdict[self.subproject] = {}
-        self.add_arguments(node, argsdict[self.subproject],
-                           self.project_args_frozen, args, kwargs)
-
-    def add_arguments(self, node, argsdict, args_frozen, args, kwargs):
-        if args_frozen:
-            msg = 'Tried to use \'{}\' after a build target has been declared.\n' \
-                  'This is not permitted. Please declare all ' \
-                  'arguments before your targets.'.format(node.func_name)
-            raise InvalidCode(msg)
-
-        if 'language' not in kwargs:
-            raise InvalidCode('Missing language definition in {}'.format(node.func_name))
-
-        self.warn_about_builtin_args(args)
-
-        for lang in mesonlib.stringlistify(kwargs['language']):
-            lang = lang.lower()
-            argsdict[lang] = argsdict.get(lang, []) + args
-
-    @noKwargs
-    @noArgsFlattening
-    def func_environment(self, node, args, kwargs):
-        if len(args) > 1:
-            raise InterpreterException('environment takes only one optional positional arguments')
-        elif len(args) == 1:
-            FeatureNew('environment positional arguments', '0.52.0').use(self.subproject)
-            initial_values = args[0]
-            if not isinstance(initial_values, dict) and not isinstance(initial_values, list):
-                raise InterpreterException('environment first argument must be a dictionary or a list')
-        else:
-            initial_values = {}
-        return EnvironmentVariablesHolder(initial_values)
-
-    @stringArgs
-    @noKwargs
-    def func_join_paths(self, node, args, kwargs):
-        return self.join_path_strings(args)
-
-    def run(self):
-        super().run()
-        mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets))))
-        FeatureNew.report(self.subproject)
-        FeatureDeprecated.report(self.subproject)
-        if not self.is_subproject():
-            self.print_extra_warnings()
-        if self.subproject == '':
-            self._print_summary()
-
-    def print_extra_warnings(self):
-        # TODO cross compilation
-        for c in self.coredata.compilers.host.values():
-            if c.get_id() == 'clang':
-                self.check_clang_asan_lundef()
-                break
-
-    def check_clang_asan_lundef(self):
-        if 'b_lundef' not in self.coredata.base_options:
-            return
-        if 'b_sanitize' not in self.coredata.base_options:
-            return
-        if (self.coredata.base_options['b_lundef'].value and
-                self.coredata.base_options['b_sanitize'].value != 'none'):
-            mlog.warning('''Trying to use {} sanitizer on Clang with b_lundef.
-This will probably not work.
-Try setting b_lundef to false instead.'''.format(self.coredata.base_options['b_sanitize'].value),
-                         location=self.current_node)
-
-    def evaluate_subproject_info(self, path_from_source_root, subproject_dirname):
-        depth = 0
-        subproj_name = ''
-        segs = PurePath(path_from_source_root).parts
-        segs_spd = PurePath(subproject_dirname).parts
-        while segs and segs[0] == segs_spd[0]:
-            if len(segs_spd) == 1:
-                subproj_name = segs[1]
-                segs = segs[2:]
-                depth += 1
-            else:
-                segs_spd = segs_spd[1:]
-                segs = segs[1:]
-        return (depth, subproj_name)
-
-    # Check that the indicated file is within the same subproject
-    # as we currently are. This is to stop people doing
-    # nasty things like:
-    #
-    # f = files('../../master_src/file.c')
-    #
-    # Note that this is validated only when the file
-    # object is generated. The result can be used in a different
-    # subproject than it is defined in (due to e.g. a
-    # declare_dependency).
-    def validate_within_subproject(self, subdir, fname):
-        norm = os.path.normpath(os.path.join(subdir, fname))
-        if os.path.isabs(norm):
-            if not norm.startswith(self.environment.source_dir):
-                # Grabbing files outside the source tree is ok.
-                # This is for vendor stuff like:
-                #
-                # /opt/vendorsdk/src/file_with_license_restrictions.c
-                return
-            norm = os.path.relpath(norm, self.environment.source_dir)
-            assert(not os.path.isabs(norm))
-        (num_sps, sproj_name) = self.evaluate_subproject_info(norm, self.subproject_dir)
-        plain_filename = os.path.basename(norm)
-        if num_sps == 0:
-            if not self.is_subproject():
-                return
-            raise InterpreterException('Sandbox violation: Tried to grab file %s from a different subproject.' % plain_filename)
-        if num_sps > 1:
-            raise InterpreterException('Sandbox violation: Tried to grab file %s from a nested subproject.' % plain_filename)
-        if sproj_name != self.subproject_directory_name:
-            raise InterpreterException('Sandbox violation: Tried to grab file %s from a different subproject.' % plain_filename)
-
-    def source_strings_to_files(self, sources):
-        results = []
-        mesonlib.check_direntry_issues(sources)
-        if not isinstance(sources, list):
-            sources = [sources]
-        for s in sources:
-            if isinstance(s, (mesonlib.File, GeneratedListHolder,
-                              TargetHolder, CustomTargetIndexHolder,
-                              GeneratedObjectsHolder)):
-                pass
-            elif isinstance(s, str):
-                self.validate_within_subproject(self.subdir, s)
-                s = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s)
-            else:
-                raise InterpreterException('Source item is {!r} instead of '
-                                           'string or File-type object'.format(s))
-            results.append(s)
-        return results
-
-    def add_target(self, name, tobj):
-        if name == '':
-            raise InterpreterException('Target name must not be empty.')
-        if name.strip() == '':
-            raise InterpreterException('Target name must not consist only of whitespace.')
-        if name.startswith('meson-'):
-            raise InvalidArguments("Target names starting with 'meson-' are reserved "
-                                   "for Meson's internal use. Please rename.")
-        if name in coredata.forbidden_target_names:
-            raise InvalidArguments("Target name '%s' is reserved for Meson's "
-                                   "internal use. Please rename." % name)
-        # To permit an executable and a shared library to have the
-        # same name, such as "foo.exe" and "libfoo.a".
-        idname = tobj.get_id()
-        if idname in self.build.targets:
-            raise InvalidCode('Tried to create target "%s", but a target of that name already exists.' % name)
-        self.build.targets[idname] = tobj
-        if idname not in self.coredata.target_guids:
-            self.coredata.target_guids[idname] = str(uuid.uuid4()).upper()
-
-    @FeatureNew('both_libraries', '0.46.0')
-    def build_both_libraries(self, node, args, kwargs):
-        shared_holder = self.build_target(node, args, kwargs, SharedLibraryHolder)
-
-        # Check if user forces non-PIC static library.
-        pic = True
-        if 'pic' in kwargs:
-            pic = kwargs['pic']
-        elif 'b_staticpic' in self.environment.coredata.base_options:
-            pic = self.environment.coredata.base_options['b_staticpic'].value
-
-        if pic:
-            # Exclude sources from args and kwargs to avoid building them twice
-            static_args = [args[0]]
-            static_kwargs = kwargs.copy()
-            static_kwargs['sources'] = []
-            static_kwargs['objects'] = shared_holder.held_object.extract_all_objects()
-        else:
-            static_args = args
-            static_kwargs = kwargs
-
-        static_holder = self.build_target(node, static_args, static_kwargs, StaticLibraryHolder)
-
-        return BothLibrariesHolder(shared_holder, static_holder, self)
-
-    def build_library(self, node, args, kwargs):
-        default_library = self.coredata.get_builtin_option('default_library')
-        if default_library == 'shared':
-            return self.build_target(node, args, kwargs, SharedLibraryHolder)
-        elif default_library == 'static':
-            return self.build_target(node, args, kwargs, StaticLibraryHolder)
-        elif default_library == 'both':
-            return self.build_both_libraries(node, args, kwargs)
-        else:
-            raise InterpreterException('Unknown default_library value: %s.', default_library)
-
-    def build_target(self, node, args, kwargs, targetholder):
-        @FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories'])
-        @FeatureNewKwargs('build target', '0.41.0', ['rust_args'])
-        @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
-        @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility'])
-        def build_target_decorator_caller(self, node, args, kwargs):
-            return True
-
-        build_target_decorator_caller(self, node, args, kwargs)
-
-        if not args:
-            raise InterpreterException('Target does not have a name.')
-        name, *sources = args
-        for_machine = self.machine_from_native_kwarg(kwargs)
-        if 'sources' in kwargs:
-            sources += listify(kwargs['sources'])
-        sources = self.source_strings_to_files(sources)
-        objs = extract_as_list(kwargs, 'objects')
-        kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies')
-        kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs)
-        if 'extra_files' in kwargs:
-            ef = extract_as_list(kwargs, 'extra_files')
-            kwargs['extra_files'] = self.source_strings_to_files(ef)
-        self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources)
-        if targetholder is ExecutableHolder:
-            targetclass = build.Executable
-        elif targetholder is SharedLibraryHolder:
-            targetclass = build.SharedLibrary
-        elif targetholder is SharedModuleHolder:
-            targetclass = build.SharedModule
-        elif targetholder is StaticLibraryHolder:
-            targetclass = build.StaticLibrary
-        elif targetholder is JarHolder:
-            targetclass = build.Jar
-        else:
-            mlog.debug('Unknown target type:', str(targetholder))
-            raise RuntimeError('Unreachable code')
-        self.kwarg_strings_to_includedirs(kwargs)
-
-        # Filter out kwargs from other target types. For example 'soversion'
-        # passed to library() when default_library == 'static'.
-        kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs}
-
-        kwargs['include_directories'] = self.extract_incdirs(kwargs)
-        target = targetclass(name, self.subdir, self.subproject, for_machine, sources, objs, self.environment, kwargs)
-
-        if not self.environment.machines.matches_build_machine(for_machine):
-            self.add_cross_stdlib_info(target)
-        l = targetholder(target, self)
-        self.add_target(name, l.held_object)
-        self.project_args_frozen = True
-        return l
-
-    def kwarg_strings_to_includedirs(self, kwargs):
-        if 'd_import_dirs' in kwargs:
-            items = mesonlib.extract_as_list(kwargs, 'd_import_dirs')
-            cleaned_items = []
-            for i in items:
-                if isinstance(i, str):
-                    # BW compatibility. This was permitted so we must support it
-                    # for a few releases so people can transition to "correct"
-                    # path declarations.
-                    if os.path.normpath(i).startswith(self.environment.get_source_dir()):
-                        mlog.warning('''Building a path to the source dir is not supported. Use a relative path instead.
-This will become a hard error in the future.''', location=self.current_node)
-                        i = os.path.relpath(i, os.path.join(self.environment.get_source_dir(), self.subdir))
-                        i = self.build_incdir_object([i])
-                cleaned_items.append(i)
-            kwargs['d_import_dirs'] = cleaned_items
-
-    def get_used_languages(self, target):
-        result = {}
-        for i in target.sources:
-            # TODO other platforms
-            for lang, c in self.coredata.compilers.host.items():
-                if c.can_compile(i):
-                    result[lang] = True
-                    break
-        return result
-
-    def add_cross_stdlib_info(self, target):
-        if target.for_machine != MachineChoice.HOST:
-            return
-        for l in self.get_used_languages(target):
-            props = self.environment.properties.host
-            if props.has_stdlib(l) \
-                    and self.subproject != props.get_stdlib(l)[0]:
-                target.add_deps(self.build.stdlibs.host[l])
-
-    def check_sources_exist(self, subdir, sources):
-        for s in sources:
-            if not isinstance(s, str):
-                continue # This means a generated source and they always exist.
-            fname = os.path.join(subdir, s)
-            if not os.path.isfile(fname):
-                raise InterpreterException('Tried to add non-existing source file %s.' % s)
-
-    # Only permit object extraction from the same subproject
-    def validate_extraction(self, buildtarget):
-        if not self.subdir.startswith(self.subproject_dir):
-            if buildtarget.subdir.startswith(self.subproject_dir):
-                raise InterpreterException('Tried to extract objects from a subproject target.')
-        else:
-            if not buildtarget.subdir.startswith(self.subproject_dir):
-                raise InterpreterException('Tried to extract objects from the main project from a subproject.')
-            if self.subdir.split('/')[1] != buildtarget.subdir.split('/')[1]:
-                raise InterpreterException('Tried to extract objects from a different subproject.')
-
-    def check_contains(self, obj, args):
-        if len(args) != 1:
-            raise InterpreterException('Contains method takes exactly one argument.')
-        item = args[0]
-        for element in obj:
-            if isinstance(element, list):
-                found = self.check_contains(element, args)
-                if found:
-                    return True
-            if element == item:
-                return True
-        return False
-
-    def is_subproject(self):
-        return self.subproject != ''
-
-    @noKwargs
-    @noArgsFlattening
-    def func_set_variable(self, node, args, kwargs):
-        if len(args) != 2:
-            raise InvalidCode('Set_variable takes two arguments.')
-        varname, value = args
-        self.set_variable(varname, value)
-
-    @noKwargs
-    @noArgsFlattening
-    def func_get_variable(self, node, args, kwargs):
-        if len(args) < 1 or len(args) > 2:
-            raise InvalidCode('Get_variable takes one or two arguments.')
-        varname = args[0]
-        if not isinstance(varname, str):
-            raise InterpreterException('First argument must be a string.')
-        try:
-            return self.variables[varname]
-        except KeyError:
-            pass
-        if len(args) == 2:
-            return args[1]
-        raise InterpreterException('Tried to get unknown variable "%s".' % varname)
-
-    @stringArgs
-    @noKwargs
-    def func_is_variable(self, node, args, kwargs):
-        if len(args) != 1:
-            raise InvalidCode('Is_variable takes two arguments.')
-        varname = args[0]
-        return varname in self.variables
-
-    @staticmethod
-    def machine_from_native_kwarg(kwargs: T.Dict[str, T.Any]) -> MachineChoice:
-        native = kwargs.get('native', False)
-        if not isinstance(native, bool):
-            raise InvalidArguments('Argument to "native" must be a boolean.')
-        return MachineChoice.BUILD if native else MachineChoice.HOST
-
-    @FeatureNew('is_disabler', '0.52.0')
-    @noKwargs
-    def func_is_disabler(self, node, args, kwargs):
-        if len(args) != 1:
-            raise InvalidCode('Is_disabler takes one argument.')
-        varname = args[0]
-        return isinstance(varname, Disabler)
diff -Nru meson-0.53.2/mesonbuild/linkers/detect.py meson-0.61.2/mesonbuild/linkers/detect.py
--- meson-0.53.2/mesonbuild/linkers/detect.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/linkers/detect.py	2021-11-02 19:58:13.000000000 +0000
@@ -0,0 +1,218 @@
+# Copyright 2012-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ..mesonlib import (
+    EnvironmentException, MachineChoice, OptionKey,
+    Popen_safe, search_version
+)
+from .linkers import (
+    DynamicLinker,
+    AppleDynamicLinker,
+    GnuDynamicLinker,
+    GnuGoldDynamicLinker,
+    GnuBFDDynamicLinker,
+    LLVMDynamicLinker,
+    QualcommLLVMDynamicLinker,
+    MSVCDynamicLinker,
+    ClangClDynamicLinker,
+    SolarisDynamicLinker,
+    AIXDynamicLinker,
+    OptlinkDynamicLinker,
+)
+
+import re
+import shlex
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+    from ..compilers import Compiler
+
+defaults: T.Dict[str, T.List[str]] = {}
+defaults['static_linker'] = ['ar', 'gar']
+defaults['vs_static_linker'] = ['lib']
+defaults['clang_cl_static_linker'] = ['llvm-lib']
+defaults['cuda_static_linker'] = ['nvlink']
+defaults['gcc_static_linker'] = ['gcc-ar']
+defaults['clang_static_linker'] = ['llvm-ar']
+
+def __failed_to_detect_linker(compiler: T.List[str], args: T.List[str], stdout: str, stderr: str) -> 'T.NoReturn':
+    msg = 'Unable to detect linker for compiler "{} {}"\nstdout: {}\nstderr: {}'.format(
+        ' '.join(compiler), ' '.join(args), stdout, stderr)
+    raise EnvironmentException(msg)
+
+
+def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Type['Compiler'],
+                     for_machine: MachineChoice, *,
+                     use_linker_prefix: bool = True, invoked_directly: bool = True,
+                     extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
+    env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env)
+
+    # Explicitly pass logo here so that we can get the version of link.exe
+    if not use_linker_prefix or comp_class.LINKER_PREFIX is None:
+        check_args = ['/logo', '--version']
+    elif isinstance(comp_class.LINKER_PREFIX, str):
+        check_args = [comp_class.LINKER_PREFIX + '/logo', comp_class.LINKER_PREFIX + '--version']
+    elif isinstance(comp_class.LINKER_PREFIX, list):
+        check_args = comp_class.LINKER_PREFIX + ['/logo'] + comp_class.LINKER_PREFIX + ['--version']
+
+    check_args += env.coredata.options[OptionKey('args', lang=comp_class.language, machine=for_machine)].value
+
+    override = []  # type: T.List[str]
+    value = env.lookup_binary_entry(for_machine, comp_class.language + '_ld')
+    if value is not None:
+        override = comp_class.use_linker_args(value[0])
+        check_args += override
+
+    if extra_args is not None:
+        check_args.extend(extra_args)
+
+    p, o, _ = Popen_safe(compiler + check_args)
+    if 'LLD' in o.split('\n')[0]:
+        if '(compatible with GNU linkers)' in o:
+            return LLVMDynamicLinker(
+                compiler, for_machine, comp_class.LINKER_PREFIX,
+                override, version=search_version(o))
+        elif not invoked_directly:
+            return ClangClDynamicLinker(
+                for_machine, override, exelist=compiler, prefix=comp_class.LINKER_PREFIX,
+                version=search_version(o), direct=False, machine=None)
+
+    if value is not None and invoked_directly:
+        compiler = value
+        # We've already hanedled the non-direct case above
+
+    p, o, e = Popen_safe(compiler + check_args)
+    if 'LLD' in o.split('\n')[0]:
+        return ClangClDynamicLinker(
+            for_machine, [],
+            prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
+            exelist=compiler, version=search_version(o), direct=invoked_directly)
+    elif 'OPTLINK' in o:
+        # Opltink's stdout *may* beging with a \r character.
+        return OptlinkDynamicLinker(compiler, for_machine, version=search_version(o))
+    elif o.startswith('Microsoft') or e.startswith('Microsoft'):
+        out = o or e
+        match = re.search(r'.*(X86|X64|ARM|ARM64).*', out)
+        if match:
+            target = str(match.group(1))
+        else:
+            target = 'x86'
+
+        return MSVCDynamicLinker(
+            for_machine, [], machine=target, exelist=compiler,
+            prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
+            version=search_version(out), direct=invoked_directly)
+    elif 'GNU coreutils' in o:
+        import shutil
+        fullpath = shutil.which(compiler[0])
+        raise EnvironmentException(
+            f"Found GNU link.exe instead of MSVC link.exe in {fullpath}.\n"
+            "This link.exe is not a linker.\n"
+            "You may need to reorder entries to your %PATH% variable to resolve this.")
+    __failed_to_detect_linker(compiler, check_args, o, e)
+
+def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Type['Compiler'],
+                     for_machine: MachineChoice, *,
+                     extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
+    """Helper for guessing what linker to use on Unix-Like OSes.
+
+    :compiler: Invocation to use to get linker
+    :comp_class: The Compiler Type (uninstantiated)
+    :for_machine: which machine this linker targets
+    :extra_args: Any additional arguments required (such as a source file)
+    """
+    env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env)
+    extra_args = extra_args or []
+    extra_args += env.coredata.options[OptionKey('args', lang=comp_class.language, machine=for_machine)].value
+
+    if isinstance(comp_class.LINKER_PREFIX, str):
+        check_args = [comp_class.LINKER_PREFIX + '--version'] + extra_args
+    else:
+        check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args
+
+    override = []  # type: T.List[str]
+    value = env.lookup_binary_entry(for_machine, comp_class.language + '_ld')
+    if value is not None:
+        override = comp_class.use_linker_args(value[0])
+        check_args += override
+
+    _, o, e = Popen_safe(compiler + check_args)
+    v = search_version(o + e)
+    linker: DynamicLinker
+    if 'LLD' in o.split('\n')[0]:
+        linker = LLVMDynamicLinker(
+            compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
+    elif 'Snapdragon' in e and 'LLVM' in e:
+        linker = QualcommLLVMDynamicLinker(
+            compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
+    elif e.startswith('lld-link: '):
+        # The LLD MinGW frontend didn't respond to --version before version 9.0.0,
+        # and produced an error message about failing to link (when no object
+        # files were specified), instead of printing the version number.
+        # Let's try to extract the linker invocation command to grab the version.
+
+        _, o, e = Popen_safe(compiler + check_args + ['-v'])
+
+        try:
+            linker_cmd = re.match(r'.*\n(.*?)\nlld-link: ', e, re.DOTALL).group(1)
+            linker_cmd = shlex.split(linker_cmd)[0]
+        except (AttributeError, IndexError, ValueError):
+            pass
+        else:
+            _, o, e = Popen_safe([linker_cmd, '--version'])
+            v = search_version(o)
+
+        linker = LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
+    # first is for apple clang, second is for real gcc, the third is icc
+    elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e:
+        if isinstance(comp_class.LINKER_PREFIX, str):
+            _, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args)
+        else:
+            _, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args)
+        for line in e.split('\n'):
+            if 'PROJECT:ld' in line:
+                v = line.split('-')[1]
+                break
+        else:
+            v = 'unknown version'
+        linker = AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
+    elif 'GNU' in o or 'GNU' in e:
+        cls: T.Type[GnuDynamicLinker]
+        if 'gold' in o or 'gold' in e:
+            cls = GnuGoldDynamicLinker
+        else:
+            cls = GnuBFDDynamicLinker
+        linker = cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
+    elif 'Solaris' in e or 'Solaris' in o:
+        for line in (o+e).split('\n'):
+            if 'ld: Software Generation Utilities' in line:
+                v = line.split(':')[2].lstrip()
+                break
+        else:
+            v = 'unknown version'
+        linker = SolarisDynamicLinker(
+            compiler, for_machine, comp_class.LINKER_PREFIX, override,
+            version=v)
+    elif 'ld: 0706-012 The -- flag is not recognized' in e:
+        if isinstance(comp_class.LINKER_PREFIX, str):
+            _, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-V'] + extra_args)
+        else:
+            _, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-V'] + extra_args)
+        linker = AIXDynamicLinker(
+            compiler, for_machine, comp_class.LINKER_PREFIX, override,
+            version=search_version(e))
+    else:
+        __failed_to_detect_linker(compiler, check_args, o, e)
+    return linker
diff -Nru meson-0.53.2/mesonbuild/linkers/__init__.py meson-0.61.2/mesonbuild/linkers/__init__.py
--- meson-0.53.2/mesonbuild/linkers/__init__.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/linkers/__init__.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,128 @@
+# Copyright 2012-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .detect import (
+    defaults,
+    guess_win_linker,
+    guess_nix_linker,
+)
+from .linkers import (
+    RSPFileSyntax,
+
+    StaticLinker,
+    VisualStudioLikeLinker,
+    VisualStudioLinker,
+    IntelVisualStudioLinker,
+    ArLinker,
+    ArmarLinker,
+    DLinker,
+    CcrxLinker,
+    Xc16Linker,
+    CompCertLinker,
+    C2000Linker,
+    AIXArLinker,
+    PGIStaticLinker,
+    NvidiaHPC_StaticLinker,
+
+    DynamicLinker,
+    PosixDynamicLinkerMixin,
+    GnuLikeDynamicLinkerMixin,
+    AppleDynamicLinker,
+    GnuDynamicLinker,
+    GnuGoldDynamicLinker,
+    GnuBFDDynamicLinker,
+    LLVMDynamicLinker,
+    WASMDynamicLinker,
+    CcrxDynamicLinker,
+    Xc16DynamicLinker,
+    CompCertDynamicLinker,
+    C2000DynamicLinker,
+    ArmDynamicLinker,
+    ArmClangDynamicLinker,
+    QualcommLLVMDynamicLinker,
+    PGIDynamicLinker,
+    NvidiaHPC_DynamicLinker,
+    NAGDynamicLinker,
+
+    VisualStudioLikeLinkerMixin,
+    MSVCDynamicLinker,
+    ClangClDynamicLinker,
+    XilinkDynamicLinker,
+    SolarisDynamicLinker,
+    AIXDynamicLinker,
+    OptlinkDynamicLinker,
+    CudaLinker,
+
+    prepare_rpaths,
+    order_rpaths,
+    evaluate_rpath,
+)
+
+__all__ = [
+    # detect.py
+    'defaults',
+    'guess_win_linker',
+    'guess_nix_linker',
+
+    # linkers.py
+    'RSPFileSyntax',
+
+    'StaticLinker',
+    'VisualStudioLikeLinker',
+    'VisualStudioLinker',
+    'IntelVisualStudioLinker',
+    'ArLinker',
+    'ArmarLinker',
+    'DLinker',
+    'CcrxLinker',
+    'Xc16Linker',
+    'CompCertLinker',
+    'C2000Linker',
+    'AIXArLinker',
+    'PGIStaticLinker',
+    'NvidiaHPC_StaticLinker',
+
+    'DynamicLinker',
+    'PosixDynamicLinkerMixin',
+    'GnuLikeDynamicLinkerMixin',
+    'AppleDynamicLinker',
+    'GnuDynamicLinker',
+    'GnuGoldDynamicLinker',
+    'GnuBFDDynamicLinker',
+    'LLVMDynamicLinker',
+    'WASMDynamicLinker',
+    'CcrxDynamicLinker',
+    'Xc16DynamicLinker',
+    'CompCertDynamicLinker',
+    'C2000DynamicLinker',
+    'ArmDynamicLinker',
+    'ArmClangDynamicLinker',
+    'QualcommLLVMDynamicLinker',
+    'PGIDynamicLinker',
+    'NvidiaHPC_DynamicLinker',
+    'NAGDynamicLinker',
+
+    'VisualStudioLikeLinkerMixin',
+    'MSVCDynamicLinker',
+    'ClangClDynamicLinker',
+    'XilinkDynamicLinker',
+    'SolarisDynamicLinker',
+    'AIXDynamicLinker',
+    'OptlinkDynamicLinker',
+    'CudaLinker',
+
+    'prepare_rpaths',
+    'order_rpaths',
+    'evaluate_rpath',
+]
diff -Nru meson-0.53.2/mesonbuild/linkers/linkers.py meson-0.61.2/mesonbuild/linkers/linkers.py
--- meson-0.53.2/mesonbuild/linkers/linkers.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/linkers/linkers.py	2022-01-02 20:12:32.000000000 +0000
@@ -0,0 +1,1467 @@
+# Copyright 2012-2017 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 abc
+import enum
+import os
+import typing as T
+
+from .. import mesonlib
+from ..mesonlib import EnvironmentException, MesonException
+from ..arglist import CompilerArgs
+
+if T.TYPE_CHECKING:
+    from ..coredata import KeyedOptionDictType
+    from ..environment import Environment
+    from ..mesonlib import MachineChoice
+
+
+@enum.unique
+class RSPFileSyntax(enum.Enum):
+
+    """Which RSP file syntax the compiler supports."""
+
+    MSVC = enum.auto()
+    GCC = enum.auto()
+
+
+class StaticLinker:
+
+    id: str
+
+    def __init__(self, exelist: T.List[str]):
+        self.exelist = exelist
+
+    def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs:
+        return CompilerArgs(self, args)
+
+    def can_linker_accept_rsp(self) -> bool:
+        """
+        Determines whether the linker can accept arguments using the @rsp syntax.
+        """
+        return mesonlib.is_windows()
+
+    def get_base_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        """Like compilers.get_base_link_args, but for the static linker."""
+        return []
+
+    def get_exelist(self) -> T.List[str]:
+        return self.exelist.copy()
+
+    def get_std_link_args(self, is_thin: bool) -> T.List[str]:
+        return []
+
+    def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
+        return []
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return[]
+
+    def get_coverage_link_args(self) -> T.List[str]:
+        return []
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
+                         rpath_paths: T.Tuple[str, ...], build_rpath: str,
+                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+        return ([], set())
+
+    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def openmp_flags(self) -> T.List[str]:
+        return []
+
+    def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        return []
+
+    @classmethod
+    def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
+        return args[:]
+
+    @classmethod
+    def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
+        return args[:]
+
+    def get_link_debugfile_name(self, targetfile: str) -> str:
+        return None
+
+    def get_link_debugfile_args(self, targetfile: str) -> T.List[str]:
+        # Static libraries do not have PDB files
+        return []
+
+    def get_always_args(self) -> T.List[str]:
+        return []
+
+    def get_linker_always_args(self) -> T.List[str]:
+        return []
+
+    def rsp_file_syntax(self) -> RSPFileSyntax:
+        """The format of the RSP file that this compiler supports.
+
+        If `self.can_linker_accept_rsp()` returns True, then this needs to
+        be implemented
+        """
+        assert not self.can_linker_accept_rsp(), f'{self.id} linker accepts RSP, but doesn\' provide a supported format, this is a bug'
+        raise EnvironmentException(f'{self.id} does not implement rsp format, this shouldn\'t be called')
+
+
+class VisualStudioLikeLinker:
+    always_args = ['/NOLOGO']
+
+    def __init__(self, machine: str):
+        self.machine = machine
+
+    def get_always_args(self) -> T.List[str]:
+        return self.always_args.copy()
+
+    def get_linker_always_args(self) -> T.List[str]:
+        return self.always_args.copy()
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        args = []  # type: T.List[str]
+        if self.machine:
+            args += ['/MACHINE:' + self.machine]
+        args += ['/OUT:' + target]
+        return args
+
+    @classmethod
+    def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
+        from ..compilers import VisualStudioCCompiler
+        return VisualStudioCCompiler.unix_args_to_native(args)
+
+    @classmethod
+    def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
+        from ..compilers import VisualStudioCCompiler
+        return VisualStudioCCompiler.native_args_to_unix(args)
+
+    def rsp_file_syntax(self) -> RSPFileSyntax:
+        return RSPFileSyntax.MSVC
+
+
+class VisualStudioLinker(VisualStudioLikeLinker, StaticLinker):
+
+    """Microsoft's lib static linker."""
+
+    def __init__(self, exelist: T.List[str], machine: str):
+        StaticLinker.__init__(self, exelist)
+        VisualStudioLikeLinker.__init__(self, machine)
+
+
+class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker):
+
+    """Intel's xilib static linker."""
+
+    def __init__(self, exelist: T.List[str], machine: str):
+        StaticLinker.__init__(self, exelist)
+        VisualStudioLikeLinker.__init__(self, machine)
+
+
+class ArLikeLinker(StaticLinker):
+    # POSIX requires supporting the dash, GNU permits omitting it
+    std_args = ['-csr']
+
+    def can_linker_accept_rsp(self) -> bool:
+        # armar / AIX can't accept arguments using the @rsp syntax
+        # in fact, only the 'ar' id can
+        return False
+
+    def get_std_link_args(self, is_thin: bool) -> T.List[str]:
+        return self.std_args
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return [target]
+
+    def rsp_file_syntax(self) -> RSPFileSyntax:
+        return RSPFileSyntax.GCC
+
+
+class ArLinker(ArLikeLinker):
+    id = 'ar'
+
+    def __init__(self, exelist: T.List[str]):
+        super().__init__(exelist)
+        stdo = mesonlib.Popen_safe(self.exelist + ['-h'])[1]
+        # Enable deterministic builds if they are available.
+        stdargs = 'csr'
+        thinargs = ''
+        if '[D]' in stdo:
+            stdargs += 'D'
+        if '[T]' in stdo:
+            thinargs = 'T'
+        self.std_args = [stdargs]
+        self.std_thin_args = [stdargs + thinargs]
+        self.can_rsp = '@<' in stdo
+
+    def can_linker_accept_rsp(self) -> bool:
+        return self.can_rsp
+
+    def get_std_link_args(self, is_thin: bool) -> T.List[str]:
+        # FIXME: osx ld rejects this: "file built for unknown-unsupported file format"
+        if is_thin and not mesonlib.is_osx():
+            return self.std_thin_args
+        else:
+            return self.std_args
+
+
+class ArmarLinker(ArLikeLinker):
+    id = 'armar'
+
+
+class DLinker(StaticLinker):
+    def __init__(self, exelist: T.List[str], arch: str, *, rsp_syntax: RSPFileSyntax = RSPFileSyntax.GCC):
+        super().__init__(exelist)
+        self.id = exelist[0]
+        self.arch = arch
+        self.__rsp_syntax = rsp_syntax
+
+    def get_std_link_args(self, is_thin: bool) -> T.List[str]:
+        return ['-lib']
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return ['-of=' + target]
+
+    def get_linker_always_args(self) -> T.List[str]:
+        if mesonlib.is_windows():
+            if self.arch == 'x86_64':
+                return ['-m64']
+            elif self.arch == 'x86_mscoff' and self.id == 'dmd':
+                return ['-m32mscoff']
+            return ['-m32']
+        return []
+
+    def rsp_file_syntax(self) -> RSPFileSyntax:
+        return self.__rsp_syntax
+
+
+class CcrxLinker(StaticLinker):
+
+    def __init__(self, exelist: T.List[str]):
+        super().__init__(exelist)
+        self.id = 'rlink'
+
+    def can_linker_accept_rsp(self) -> bool:
+        return False
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return [f'-output={target}']
+
+    def get_linker_always_args(self) -> T.List[str]:
+        return ['-nologo', '-form=library']
+
+
+class Xc16Linker(StaticLinker):
+
+    def __init__(self, exelist: T.List[str]):
+        super().__init__(exelist)
+        self.id = 'xc16-ar'
+
+    def can_linker_accept_rsp(self) -> bool:
+        return False
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return [f'{target}']
+
+    def get_linker_always_args(self) -> T.List[str]:
+        return ['rcs']
+
+class CompCertLinker(StaticLinker):
+
+    def __init__(self, exelist: T.List[str]):
+        super().__init__(exelist)
+        self.id = 'ccomp'
+
+    def can_linker_accept_rsp(self) -> bool:
+        return False
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return [f'-o{target}']
+
+
+class C2000Linker(StaticLinker):
+
+    def __init__(self, exelist: T.List[str]):
+        super().__init__(exelist)
+        self.id = 'ar2000'
+
+    def can_linker_accept_rsp(self) -> bool:
+        return False
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return [f'{target}']
+
+    def get_linker_always_args(self) -> T.List[str]:
+        return ['-r']
+
+
+class AIXArLinker(ArLikeLinker):
+    id = 'aixar'
+    std_args = ['-csr', '-Xany']
+
+
+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.
+    internal_format_rpaths = [evaluate_rpath(p, build_dir, from_dir) for p in raw_rpaths]
+    ordered_rpaths = order_rpaths(internal_format_rpaths)
+    return ordered_rpaths
+
+
+def order_rpaths(rpath_list: T.List[str]) -> T.List[str]:
+    # We want rpaths that point inside our build dir to always override
+    # those pointing to other places in the file system. This is so built
+    # binaries prefer our libraries to the ones that may lie somewhere
+    # in the file system, such as /lib/x86_64-linux-gnu.
+    #
+    # The correct thing to do here would be C++'s std::stable_partition.
+    # Python standard library does not have it, so replicate it with
+    # sort, which is guaranteed to be stable.
+    return sorted(rpath_list, key=os.path.isabs)
+
+
+def evaluate_rpath(p: str, build_dir: str, from_dir: str) -> str:
+    if p == from_dir:
+        return '' # relpath errors out in this case
+    elif os.path.isabs(p):
+        return p # These can be outside of build dir.
+    else:
+        return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir))
+
+class DynamicLinker(metaclass=abc.ABCMeta):
+
+    """Base class for dynamic linkers."""
+
+    _BUILDTYPE_ARGS = {
+        'plain': [],
+        'debug': [],
+        'debugoptimized': [],
+        'release': [],
+        'minsize': [],
+        'custom': [],
+    }  # type: T.Dict[str, T.List[str]]
+
+    @abc.abstractproperty
+    def id(self) -> str:
+        pass
+
+    def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]:
+        args = [arg] if isinstance(arg, str) else arg
+        if self.prefix_arg is None:
+            return args
+        elif isinstance(self.prefix_arg, str):
+            return [self.prefix_arg + arg for arg in args]
+        ret = []
+        for arg in args:
+            ret += self.prefix_arg + [arg]
+        return ret
+
+    def __init__(self, exelist: T.List[str],
+                 for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]],
+                 always_args: T.List[str], *, version: str = 'unknown version'):
+        self.exelist = exelist
+        self.for_machine = for_machine
+        self.version = version
+        self.prefix_arg = prefix_arg
+        self.always_args = always_args
+        self.machine = None  # type: T.Optional[str]
+
+    def __repr__(self) -> str:
+        return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist))
+
+    def get_id(self) -> str:
+        return self.id
+
+    def get_version_string(self) -> str:
+        return f'({self.id} {self.version})'
+
+    def get_exelist(self) -> T.List[str]:
+        return self.exelist.copy()
+
+    def get_accepts_rsp(self) -> bool:
+        # rsp files are only used when building on Windows because we want to
+        # avoid issues with quoting and max argument length
+        return mesonlib.is_windows()
+
+    def rsp_file_syntax(self) -> RSPFileSyntax:
+        """The format of the RSP file that this compiler supports.
+
+        If `self.can_linker_accept_rsp()` returns True, then this needs to
+        be implemented
+        """
+        return RSPFileSyntax.GCC
+
+    def get_always_args(self) -> T.List[str]:
+        return self.always_args.copy()
+
+    def get_lib_prefix(self) -> str:
+        return ''
+
+    # XXX: is use_ldflags a compiler or a linker attribute?
+
+    def get_option_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        return []
+
+    def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
+        raise EnvironmentException(f'Language {self.id} does not support has_multi_link_arguments.')
+
+    def get_debugfile_name(self, targetfile: str) -> str:
+        '''Name of debug file written out (see below)'''
+        return None
+
+    def get_debugfile_args(self, targetfile: str) -> T.List[str]:
+        """Some compilers (MSVC) write debug into a separate file.
+
+        This method takes the target object path and returns a list of
+        commands to append to the linker invocation to control where that
+        file is written.
+        """
+        return []
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        return []
+
+    def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        return self.get_std_shared_lib_args()
+
+    def get_pie_args(self) -> T.List[str]:
+        # TODO: this really needs to take a boolean and return the args to
+        # disable pie, otherwise it only acts to enable pie if pie *isn't* the
+        # default.
+        raise EnvironmentException(f'Linker {self.id} does not support position-independent executable')
+
+    def get_lto_args(self) -> T.List[str]:
+        return []
+
+    def sanitizer_args(self, value: str) -> T.List[str]:
+        return []
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        # We can override these in children by just overriding the
+        # _BUILDTYPE_ARGS value.
+        return self._BUILDTYPE_ARGS[buildtype]
+
+    def get_asneeded_args(self) -> T.List[str]:
+        return []
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        raise EnvironmentException(
+            f'Linker {self.id} does not support link_whole')
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        raise EnvironmentException(
+            f'Linker {self.id} does not support allow undefined')
+
+    @abc.abstractmethod
+    def get_output_args(self, outname: str) -> T.List[str]:
+        pass
+
+    def get_coverage_args(self) -> T.List[str]:
+        raise EnvironmentException(f"Linker {self.id} doesn't implement coverage data generation.")
+
+    @abc.abstractmethod
+    def get_search_args(self, dirname: str) -> T.List[str]:
+        pass
+
+    def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def import_library_args(self, implibname: str) -> T.List[str]:
+        """The name of the outputted import library.
+
+        This implementation is used only on Windows by compilers that use GNU ld
+        """
+        return []
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def no_undefined_args(self) -> T.List[str]:
+        """Arguments to error if there are any undefined symbols at link time.
+
+        This is the inverse of get_allow_undefined_args().
+
+        TODO: A future cleanup might merge this and
+              get_allow_undefined_args() into a single method taking a
+              boolean
+        """
+        return []
+
+    def fatal_warnings(self) -> T.List[str]:
+        """Arguments to make all warnings errors."""
+        return []
+
+    def headerpad_args(self) -> T.List[str]:
+        # Only used by the Apple linker
+        return []
+
+    def get_gui_app_args(self, value: bool) -> T.List[str]:
+        # Only used by VisualStudioLikeLinkers
+        return []
+
+    def get_win_subsystem_args(self, value: str) -> T.List[str]:
+        # Only used if supported by the dynamic linker and
+        # only when targeting Windows
+        return []
+
+    def bitcode_args(self) -> T.List[str]:
+        raise MesonException('This linker does not support bitcode bundles')
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
+                         rpath_paths: T.Tuple[str, ...], build_rpath: str,
+                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+        return ([], set())
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        return []
+
+
+class PosixDynamicLinkerMixin:
+
+    """Mixin class for POSIX-ish linkers.
+
+    This is obviously a pretty small subset of the linker interface, but
+    enough dynamic linkers that meson supports are POSIX-like but not
+    GNU-like that it makes sense to split this out.
+    """
+
+    def get_output_args(self, outname: str) -> T.List[str]:
+        return ['-o', outname]
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        return ['-shared']
+
+    def get_search_args(self, dirname: str) -> T.List[str]:
+        return ['-L' + dirname]
+
+
+class GnuLikeDynamicLinkerMixin:
+
+    """Mixin class for dynamic linkers that provides gnu-like interface.
+
+    This acts as a base for the GNU linkers (bfd and gold), LLVM's lld, and
+    other linkers like GNU-ld.
+    """
+
+    if T.TYPE_CHECKING:
+        for_machine = MachineChoice.HOST
+        def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ...
+
+    _BUILDTYPE_ARGS = {
+        'plain': [],
+        'debug': [],
+        'debugoptimized': [],
+        'release': ['-O1'],
+        'minsize': [],
+        'custom': [],
+    }  # type: T.Dict[str, T.List[str]]
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        # We can override these in children by just overriding the
+        # _BUILDTYPE_ARGS value.
+        return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]])
+
+    def get_pie_args(self) -> T.List[str]:
+        return ['-pie']
+
+    def get_asneeded_args(self) -> T.List[str]:
+        return self._apply_prefix('--as-needed')
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        if not args:
+            return args
+        return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive')
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return self._apply_prefix('--allow-shlib-undefined')
+
+    def get_lto_args(self) -> T.List[str]:
+        return ['-flto']
+
+    def sanitizer_args(self, value: str) -> T.List[str]:
+        if value == 'none':
+            return []
+        return ['-fsanitize=' + value]
+
+    def get_coverage_args(self) -> T.List[str]:
+        return ['--coverage']
+
+    def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
+        m = env.machines[self.for_machine]
+        if m.is_windows() or m.is_cygwin():
+            return self._apply_prefix('--export-all-symbols')
+        return self._apply_prefix('-export-dynamic')
+
+    def import_library_args(self, implibname: str) -> T.List[str]:
+        return self._apply_prefix('--out-implib=' + implibname)
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        if env.machines[self.for_machine].is_haiku():
+            return []
+        return ['-pthread']
+
+    def no_undefined_args(self) -> T.List[str]:
+        return self._apply_prefix('--no-undefined')
+
+    def fatal_warnings(self) -> T.List[str]:
+        return self._apply_prefix('--fatal-warnings')
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        m = env.machines[self.for_machine]
+        if m.is_windows() or m.is_cygwin():
+            # For PE/COFF the soname argument has no effect
+            return []
+        sostr = '' if soversion is None else '.' + soversion
+        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: 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():
+            return ([], set())
+        if not rpath_paths and not install_rpath and not build_rpath:
+            return ([], set())
+        args = []
+        origin_placeholder = '$ORIGIN'
+        processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
+        # Need to deduplicate rpaths, as macOS's install_name_tool
+        # is *very* allergic to duplicate -delete_rpath arguments
+        # when calling depfixer on installation.
+        all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
+        rpath_dirs_to_remove = set()
+        for p in all_paths:
+            rpath_dirs_to_remove.add(p.encode('utf8'))
+        # Build_rpath is used as-is (it is usually absolute).
+        if build_rpath != '':
+            all_paths.add(build_rpath)
+            for p in build_rpath.split(':'):
+                rpath_dirs_to_remove.add(p.encode('utf8'))
+
+        # TODO: should this actually be "for (dragonfly|open)bsd"?
+        if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd():
+            # This argument instructs the compiler to record the value of
+            # ORIGIN in the .dynamic section of the elf. On Linux this is done
+            # by default, but is not on dragonfly/openbsd for some reason. Without this
+            # $ORIGIN in the runtime path will be undefined and any binaries
+            # linked against local libraries will fail to resolve them.
+            args.extend(self._apply_prefix('-z,origin'))
+
+        # In order to avoid relinking for RPATH removal, the binary needs to contain just
+        # enough space in the ELF header to hold the final installation RPATH.
+        paths = ':'.join(all_paths)
+        if len(paths) < len(install_rpath):
+            padding = 'X' * (len(install_rpath) - len(paths))
+            if not paths:
+                paths = padding
+            else:
+                paths = paths + ':' + padding
+        args.extend(self._apply_prefix('-rpath,' + paths))
+
+        # TODO: should this actually be "for solaris/sunos"?
+        if mesonlib.is_sunos():
+            return (args, rpath_dirs_to_remove)
+
+        # Rpaths to use while linking must be absolute. These are not
+        # written to the binary. Needed only with GNU ld:
+        # https://sourceware.org/bugzilla/show_bug.cgi?id=16936
+        # Not needed on Windows or other platforms that don't use RPATH
+        # https://github.com/mesonbuild/meson/issues/1897
+        #
+        # In addition, this linker option tends to be quite long and some
+        # compilers have trouble dealing with it. That's why we will include
+        # one option per folder, like this:
+        #
+        #   -Wl,-rpath-link,/path/to/folder1 -Wl,-rpath,/path/to/folder2 ...
+        #
+        # ...instead of just one single looooong option, like this:
+        #
+        #   -Wl,-rpath-link,/path/to/folder1:/path/to/folder2:...
+        for p in rpath_paths:
+            args.extend(self._apply_prefix('-rpath-link,' + os.path.join(build_dir, p)))
+
+        return (args, rpath_dirs_to_remove)
+
+    def get_win_subsystem_args(self, value: str) -> T.List[str]:
+        if 'windows' in value:
+            args = ['--subsystem,windows']
+        elif 'console' in value:
+            args = ['--subsystem,console']
+        else:
+            raise MesonException(f'Only "windows" and "console" are supported for win_subsystem with MinGW, not "{value}".')
+        if ',' in value:
+            args[-1] = args[-1] + ':' + value.split(',')[1]
+
+        return self._apply_prefix(args)
+
+
+class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
+
+    """Apple's ld implementation."""
+
+    id = 'ld64'
+
+    def get_asneeded_args(self) -> T.List[str]:
+        return self._apply_prefix('-dead_strip_dylibs')
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return self._apply_prefix('-undefined,dynamic_lookup')
+
+    def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup')
+
+    def get_pie_args(self) -> T.List[str]:
+        return []
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        result = []  # type: T.List[str]
+        for a in args:
+            result.extend(self._apply_prefix('-force_load'))
+            result.append(a)
+        return result
+
+    def get_coverage_args(self) -> T.List[str]:
+        return ['--coverage']
+
+    def sanitizer_args(self, value: str) -> T.List[str]:
+        if value == 'none':
+            return []
+        return ['-fsanitize=' + value]
+
+    def no_undefined_args(self) -> T.List[str]:
+        return self._apply_prefix('-undefined,error')
+
+    def headerpad_args(self) -> T.List[str]:
+        return self._apply_prefix('-headerpad_max_install_names')
+
+    def bitcode_args(self) -> T.List[str]:
+        return self._apply_prefix('-bitcode_bundle')
+
+    def fatal_warnings(self) -> T.List[str]:
+        return self._apply_prefix('-fatal_warnings')
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        install_name = ['@rpath/', prefix, shlib_name]
+        if soversion is not None:
+            install_name.append('.' + soversion)
+        install_name.append('.dylib')
+        args = ['-install_name', ''.join(install_name)]
+        if darwin_versions:
+            args.extend(['-compatibility_version', darwin_versions[0],
+                         '-current_version', darwin_versions[1]])
+        return args
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: 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())
+        args = []
+        # @loader_path is the equivalent of $ORIGIN on macOS
+        # https://stackoverflow.com/q/26280738
+        origin_placeholder = '@loader_path'
+        processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
+        all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
+        if build_rpath != '':
+            all_paths.add(build_rpath)
+        for rp in all_paths:
+            args.extend(self._apply_prefix('-rpath,' + rp))
+
+        return (args, set())
+
+
+class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
+
+    """Representation of GNU ld.bfd and ld.gold."""
+
+    def get_accepts_rsp(self) -> bool:
+        return True
+
+
+class GnuGoldDynamicLinker(GnuDynamicLinker):
+
+    id = 'ld.gold'
+
+
+class GnuBFDDynamicLinker(GnuDynamicLinker):
+
+    id = 'ld.bfd'
+
+
+class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
+
+    """Representation of LLVM's ld.lld linker.
+
+    This is only the gnu-like linker, not the apple like or link.exe like
+    linkers.
+    """
+
+    id = 'ld.lld'
+
+    def __init__(self, exelist: T.List[str],
+                 for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]],
+                 always_args: T.List[str], *, version: str = 'unknown version'):
+        super().__init__(exelist, for_machine, prefix_arg, always_args, version=version)
+
+        # Some targets don't seem to support this argument (windows, wasm, ...)
+        _, _, e = mesonlib.Popen_safe(self.exelist + self._apply_prefix('--allow-shlib-undefined'))
+        self.has_allow_shlib_undefined = 'unknown argument: --allow-shlib-undefined' not in e
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        if self.has_allow_shlib_undefined:
+            return self._apply_prefix('--allow-shlib-undefined')
+        return []
+
+
+class WASMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
+
+    """Emscripten's wasm-ld."""
+
+    id = 'ld.wasm'
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0']
+
+    def no_undefined_args(self) -> T.List[str]:
+        return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1']
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        raise MesonException(f'{self.id} does not support shared libraries.')
+
+    def get_asneeded_args(self) -> T.List[str]:
+        return []
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
+                         rpath_paths: T.Tuple[str, ...], build_rpath: str,
+                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+        return ([], set())
+
+
+class CcrxDynamicLinker(DynamicLinker):
+
+    """Linker for Renesis CCrx compiler."""
+
+    id = 'rlink'
+
+    def __init__(self, for_machine: mesonlib.MachineChoice,
+                 *, version: str = 'unknown version'):
+        super().__init__(['rlink.exe'], for_machine, '', [],
+                         version=version)
+
+    def get_accepts_rsp(self) -> bool:
+        return False
+
+    def get_lib_prefix(self) -> str:
+        return '-lib='
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        return []
+
+    def get_output_args(self, outputname: str) -> T.List[str]:
+        return [f'-output={outputname}']
+
+    def get_search_args(self, dirname: str) -> 'T.NoReturn':
+        raise OSError('rlink.exe does not have a search dir argument')
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        return []
+
+
+class Xc16DynamicLinker(DynamicLinker):
+
+    """Linker for Microchip XC16 compiler."""
+
+    id = 'xc16-gcc'
+
+    def __init__(self, for_machine: mesonlib.MachineChoice,
+                 *, version: str = 'unknown version'):
+        super().__init__(['xc16-gcc'], for_machine, '', [],
+                         version=version)
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        if not args:
+            return args
+        return self._apply_prefix('--start-group') + args + self._apply_prefix('--end-group')
+
+    def get_accepts_rsp(self) -> bool:
+        return False
+
+    def get_lib_prefix(self) -> str:
+        return ''
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        return []
+
+    def get_output_args(self, outputname: str) -> T.List[str]:
+        return [f'-o{outputname}']
+
+    def get_search_args(self, dirname: str) -> 'T.NoReturn':
+        raise OSError('xc16-gcc does not have a search dir argument')
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        return []
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
+                         rpath_paths: T.Tuple[str, ...], build_rpath: str,
+                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+        return ([], set())
+
+class CompCertDynamicLinker(DynamicLinker):
+
+    """Linker for CompCert C compiler."""
+
+    id = 'ccomp'
+
+    def __init__(self, for_machine: mesonlib.MachineChoice,
+                 *, version: str = 'unknown version'):
+        super().__init__(['ccomp'], for_machine, '', [],
+                         version=version)
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        if not args:
+            return args
+        return self._apply_prefix('-Wl,--whole-archive') + args + self._apply_prefix('-Wl,--no-whole-archive')
+
+    def get_accepts_rsp(self) -> bool:
+        return False
+
+    def get_lib_prefix(self) -> str:
+        return ''
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        return []
+
+    def get_output_args(self, outputname: str) -> T.List[str]:
+        return [f'-o{outputname}']
+
+    def get_search_args(self, dirname: str) -> T.List[str]:
+        return [f'-L{dirname}']
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        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: T.Tuple[str, ...], build_rpath: str,
+                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+        return ([], set())
+
+class C2000DynamicLinker(DynamicLinker):
+
+    """Linker for Texas Instruments C2000 compiler."""
+
+    id = 'cl2000'
+
+    def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
+                 *, version: str = 'unknown version'):
+        super().__init__(exelist or ['cl2000.exe'], for_machine, '', [],
+                         version=version)
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        if not args:
+            return args
+        return self._apply_prefix('--start-group') + args + self._apply_prefix('--end-group')
+
+    def get_accepts_rsp(self) -> bool:
+        return False
+
+    def get_lib_prefix(self) -> str:
+        return '-l='
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        return []
+
+    def get_output_args(self, outputname: str) -> T.List[str]:
+        return ['-z', f'--output_file={outputname}']
+
+    def get_search_args(self, dirname: str) -> 'T.NoReturn':
+        raise OSError('cl2000.exe does not have a search dir argument')
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_always_args(self) -> T.List[str]:
+        return []
+
+
+class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
+
+    """Linker for the ARM compiler."""
+
+    id = 'armlink'
+
+    def __init__(self, for_machine: mesonlib.MachineChoice,
+                 *, version: str = 'unknown version'):
+        super().__init__(['armlink'], for_machine, '', [],
+                         version=version)
+
+    def get_accepts_rsp(self) -> bool:
+        return False
+
+    def get_std_shared_lib_args(self) -> 'T.NoReturn':
+        raise MesonException('The Arm Linkers do not support shared libraries')
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+
+class ArmClangDynamicLinker(ArmDynamicLinker):
+
+    """Linker used with ARM's clang fork.
+
+    The interface is similar enough to the old ARM ld that it inherits and
+    extends a few things as needed.
+    """
+
+    def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
+        return ['--export_dynamic']
+
+    def import_library_args(self, implibname: str) -> T.List[str]:
+        return ['--symdefs=' + implibname]
+
+class QualcommLLVMDynamicLinker(LLVMDynamicLinker):
+
+    """ARM Linker from Snapdragon LLVM ARM Compiler."""
+
+    id = 'ld.qcld'
+
+
+class NAGDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
+
+    """NAG Fortran linker, ld via gcc indirection.
+
+    Using nagfor -Wl,foo passes option foo to a backend gcc invocation.
+    (This linking gathers the correct objects needed from the nagfor runtime
+    system.)
+    To pass gcc -Wl,foo options (i.e., to ld) one must apply indirection
+    again: nagfor -Wl,-Wl,,foo
+    """
+
+    id = 'nag'
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: 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())
+        args = []
+        origin_placeholder = '$ORIGIN'
+        processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
+        all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
+        if build_rpath != '':
+            all_paths.add(build_rpath)
+        for rp in all_paths:
+            args.extend(self._apply_prefix('-Wl,-Wl,,-rpath,,' + rp))
+
+        return (args, set())
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        from ..compilers import NAGFortranCompiler
+        return NAGFortranCompiler.get_nagfor_quiet(self.version) + ['-Wl,-shared']
+
+
+class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
+
+    """PGI linker."""
+
+    id = 'pgi'
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        return []
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        # PGI -shared is Linux only.
+        if mesonlib.is_windows():
+            return ['-Bdynamic', '-Mmakedll']
+        elif mesonlib.is_linux():
+            return ['-shared']
+        return []
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: 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())
+        return ([], set())
+
+NvidiaHPC_DynamicLinker = PGIDynamicLinker
+
+
+class PGIStaticLinker(StaticLinker):
+    def __init__(self, exelist: T.List[str]):
+        super().__init__(exelist)
+        self.id = 'ar'
+        self.std_args = ['-r']
+
+    def get_std_link_args(self, is_thin: bool) -> T.List[str]:
+        return self.std_args
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return [target]
+
+NvidiaHPC_StaticLinker = PGIStaticLinker
+
+
+class VisualStudioLikeLinkerMixin:
+
+    """Mixin class for for dynamic linkers that act like Microsoft's link.exe."""
+
+    if T.TYPE_CHECKING:
+        for_machine = MachineChoice.HOST
+        def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ...
+
+    _BUILDTYPE_ARGS = {
+        'plain': [],
+        'debug': [],
+        'debugoptimized': [],
+        # The otherwise implicit REF and ICF linker optimisations are disabled by
+        # /DEBUG. REF implies ICF.
+        'release': ['/OPT:REF'],
+        'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
+        'custom': [],
+    }  # type: T.Dict[str, T.List[str]]
+
+    def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
+                 prefix_arg: T.Union[str, T.List[str]], always_args: T.List[str], *,
+                 version: str = 'unknown version', direct: bool = True, machine: str = 'x86'):
+        # There's no way I can find to make mypy understand what's going on here
+        super().__init__(exelist, for_machine, prefix_arg, always_args, version=version)  # type: ignore
+        self.machine = machine
+        self.direct = direct
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]])
+
+    def invoked_by_compiler(self) -> bool:
+        return not self.direct
+
+    def get_output_args(self, outputname: str) -> T.List[str]:
+        return self._apply_prefix(['/MACHINE:' + self.machine, '/OUT:' + outputname])
+
+    def get_always_args(self) -> T.List[str]:
+        parent = super().get_always_args() # type: ignore
+        return self._apply_prefix('/nologo') + T.cast(T.List[str], parent)
+
+    def get_search_args(self, dirname: str) -> T.List[str]:
+        return self._apply_prefix('/LIBPATH:' + dirname)
+
+    def get_std_shared_lib_args(self) -> T.List[str]:
+        return self._apply_prefix('/DLL')
+
+    def get_debugfile_name(self, targetfile: str) -> str:
+        basename = targetfile.rsplit('.', maxsplit=1)[0]
+        return basename + '.pdb'
+
+    def get_debugfile_args(self, targetfile: str) -> T.List[str]:
+        return self._apply_prefix(['/DEBUG', '/PDB:' + self.get_debugfile_name(targetfile)])
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        # Only since VS2015
+        args = mesonlib.listify(args)
+        l = []  # T.List[str]
+        for a in args:
+            l.extend(self._apply_prefix('/WHOLEARCHIVE:' + a))
+        return l
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        return []
+
+    def import_library_args(self, implibname: str) -> T.List[str]:
+        """The command to generate the import library."""
+        return self._apply_prefix(['/IMPLIB:' + implibname])
+
+    def rsp_file_syntax(self) -> RSPFileSyntax:
+        return RSPFileSyntax.MSVC
+
+
+class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
+
+    """Microsoft's Link.exe."""
+
+    id = 'link'
+
+    def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
+                 exelist: T.Optional[T.List[str]] = None,
+                 prefix: T.Union[str, T.List[str]] = '',
+                 machine: str = 'x86', version: str = 'unknown version',
+                 direct: bool = True):
+        super().__init__(exelist or ['link.exe'], for_machine,
+                         prefix, always_args, machine=machine, version=version, direct=direct)
+
+    def get_always_args(self) -> T.List[str]:
+        return self._apply_prefix(['/nologo', '/release']) + super().get_always_args()
+
+    def get_gui_app_args(self, value: bool) -> T.List[str]:
+        return self.get_win_subsystem_args("windows" if value else "console")
+
+    def get_win_subsystem_args(self, value: str) -> T.List[str]:
+        return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}'])
+
+
+class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
+
+    """Clang's lld-link.exe."""
+
+    id = 'lld-link'
+
+    def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
+                 exelist: T.Optional[T.List[str]] = None,
+                 prefix: T.Union[str, T.List[str]] = '',
+                 machine: str = 'x86', version: str = 'unknown version',
+                 direct: bool = True):
+        super().__init__(exelist or ['lld-link.exe'], for_machine,
+                         prefix, always_args, machine=machine, version=version, direct=direct)
+
+    def get_output_args(self, outputname: str) -> T.List[str]:
+        # If we're being driven indirectly by clang just skip /MACHINE
+        # as clang's target triple will handle the machine selection
+        if self.machine is None:
+            return self._apply_prefix([f"/OUT:{outputname}"])
+
+        return super().get_output_args(outputname)
+
+    def get_gui_app_args(self, value: bool) -> T.List[str]:
+        return self.get_win_subsystem_args("windows" if value else "console")
+
+    def get_win_subsystem_args(self, value: str) -> T.List[str]:
+        return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}'])
+
+
+class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
+
+    """Intel's Xilink.exe."""
+
+    id = 'xilink'
+
+    def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
+                 exelist: T.Optional[T.List[str]] = None,
+                 prefix: T.Union[str, T.List[str]] = '',
+                 machine: str = 'x86', version: str = 'unknown version',
+                 direct: bool = True):
+        super().__init__(['xilink.exe'], for_machine, '', always_args, version=version)
+
+    def get_gui_app_args(self, value: bool) -> T.List[str]:
+        return self.get_win_subsystem_args("windows" if value else "console")
+
+    def get_win_subsystem_args(self, value: str) -> T.List[str]:
+        return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}'])
+
+
+class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
+
+    """Sys-V derived linker used on Solaris and OpenSolaris."""
+
+    id = 'ld.solaris'
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        if not args:
+            return args
+        return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive')
+
+    def get_pie_args(self) -> T.List[str]:
+        # Available in Solaris 11.2 and later
+        pc, stdo, stde = mesonlib.Popen_safe(self.exelist + self._apply_prefix('-zhelp'))
+        for line in (stdo + stde).split('\n'):
+            if '-z type' in line:
+                if 'pie' in line:
+                    return ['-z', 'type=pie']
+                break
+        return []
+
+    def get_asneeded_args(self) -> T.List[str]:
+        return self._apply_prefix(['-z', 'ignore'])
+
+    def no_undefined_args(self) -> T.List[str]:
+        return ['-z', 'defs']
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return ['-z', 'nodefs']
+
+    def fatal_warnings(self) -> T.List[str]:
+        return ['-z', 'fatal-warnings']
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: 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())
+        processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
+        all_paths = mesonlib.OrderedSet([os.path.join('$ORIGIN', p) for p in processed_rpaths])
+        rpath_dirs_to_remove = set()
+        for p in all_paths:
+            rpath_dirs_to_remove.add(p.encode('utf8'))
+        if build_rpath != '':
+            all_paths.add(build_rpath)
+            for p in build_rpath.split(':'):
+                rpath_dirs_to_remove.add(p.encode('utf8'))
+
+        # In order to avoid relinking for RPATH removal, the binary needs to contain just
+        # enough space in the ELF header to hold the final installation RPATH.
+        paths = ':'.join(all_paths)
+        if len(paths) < len(install_rpath):
+            padding = 'X' * (len(install_rpath) - len(paths))
+            if not paths:
+                paths = padding
+            else:
+                paths = paths + ':' + padding
+        return (self._apply_prefix(f'-rpath,{paths}'), rpath_dirs_to_remove)
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        sostr = '' if soversion is None else '.' + soversion
+        return self._apply_prefix(f'-soname,{prefix}{shlib_name}.{suffix}{sostr}')
+
+
+class AIXDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
+
+    """Sys-V derived linker used on AIX"""
+
+    id = 'ld.aix'
+
+    def get_always_args(self) -> T.List[str]:
+        return self._apply_prefix(['-bnoipath', '-bbigtoc']) + super().get_always_args()
+
+    def no_undefined_args(self) -> T.List[str]:
+        return self._apply_prefix(['-bernotok'])
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return self._apply_prefix(['-berok'])
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: 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
+        if install_rpath != '':
+            all_paths.add(install_rpath)
+        if build_rpath != '':
+            all_paths.add(build_rpath)
+        for p in rpath_paths:
+            all_paths.add(os.path.join(build_dir, p))
+        # We should consider allowing the $LIBPATH environment variable
+        # to override sys_path.
+        sys_path = env.get_compiler_system_dirs(self.for_machine)
+        if len(sys_path) == 0:
+            # get_compiler_system_dirs doesn't support our compiler.
+            # Use the default system library path
+            all_paths.update(['/usr/lib', '/lib'])
+        else:
+            # Include the compiler's default library paths, but filter out paths that don't exist
+            for p in sys_path:
+                if os.path.isdir(p):
+                    all_paths.add(p)
+        return (self._apply_prefix('-blibpath:' + ':'.join(all_paths)), set())
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return ['-pthread']
+
+
+class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
+
+    """Digital Mars dynamic linker for windows."""
+
+    id = 'optlink'
+
+    def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
+                 *, version: str = 'unknown version'):
+        # Use optlink instead of link so we don't interfer with other link.exe
+        # implementations.
+        super().__init__(exelist, for_machine, '', [], version=version)
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_debugfile_args(self, targetfile: str) -> T.List[str]:
+        # Optlink does not generate pdb files.
+        return []
+
+    def get_always_args(self) -> T.List[str]:
+        return []
+
+
+class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
+    """Cuda linker (nvlink)"""
+
+    id = 'nvlink'
+
+    @staticmethod
+    def parse_version() -> str:
+        version_cmd = ['nvlink', '--version']
+        try:
+            _, out, _ = mesonlib.Popen_safe(version_cmd)
+        except OSError:
+            return 'unknown version'
+        # Output example:
+        # nvlink: NVIDIA (R) Cuda linker
+        # Copyright (c) 2005-2018 NVIDIA Corporation
+        # Built on Sun_Sep_30_21:09:22_CDT_2018
+        # Cuda compilation tools, release 10.0, V10.0.166
+        # we need the most verbose version output. Luckily starting with V
+        return out.strip().split('V')[-1]
+
+    def get_accepts_rsp(self) -> bool:
+        # nvcc does not support response files
+        return False
+
+    def get_lib_prefix(self) -> str:
+        # nvcc doesn't recognize Meson's default .a extension for static libraries on
+        # Windows and passes it to cl as an object file, resulting in 'warning D9024 :
+        # unrecognized source file type 'xxx.a', object file assumed'.
+        #
+        # nvcc's --library= option doesn't help: it takes the library name without the
+        # extension and assumes that the extension on Windows is .lib; prefixing the
+        # library with -Xlinker= seems to work.
+        #
+        # On Linux, we have to use rely on -Xlinker= too, since nvcc/nvlink chokes on
+        # versioned shared libraries:
+        #
+        #   nvcc fatal : Don't know what to do with 'subprojects/foo/libbar.so.0.1.2'
+        #
+        from ..compilers import CudaCompiler
+        return CudaCompiler.LINKER_PREFIX
+
+    def fatal_warnings(self) -> T.List[str]:
+        return ['--warning-as-error']
+
+    def get_allow_undefined_args(self) -> T.List[str]:
+        return []
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        return []
diff -Nru meson-0.53.2/mesonbuild/linkers.py meson-0.61.2/mesonbuild/linkers.py
--- meson-0.53.2/mesonbuild/linkers.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/linkers.py	1970-01-01 00:00:00.000000000 +0000
@@ -1,1006 +0,0 @@
-# Copyright 2012-2017 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 abc
-import os
-import typing as T
-
-from . import mesonlib
-
-if T.TYPE_CHECKING:
-    from .coredata import OptionDictType
-    from .environment import Environment
-
-
-class StaticLinker:
-
-    def __init__(self, exelist: T.List[str]):
-        self.exelist = exelist
-
-    def can_linker_accept_rsp(self) -> bool:
-        """
-        Determines whether the linker can accept arguments using the @rsp syntax.
-        """
-        return mesonlib.is_windows()
-
-    def get_base_link_args(self, options: 'OptionDictType') -> T.List[str]:
-        """Like compilers.get_base_link_args, but for the static linker."""
-        return []
-
-    def get_exelist(self) -> T.List[str]:
-        return self.exelist.copy()
-
-    def get_std_link_args(self) -> T.List[str]:
-        return []
-
-    def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
-        return []
-
-    def get_output_args(self, target: str) -> T.List[str]:
-        return[]
-
-    def get_coverage_link_args(self) -> T.List[str]:
-        return []
-
-    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
-                         rpath_paths: str, build_rpath: str,
-                         install_rpath: str) -> T.List[str]:
-        return []
-
-    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
-        return []
-
-    def openmp_flags(self) -> T.List[str]:
-        return []
-
-    def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
-        return []
-
-    @classmethod
-    def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
-        return args[:]
-
-    @classmethod
-    def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
-        return args[:]
-
-    def get_link_debugfile_args(self, targetfile: str) -> T.List[str]:
-        # Static libraries do not have PDB files
-        return []
-
-    def get_always_args(self) -> T.List[str]:
-        return []
-
-    def get_linker_always_args(self) -> T.List[str]:
-        return []
-
-
-class VisualStudioLikeLinker:
-    always_args = ['/NOLOGO']
-
-    def __init__(self, machine: str):
-        self.machine = machine
-
-    def get_always_args(self) -> T.List[str]:
-        return self.always_args.copy()
-
-    def get_linker_always_args(self) -> T.List[str]:
-        return self.always_args.copy()
-
-    def get_output_args(self, target: str) -> T.List[str]:
-        args = []  # type: T.List[str]
-        if self.machine:
-            args += ['/MACHINE:' + self.machine]
-        args += ['/OUT:' + target]
-        return args
-
-    @classmethod
-    def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
-        from .compilers import VisualStudioCCompiler
-        return VisualStudioCCompiler.unix_args_to_native(args)
-
-    @classmethod
-    def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
-        from .compilers import VisualStudioCCompiler
-        return VisualStudioCCompiler.native_args_to_unix(args)
-
-
-class VisualStudioLinker(VisualStudioLikeLinker, StaticLinker):
-
-    """Microsoft's lib static linker."""
-
-    def __init__(self, exelist: T.List[str], machine: str):
-        StaticLinker.__init__(self, exelist)
-        VisualStudioLikeLinker.__init__(self, machine)
-
-
-class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker):
-
-    """Intel's xilib static linker."""
-
-    def __init__(self, exelist: T.List[str], machine: str):
-        StaticLinker.__init__(self, exelist)
-        VisualStudioLikeLinker.__init__(self, machine)
-
-
-class ArLinker(StaticLinker):
-
-    def __init__(self, exelist: T.List[str]):
-        super().__init__(exelist)
-        self.id = 'ar'
-        pc, stdo = mesonlib.Popen_safe(self.exelist + ['-h'])[0:2]
-        # Enable deterministic builds if they are available.
-        if '[D]' in stdo:
-            self.std_args = ['csrD']
-        else:
-            self.std_args = ['csr']
-
-    def get_std_link_args(self) -> T.List[str]:
-        return self.std_args
-
-    def get_output_args(self, target: str) -> T.List[str]:
-        return [target]
-
-
-class ArmarLinker(ArLinker):  # lgtm [py/missing-call-to-init]
-
-    def __init__(self, exelist: T.List[str]):
-        StaticLinker.__init__(self, exelist)
-        self.id = 'armar'
-        self.std_args = ['-csr']
-
-    def can_linker_accept_rsp(self) -> bool:
-        # armar can't accept arguments using the @rsp syntax
-        return False
-
-
-class DLinker(StaticLinker):
-    def __init__(self, exelist: T.List[str], arch: str):
-        super().__init__(exelist)
-        self.id = exelist[0]
-        self.arch = arch
-
-    def get_std_link_args(self) -> T.List[str]:
-        return ['-lib']
-
-    def get_output_args(self, target: str) -> T.List[str]:
-        return ['-of=' + target]
-
-    def get_linker_always_args(self) -> T.List[str]:
-        if mesonlib.is_windows():
-            if self.arch == 'x86_64':
-                return ['-m64']
-            elif self.arch == 'x86_mscoff' and self.id == 'dmd':
-                return ['-m32mscoff']
-            return ['-m32']
-        return []
-
-
-class CcrxLinker(StaticLinker):
-
-    def __init__(self, exelist: T.List[str]):
-        super().__init__(exelist)
-        self.id = 'rlink'
-
-    def can_linker_accept_rsp(self) -> bool:
-        return False
-
-    def get_output_args(self, target: str) -> T.List[str]:
-        return ['-output=%s' % target]
-
-    def get_linker_always_args(self) -> T.List[str]:
-        return ['-nologo', '-form=library']
-
-
-def prepare_rpaths(raw_rpaths: 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.
-    internal_format_rpaths = [evaluate_rpath(p, build_dir, from_dir) for p in raw_rpaths]
-    ordered_rpaths = order_rpaths(internal_format_rpaths)
-    return ordered_rpaths
-
-
-def order_rpaths(rpath_list: T.List[str]) -> T.List[str]:
-    # We want rpaths that point inside our build dir to always override
-    # those pointing to other places in the file system. This is so built
-    # binaries prefer our libraries to the ones that may lie somewhere
-    # in the file system, such as /lib/x86_64-linux-gnu.
-    #
-    # The correct thing to do here would be C++'s std::stable_partition.
-    # Python standard library does not have it, so replicate it with
-    # sort, which is guaranteed to be stable.
-    return sorted(rpath_list, key=os.path.isabs)
-
-
-def evaluate_rpath(p: str, build_dir: str, from_dir: str) -> str:
-    if p == from_dir:
-        return '' # relpath errors out in this case
-    elif os.path.isabs(p):
-        return p # These can be outside of build dir.
-    else:
-        return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir))
-
-
-class DynamicLinker(metaclass=abc.ABCMeta):
-
-    """Base class for dynamic linkers."""
-
-    _BUILDTYPE_ARGS = {
-        'plain': [],
-        'debug': [],
-        'debugoptimized': [],
-        'release': [],
-        'minsize': [],
-        'custom': [],
-    }  # type: T.Dict[str, T.List[str]]
-
-    def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]:
-        args = [arg] if isinstance(arg, str) else arg
-        if self.prefix_arg is None:
-            return args
-        elif isinstance(self.prefix_arg, str):
-            return [self.prefix_arg + arg for arg in args]
-        ret = []
-        for arg in args:
-            ret += self.prefix_arg + [arg]
-        return ret
-
-    def __init__(self, id_: str, exelist: T.List[str],
-                 for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]],
-                 always_args: T.List[str], *, version: str = 'unknown version'):
-        self.exelist = exelist
-        self.for_machine = for_machine
-        self.version = version
-        self.id = id_
-        self.prefix_arg = prefix_arg
-        self.always_args = always_args
-
-    def __repr__(self) -> str:
-        return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist))
-
-    def get_id(self) -> str:
-        return self.id
-
-    def get_version_string(self) -> str:
-        return '({} {})'.format(self.id, self.version)
-
-    def get_exelist(self) -> T.List[str]:
-        return self.exelist.copy()
-
-    def get_accepts_rsp(self) -> bool:
-        # rsp files are only used when building on Windows because we want to
-        # avoid issues with quoting and max argument length
-        return mesonlib.is_windows()
-
-    def get_always_args(self) -> T.List[str]:
-        return self.always_args.copy()
-
-    def get_lib_prefix(self) -> str:
-        return ''
-
-    # XXX: is use_ldflags a compiler or a linker attribute?
-
-    def get_args_from_envvars(self) -> T.List[str]:
-        flags = os.environ.get('LDFLAGS')
-        if not flags:
-            return []
-        return mesonlib.split_args(flags)
-
-    def get_option_args(self, options: 'OptionDictType') -> T.List[str]:
-        return []
-
-    def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
-        m = 'Language {} does not support has_multi_link_arguments.'
-        raise mesonlib.EnvironmentException(m.format(self.id))
-
-    def get_debugfile_args(self, targetfile: str) -> T.List[str]:
-        """Some compilers (MSVC) write debug into a separate file.
-
-        This method takes the target object path and returns a list of
-        commands to append to the linker invocation to control where that
-        file is written.
-        """
-        return []
-
-    def get_std_shared_lib_args(self) -> T.List[str]:
-        return []
-
-    def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
-        return self.get_std_shared_lib_args()
-
-    def get_pie_args(self) -> T.List[str]:
-        # TODO: this really needs to take a boolean and return the args to
-        # disable pie, otherwise it only acts to enable pie if pie *isn't* the
-        # default.
-        m = 'Linker {} does not support position-independent executable'
-        raise mesonlib.EnvironmentException(m.format(self.id))
-
-    def get_lto_args(self) -> T.List[str]:
-        return []
-
-    def sanitizer_args(self, value: str) -> T.List[str]:
-        return []
-
-    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
-        # We can override these in children by just overriding the
-        # _BUILDTYPE_ARGS value.
-        return self._BUILDTYPE_ARGS[buildtype]
-
-    def get_asneeded_args(self) -> T.List[str]:
-        return []
-
-    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
-        raise mesonlib.EnvironmentException(
-            'Linker {} does not support link_whole'.format(self.id))
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        raise mesonlib.EnvironmentException(
-            'Linker {} does not support allow undefined'.format(self.id))
-
-    @abc.abstractmethod
-    def get_output_args(self, outname: str) -> T.List[str]:
-        pass
-
-    def get_coverage_args(self) -> T.List[str]:
-        m = "Linker {} doesn't implement coverage data generation.".format(self.id)
-        raise mesonlib.EnvironmentException(m)
-
-    @abc.abstractmethod
-    def get_search_args(self, dirname: str) -> T.List[str]:
-        pass
-
-    def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
-        return []
-
-    def import_library_args(self, implibname: str) -> T.List[str]:
-        """The name of the outputted import library.
-
-        This implementation is used only on Windows by compilers that use GNU ld
-        """
-        return []
-
-    def thread_flags(self, env: 'Environment') -> T.List[str]:
-        return []
-
-    def no_undefined_args(self) -> T.List[str]:
-        """Arguments to error if there are any undefined symbols at link time.
-
-        This is the inverse of get_allow_undefined_args().
-
-        TODO: A future cleanup might merge this and
-              get_allow_undefined_args() into a single method taking a
-              boolean
-        """
-        return []
-
-    def fatal_warnings(self) -> T.List[str]:
-        """Arguments to make all warnings errors."""
-        return []
-
-    def bitcode_args(self) -> T.List[str]:
-        raise mesonlib.MesonException('This linker does not support bitcode bundles')
-
-    def get_debug_crt_args(self) -> T.List[str]:
-        return []
-
-    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
-                         rpath_paths: str, build_rpath: str,
-                         install_rpath: str) -> T.List[str]:
-        return []
-
-    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
-                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        return []
-
-
-class PosixDynamicLinkerMixin:
-
-    """Mixin class for POSIX-ish linkers.
-
-    This is obviously a pretty small subset of the linker interface, but
-    enough dynamic linkers that meson supports are POSIX-like but not
-    GNU-like that it makes sense to split this out.
-    """
-
-    def get_output_args(self, outname: str) -> T.List[str]:
-        return ['-o', outname]
-
-    def get_std_shared_lib_args(self) -> T.List[str]:
-        return ['-shared']
-
-    def get_search_args(self, dirname: str) -> T.List[str]:
-        return ['-L' + dirname]
-
-
-class GnuLikeDynamicLinkerMixin:
-
-    """Mixin class for dynamic linkers that provides gnu-like interface.
-
-    This acts as a base for the GNU linkers (bfd and gold), LLVM's lld, and
-    other linkers like GNU-ld.
-    """
-
-    _BUILDTYPE_ARGS = {
-        'plain': [],
-        'debug': [],
-        'debugoptimized': [],
-        'release': ['-O1'],
-        'minsize': [],
-        'custom': [],
-    }  # type: T.Dict[str, T.List[str]]
-
-    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
-        # We can override these in children by just overriding the
-        # _BUILDTYPE_ARGS value.
-        return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]])
-
-    def get_pie_args(self) -> T.List[str]:
-        return ['-pie']
-
-    def get_asneeded_args(self) -> T.List[str]:
-        return self._apply_prefix('--as-needed')
-
-    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
-        if not args:
-            return args
-        return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive')
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return self._apply_prefix('--allow-shlib-undefined')
-
-    def get_lto_args(self) -> T.List[str]:
-        return ['-flto']
-
-    def sanitizer_args(self, value: str) -> T.List[str]:
-        if value == 'none':
-            return []
-        return ['-fsanitize=' + value]
-
-    def get_coverage_args(self) -> T.List[str]:
-        return ['--coverage']
-
-    def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
-        m = env.machines[self.for_machine]
-        if m.is_windows() or m.is_cygwin():
-            return self._apply_prefix('--export-all-symbols')
-        return self._apply_prefix('-export-dynamic')
-
-    def import_library_args(self, implibname: str) -> T.List[str]:
-        return self._apply_prefix('--out-implib=' + implibname)
-
-    def thread_flags(self, env: 'Environment') -> T.List[str]:
-        if env.machines[self.for_machine].is_haiku():
-            return []
-        return ['-pthread']
-
-    def no_undefined_args(self) -> T.List[str]:
-        return self._apply_prefix('--no-undefined')
-
-    def fatal_warnings(self) -> T.List[str]:
-        return self._apply_prefix('--fatal-warnings')
-
-    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
-                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        m = env.machines[self.for_machine]
-        if m.is_windows() or m.is_cygwin():
-            # For PE/COFF the soname argument has no effect
-            return []
-        sostr = '' if soversion is None else '.' + soversion
-        return self._apply_prefix('-soname,{}{}.{}{}'.format(prefix, shlib_name, suffix, sostr))
-
-    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
-                         rpath_paths: str, build_rpath: str,
-                         install_rpath: str) -> T.List[str]:
-        m = env.machines[self.for_machine]
-        if m.is_windows() or m.is_cygwin():
-            return []
-        if not rpath_paths and not install_rpath and not build_rpath:
-            return []
-        args = []
-        origin_placeholder = '$ORIGIN'
-        processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
-        # Need to deduplicate rpaths, as macOS's install_name_tool
-        # is *very* allergic to duplicate -delete_rpath arguments
-        # when calling depfixer on installation.
-        all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
-        # Build_rpath is used as-is (it is usually absolute).
-        if build_rpath != '':
-            all_paths.add(build_rpath)
-
-        # TODO: should this actually be "for (dragonfly|open)bsd"?
-        if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd():
-            # This argument instructs the compiler to record the value of
-            # ORIGIN in the .dynamic section of the elf. On Linux this is done
-            # by default, but is not on dragonfly/openbsd for some reason. Without this
-            # $ORIGIN in the runtime path will be undefined and any binaries
-            # linked against local libraries will fail to resolve them.
-            args.extend(self._apply_prefix('-z,origin'))
-
-        # In order to avoid relinking for RPATH removal, the binary needs to contain just
-        # enough space in the ELF header to hold the final installation RPATH.
-        paths = ':'.join(all_paths)
-        if len(paths) < len(install_rpath):
-            padding = 'X' * (len(install_rpath) - len(paths))
-            if not paths:
-                paths = padding
-            else:
-                paths = paths + ':' + padding
-        args.extend(self._apply_prefix('-rpath,' + paths))
-
-        # TODO: should this actually be "for solaris/sunos"?
-        if mesonlib.is_sunos():
-            return args
-
-        # Rpaths to use while linking must be absolute. These are not
-        # written to the binary. Needed only with GNU ld:
-        # https://sourceware.org/bugzilla/show_bug.cgi?id=16936
-        # Not needed on Windows or other platforms that don't use RPATH
-        # https://github.com/mesonbuild/meson/issues/1897
-        #
-        # In addition, this linker option tends to be quite long and some
-        # compilers have trouble dealing with it. That's why we will include
-        # one option per folder, like this:
-        #
-        #   -Wl,-rpath-link,/path/to/folder1 -Wl,-rpath,/path/to/folder2 ...
-        #
-        # ...instead of just one single looooong option, like this:
-        #
-        #   -Wl,-rpath-link,/path/to/folder1:/path/to/folder2:...
-        for p in rpath_paths:
-            args.extend(self._apply_prefix('-rpath-link,' + os.path.join(build_dir, p)))
-
-        return args
-
-
-class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
-
-    """Apple's ld implementation."""
-
-    def __init__(self, *args, **kwargs):
-        super().__init__('ld64', *args, **kwargs)
-
-    def get_asneeded_args(self) -> T.List[str]:
-        return self._apply_prefix('-dead_strip_dylibs')
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return self._apply_prefix('-undefined,dynamic_lookup')
-
-    def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
-        return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup')
-
-    def get_pie_args(self) -> T.List[str]:
-        return ['-pie']
-
-    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
-        result = []  # type: T.List[str]
-        for a in args:
-            result.extend(self._apply_prefix('-force_load'))
-            result.append(a)
-        return result
-
-    def get_coverage_args(self) -> T.List[str]:
-        return ['--coverage']
-
-    def sanitizer_args(self, value: str) -> T.List[str]:
-        if value == 'none':
-            return []
-        return ['-fsanitize=' + value]
-
-    def no_undefined_args(self) -> T.List[str]:
-        return self._apply_prefix('-undefined,error')
-
-    def get_always_args(self) -> T.List[str]:
-        return self._apply_prefix('-headerpad_max_install_names') + super().get_always_args()
-
-    def bitcode_args(self) -> T.List[str]:
-        return self._apply_prefix('-bitcode_bundle')
-
-    def fatal_warnings(self) -> T.List[str]:
-        return self._apply_prefix('-fatal_warnings')
-
-    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
-                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        if is_shared_module:
-            return []
-        install_name = ['@rpath/', prefix, shlib_name]
-        if soversion is not None:
-            install_name.append('.' + soversion)
-        install_name.append('.dylib')
-        args = ['-install_name', ''.join(install_name)]
-        if darwin_versions:
-            args.extend(['-compatibility_version', darwin_versions[0],
-                         '-current_version', darwin_versions[1]])
-        return args
-
-    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
-                         rpath_paths: str, build_rpath: str,
-                         install_rpath: str) -> T.List[str]:
-        if not rpath_paths and not install_rpath and not build_rpath:
-            return []
-        # Ensure that there is enough space for install_name_tool in-place
-        # editing of large RPATHs
-        args = self._apply_prefix('-headerpad_max_install_names')
-        # @loader_path is the equivalent of $ORIGIN on macOS
-        # https://stackoverflow.com/q/26280738
-        origin_placeholder = '@loader_path'
-        processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
-        all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
-        if build_rpath != '':
-            all_paths.add(build_rpath)
-        for rp in all_paths:
-            args.extend(self._apply_prefix('-rpath,' + rp))
-
-        return args
-
-
-class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
-
-    """Representation of GNU ld.bfd and ld.gold."""
-
-
-class GnuGoldDynamicLinker(GnuDynamicLinker):
-
-    def __init__(self, *args, **kwargs):
-        super().__init__('ld.gold', *args, **kwargs)
-
-
-class GnuBFDDynamicLinker(GnuDynamicLinker):
-
-    def __init__(self, *args, **kwargs):
-        super().__init__('ld.bfd', *args, **kwargs)
-
-
-class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
-
-    """Representation of LLVM's ld.lld linker.
-
-    This is only the gnu-like linker, not the apple like or link.exe like
-    linkers.
-    """
-
-    def __init__(self, *args, **kwargs):
-        super().__init__('ld.lld', *args, **kwargs)
-
-
-class CcrxDynamicLinker(DynamicLinker):
-
-    """Linker for Renesis CCrx compiler."""
-
-    def __init__(self, for_machine: mesonlib.MachineChoice,
-                 *, version: str = 'unknown version'):
-        super().__init__('rlink', ['rlink.exe'], for_machine, '', [],
-                         version=version)
-
-    def get_accepts_rsp(self) -> bool:
-        return False
-
-    def get_lib_prefix(self) -> str:
-        return '-lib='
-
-    def get_std_shared_lib_args(self) -> T.List[str]:
-        return []
-
-    def get_output_args(self, outputname: str) -> T.List[str]:
-        return ['-output=%s' % outputname]
-
-    def get_search_args(self, dirname: str) -> 'T.NoReturn':
-        raise EnvironmentError('rlink.exe does not have a search dir argument')
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return []
-
-    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
-                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        return []
-
-
-class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
-
-    """Linker for the ARM compiler."""
-
-    def __init__(self, for_machine: mesonlib.MachineChoice,
-                 *, version: str = 'unknown version'):
-        super().__init__('armlink', ['armlink'], for_machine, '', [],
-                         version=version)
-
-    def get_accepts_rsp(self) -> bool:
-        return False
-
-    def get_std_shared_lib_args(self) -> 'T.NoReturn':
-        raise mesonlib.MesonException('The Arm Linkers do not support shared libraries')
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return []
-
-
-class ArmClangDynamicLinker(ArmDynamicLinker):
-
-    """Linker used with ARM's clang fork.
-
-    The interface is similar enough to the old ARM ld that it inherits and
-    extends a few things as needed.
-    """
-
-    def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
-        return ['--export_dynamic']
-
-    def import_library_args(self, implibname: str) -> T.List[str]:
-        return ['--symdefs=' + implibname]
-
-
-class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
-
-    """PGI linker."""
-
-    def __init__(self, *args, **kwargs):
-        super().__init__('pgi', *args, **kwargs)
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return []
-
-    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
-                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        return []
-
-    def get_std_shared_lib_args(self) -> T.List[str]:
-        # PGI -shared is Linux only.
-        if mesonlib.is_windows():
-            return ['-Bdynamic', '-Mmakedll']
-        elif mesonlib.is_linux():
-            return ['-shared']
-        return []
-
-    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
-                         rpath_paths: str, build_rpath: str,
-                         install_rpath: str) -> T.List[str]:
-        if not env.machines[self.for_machine].is_windows():
-            return ['-R' + os.path.join(build_dir, p) for p in rpath_paths]
-        return []
-
-
-class PGIStaticLinker(StaticLinker):
-    def __init__(self, exelist: T.List[str]):
-        super().__init__(exelist)
-        self.id = 'ar'
-        self.std_args = ['-r']
-
-    def get_std_link_args(self) -> T.List[str]:
-        return self.std_args
-
-    def get_output_args(self, target: str) -> T.List[str]:
-        return [target]
-
-
-class VisualStudioLikeLinkerMixin:
-
-    _BUILDTYPE_ARGS = {
-        'plain': [],
-        'debug': [],
-        'debugoptimized': [],
-        # The otherwise implicit REF and ICF linker optimisations are disabled by
-        # /DEBUG. REF implies ICF.
-        'release': ['/OPT:REF'],
-        'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
-        'custom': [],
-    }  # type: T.Dict[str, T.List[str]]
-
-    def __init__(self, *args, direct: bool = True, machine: str = 'x86', **kwargs):
-        super().__init__(*args, **kwargs)
-        self.machine = machine
-
-    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
-        return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]])
-
-    def invoked_by_compiler(self) -> bool:
-        return not self.direct
-
-    def get_debug_crt_args(self) -> T.List[str]:
-        """Arguments needed to select a debug crt for the linker.
-
-        Sometimes we need to manually select the CRT (C runtime) to use with
-        MSVC. One example is when trying to link with static libraries since
-        MSVC won't auto-select a CRT for us in that case and will error out
-        asking us to select one.
-        """
-        return self._apply_prefix('/MDd')
-
-    def get_output_args(self, outputname: str) -> T.List[str]:
-        return self._apply_prefix(['/MACHINE:' + self.machine, '/OUT:' + outputname])
-
-    def get_always_args(self) -> T.List[str]:
-        return self._apply_prefix('/nologo') + super().get_always_args()
-
-    def get_search_args(self, dirname: str) -> T.List[str]:
-        return self._apply_prefix('/LIBPATH:' + dirname)
-
-    def get_std_shared_lib_args(self) -> T.List[str]:
-        return self._apply_prefix('/DLL')
-
-    def get_debugfile_args(self, targetfile: str) -> T.List[str]:
-        pdbarr = targetfile.split('.')[:-1]
-        pdbarr += ['pdb']
-        return self._apply_prefix(['/DEBUG', '/PDB:' + '.'.join(pdbarr)])
-
-    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
-        # Only since VS2015
-        args = mesonlib.listify(args)
-        l = []  # T.List[str]
-        for a in args:
-            l.extend(self._apply_prefix('/WHOLEARCHIVE:' + a))
-        return l
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return []
-
-    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
-                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        return []
-
-
-class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
-
-    """Microsoft's Link.exe."""
-
-    def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
-                 exelist: T.Optional[T.List[str]] = None,
-                 prefix: T.Union[str, T.List[str]] = '',
-                 machine: str = 'x86', version: str = 'unknown version',
-                 direct: bool = True):
-        super().__init__('link', exelist or ['link.exe'], for_machine,
-                         prefix, always_args, machine=machine, version=version, direct=direct)
-
-    def get_always_args(self) -> T.List[str]:
-        return self._apply_prefix(['/nologo', '/release']) + super().get_always_args()
-
-
-class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
-
-    """Clang's lld-link.exe."""
-
-    def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
-                 exelist: T.Optional[T.List[str]] = None,
-                 prefix: T.Union[str, T.List[str]] = '',
-                 machine: str = 'x86', version: str = 'unknown version',
-                 direct: bool = True):
-        super().__init__('lld-link', exelist or ['lld-link.exe'], for_machine,
-                         prefix, always_args, machine=machine, version=version, direct=direct)
-
-
-class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
-
-    """Intel's Xilink.exe."""
-
-    def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str],
-                 *, version: str = 'unknown version'):
-        super().__init__('xilink', ['xilink.exe'], for_machine, '', always_args, version=version)
-
-
-class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
-
-    """Sys-V derived linker used on Solaris and OpenSolaris."""
-
-    def __init__(self, *args, **kwargs):
-        super().__init__('ld.solaris', *args, **kwargs)
-
-    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
-        if not args:
-            return args
-        return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive')
-
-    def no_undefined_args(self) -> T.List[str]:
-        return ['-z', 'defs']
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return ['-z', 'nodefs']
-
-    def fatal_warnings(self) -> T.List[str]:
-        return ['-z', 'fatal-warnings']
-
-    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
-                         rpath_paths: str, build_rpath: str,
-                         install_rpath: str) -> T.List[str]:
-        if not rpath_paths and not install_rpath and not build_rpath:
-            return []
-        processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
-        all_paths = mesonlib.OrderedSet([os.path.join('$ORIGIN', p) for p in processed_rpaths])
-        if build_rpath != '':
-            all_paths.add(build_rpath)
-
-        # In order to avoid relinking for RPATH removal, the binary needs to contain just
-        # enough space in the ELF header to hold the final installation RPATH.
-        paths = ':'.join(all_paths)
-        if len(paths) < len(install_rpath):
-            padding = 'X' * (len(install_rpath) - len(paths))
-            if not paths:
-                paths = padding
-            else:
-                paths = paths + ':' + padding
-        return self._apply_prefix('-rpath,{}'.format(paths))
-
-    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
-                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        sostr = '' if soversion is None else '.' + soversion
-        return self._apply_prefix('-soname,{}{}.{}{}'.format(prefix, shlib_name, suffix, sostr))
-
-
-class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
-
-    """Digital Mars dynamic linker for windows."""
-
-    def __init__(self, for_machine: mesonlib.MachineChoice,
-                 *, version: str = 'unknown version'):
-        # Use optlink instead of link so we don't interfer with other link.exe
-        # implementations.
-        super().__init__('optlink', ['optlink.exe'], for_machine, '', [], version=version)
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return []
-
-
-class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
-    """Cuda linker (nvlink)"""
-
-    def __init__(self, *args, **kwargs):
-        super().__init__('nvlink', *args, **kwargs)
-
-    @staticmethod
-    def parse_version():
-        version_cmd = ['nvlink', '--version']
-        try:
-            _, out, _ = mesonlib.Popen_safe(version_cmd)
-        except OSError:
-            return 'unknown version'
-        # Output example:
-        # nvlink: NVIDIA (R) Cuda linker
-        # Copyright (c) 2005-2018 NVIDIA Corporation
-        # Built on Sun_Sep_30_21:09:22_CDT_2018
-        # Cuda compilation tools, release 10.0, V10.0.166
-        # we need the most verbose version output. Luckily starting with V
-        return out.strip().split('V')[-1]
-
-    def get_accepts_rsp(self) -> bool:
-        # nvcc does not support response files
-        return False
-
-    def get_lib_prefix(self) -> str:
-        if not mesonlib.is_windows():
-            return ''
-        # nvcc doesn't recognize Meson's default .a extension for static libraries on
-        # Windows and passes it to cl as an object file, resulting in 'warning D9024 :
-        # unrecognized source file type 'xxx.a', object file assumed'.
-        #
-        # nvcc's --library= option doesn't help: it takes the library name without the
-        # extension and assumes that the extension on Windows is .lib; prefixing the
-        # library with -Xlinker= seems to work.
-        from .compilers import CudaCompiler
-        return CudaCompiler.LINKER_PREFIX
-
-    def fatal_warnings(self) -> T.List[str]:
-        return ['--warning-as-error']
-
-    def get_allow_undefined_args(self) -> T.List[str]:
-        return []
-
-    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
-                        suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
-                        is_shared_module: bool) -> T.List[str]:
-        return []
diff -Nru meson-0.53.2/mesonbuild/mcompile.py meson-0.61.2/mesonbuild/mcompile.py
--- meson-0.53.2/mesonbuild/mcompile.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mcompile.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,351 @@
+# Copyright 2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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.
+
+"""Entrypoint script for backend agnostic compile."""
+
+import os
+import json
+import re
+import sys
+import shutil
+import typing as T
+from collections import defaultdict
+from pathlib import Path
+
+from . import mlog
+from . import mesonlib
+from . import coredata
+from .mesonlib import MesonException, RealPathAction, setup_vsenv
+from mesonbuild.environment import detect_ninja
+from mesonbuild.coredata import UserArrayOption
+from mesonbuild import build
+
+if T.TYPE_CHECKING:
+    import argparse
+
+def array_arg(value: str) -> T.List[str]:
+    return UserArrayOption(None, value, allow_dups=True, user_input=True).value
+
+def validate_builddir(builddir: Path) -> None:
+    if not (builddir / 'meson-private' / 'coredata.dat').is_file():
+        raise MesonException(f'Current directory is not a meson build directory: `{builddir}`.\n'
+                             'Please specify a valid build dir or change the working directory to it.\n'
+                             'It is also possible that the build directory was generated with an old\n'
+                             'meson version. Please regenerate it in this case.')
+
+def parse_introspect_data(builddir: Path) -> T.Dict[str, T.List[dict]]:
+    """
+    Converts a List of name-to-dict to a dict of name-to-dicts (since names are not unique)
+    """
+    path_to_intro = builddir / 'meson-info' / 'intro-targets.json'
+    if not path_to_intro.exists():
+        raise MesonException(f'`{path_to_intro.name}` is missing! Directory is not configured yet?')
+    with path_to_intro.open(encoding='utf-8') as f:
+        schema = json.load(f)
+
+    parsed_data = defaultdict(list) # type: T.Dict[str, T.List[dict]]
+    for target in schema:
+        parsed_data[target['name']] += [target]
+    return parsed_data
+
+class ParsedTargetName:
+    full_name = ''
+    name = ''
+    type = ''
+    path = ''
+
+    def __init__(self, target: str):
+        self.full_name = target
+        split = target.rsplit(':', 1)
+        if len(split) > 1:
+            self.type = split[1]
+            if not self._is_valid_type(self.type):
+                raise MesonException(f'Can\'t invoke target `{target}`: unknown target type: `{self.type}`')
+
+        split = split[0].rsplit('/', 1)
+        if len(split) > 1:
+            self.path = split[0]
+            self.name = split[1]
+        else:
+            self.name = split[0]
+
+    @staticmethod
+    def _is_valid_type(type: str) -> bool:
+        # Amend docs in Commands.md when editing this list
+        allowed_types = {
+            'executable',
+            'static_library',
+            'shared_library',
+            'shared_module',
+            'custom',
+            'run',
+            'jar',
+        }
+        return type in allowed_types
+
+def get_target_from_intro_data(target: ParsedTargetName, builddir: Path, introspect_data: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]:
+    if target.name not in introspect_data:
+        raise MesonException(f'Can\'t invoke target `{target.full_name}`: target not found')
+
+    intro_targets = introspect_data[target.name]
+    found_targets = []  # type: T.List[T.Dict[str, T.Any]]
+
+    resolved_bdir = builddir.resolve()
+
+    if not target.type and not target.path:
+        found_targets = intro_targets
+    else:
+        for intro_target in intro_targets:
+            if (intro_target['subproject'] or
+                    (target.type and target.type != intro_target['type'].replace(' ', '_')) or
+                    (target.path
+                        and intro_target['filename'] != 'no_name'
+                        and Path(target.path) != Path(intro_target['filename'][0]).relative_to(resolved_bdir).parent)):
+                continue
+            found_targets += [intro_target]
+
+    if not found_targets:
+        raise MesonException(f'Can\'t invoke target `{target.full_name}`: target not found')
+    elif len(found_targets) > 1:
+        raise MesonException(f'Can\'t invoke target `{target.full_name}`: ambiguous name. Add target type and/or path: `PATH/NAME:TYPE`')
+
+    return found_targets[0]
+
+def generate_target_names_ninja(target: ParsedTargetName, builddir: Path, introspect_data: dict) -> T.List[str]:
+    intro_target = get_target_from_intro_data(target, builddir, introspect_data)
+
+    if intro_target['type'] == 'run':
+        return [target.name]
+    else:
+        return [str(Path(out_file).relative_to(builddir.resolve())) for out_file in intro_target['filename']]
+
+def get_parsed_args_ninja(options: 'argparse.Namespace', builddir: Path) -> T.Tuple[T.List[str], T.Optional[T.Dict[str, str]]]:
+    runner = detect_ninja()
+    if runner is None:
+        raise MesonException('Cannot find ninja.')
+
+    cmd = runner
+    if not builddir.samefile('.'):
+        cmd.extend(['-C', builddir.as_posix()])
+
+    # If the value is set to < 1 then don't set anything, which let's
+    # ninja/samu decide what to do.
+    if options.jobs > 0:
+        cmd.extend(['-j', str(options.jobs)])
+    if options.load_average > 0:
+        cmd.extend(['-l', str(options.load_average)])
+
+    if options.verbose:
+        cmd.append('-v')
+
+    cmd += options.ninja_args
+
+    # operands must be processed after options/option-arguments
+    if options.targets:
+        intro_data = parse_introspect_data(builddir)
+        for t in options.targets:
+            cmd.extend(generate_target_names_ninja(ParsedTargetName(t), builddir, intro_data))
+    if options.clean:
+        cmd.append('clean')
+
+    return cmd, None
+
+def generate_target_name_vs(target: ParsedTargetName, builddir: Path, introspect_data: dict) -> str:
+    intro_target = get_target_from_intro_data(target, builddir, introspect_data)
+
+    assert intro_target['type'] != 'run', 'Should not reach here: `run` targets must be handle above'
+
+    # Normalize project name
+    # Source: https://docs.microsoft.com/en-us/visualstudio/msbuild/how-to-build-specific-targets-in-solutions-by-using-msbuild-exe
+    target_name = re.sub(r"[\%\$\@\;\.\(\)']", '_', intro_target['id'])  # type: str
+    rel_path = Path(intro_target['filename'][0]).relative_to(builddir.resolve()).parent
+    if rel_path != Path('.'):
+        target_name = str(rel_path / target_name)
+    return target_name
+
+def get_parsed_args_vs(options: 'argparse.Namespace', builddir: Path) -> T.Tuple[T.List[str], T.Optional[T.Dict[str, str]]]:
+    slns = list(builddir.glob('*.sln'))
+    assert len(slns) == 1, 'More than one solution in a project?'
+    sln = slns[0]
+
+    cmd = ['msbuild']
+
+    if options.targets:
+        intro_data = parse_introspect_data(builddir)
+        has_run_target = any(map(
+            lambda t:
+                get_target_from_intro_data(ParsedTargetName(t), builddir, intro_data)['type'] == 'run',
+            options.targets
+        ))
+
+        if has_run_target:
+            # `run` target can't be used the same way as other targets on `vs` backend.
+            # They are defined as disabled projects, which can't be invoked as `.sln`
+            # target and have to be invoked directly as project instead.
+            # Issue: https://github.com/microsoft/msbuild/issues/4772
+
+            if len(options.targets) > 1:
+                raise MesonException('Only one target may be specified when `run` target type is used on this backend.')
+            intro_target = get_target_from_intro_data(ParsedTargetName(options.targets[0]), builddir, intro_data)
+            proj_dir = Path(intro_target['filename'][0]).parent
+            proj = proj_dir/'{}.vcxproj'.format(intro_target['id'])
+            cmd += [str(proj.resolve())]
+        else:
+            cmd += [str(sln.resolve())]
+            cmd.extend(['-target:{}'.format(generate_target_name_vs(ParsedTargetName(t), builddir, intro_data)) for t in options.targets])
+    else:
+        cmd += [str(sln.resolve())]
+
+    if options.clean:
+        cmd.extend(['-target:Clean'])
+
+    # In msbuild `-maxCpuCount` with no number means "detect cpus", the default is `-maxCpuCount:1`
+    if options.jobs > 0:
+        cmd.append(f'-maxCpuCount:{options.jobs}')
+    else:
+        cmd.append('-maxCpuCount')
+
+    if options.load_average:
+        mlog.warning('Msbuild does not have a load-average switch, ignoring.')
+
+    if not options.verbose:
+        cmd.append('-verbosity:minimal')
+
+    cmd += options.vs_args
+
+    # Remove platform from env if set so that msbuild does not
+    # pick x86 platform when solution platform is Win32
+    env = os.environ.copy()
+    env.pop('PLATFORM', None)
+
+    return cmd, env
+
+def get_parsed_args_xcode(options: 'argparse.Namespace', builddir: Path) -> T.Tuple[T.List[str], T.Optional[T.Dict[str, str]]]:
+    runner = 'xcodebuild'
+    if not shutil.which(runner):
+        raise MesonException('Cannot find xcodebuild, did you install XCode?')
+
+    # No argument to switch directory
+    os.chdir(str(builddir))
+
+    cmd = [runner, '-parallelizeTargets']
+
+    if options.targets:
+        for t in options.targets:
+            cmd += ['-target', t]
+
+    if options.clean:
+        if options.targets:
+            cmd += ['clean']
+        else:
+            cmd += ['-alltargets', 'clean']
+        # Otherwise xcodebuild tries to delete the builddir and fails
+        cmd += ['-UseNewBuildSystem=FALSE']
+
+    if options.jobs > 0:
+        cmd.extend(['-jobs', str(options.jobs)])
+
+    if options.load_average > 0:
+        mlog.warning('xcodebuild does not have a load-average switch, ignoring')
+
+    if options.verbose:
+        # xcodebuild is already quite verbose, and -quiet doesn't print any
+        # status messages
+        pass
+
+    cmd += options.xcode_args
+    return cmd, None
+
+def add_arguments(parser: 'argparse.ArgumentParser') -> None:
+    """Add compile specific arguments."""
+    parser.add_argument(
+        'targets',
+        metavar='TARGET',
+        nargs='*',
+        default=None,
+        help='Targets to build. Target has the following format: [PATH_TO_TARGET/]TARGET_NAME[:TARGET_TYPE].')
+    parser.add_argument(
+        '--clean',
+        action='store_true',
+        help='Clean the build directory.'
+    )
+    parser.add_argument('-C', dest='wd', action=RealPathAction,
+                        help='directory to cd into before running')
+
+    parser.add_argument(
+        '-j', '--jobs',
+        action='store',
+        default=0,
+        type=int,
+        help='The number of worker jobs to run (if supported). If the value is less than 1 the build program will guess.'
+    )
+    parser.add_argument(
+        '-l', '--load-average',
+        action='store',
+        default=0,
+        type=float,
+        help='The system load average to try to maintain (if supported).'
+    )
+    parser.add_argument(
+        '-v', '--verbose',
+        action='store_true',
+        help='Show more verbose output.'
+    )
+    parser.add_argument(
+        '--ninja-args',
+        type=array_arg,
+        default=[],
+        help='Arguments to pass to `ninja` (applied only on `ninja` backend).'
+    )
+    parser.add_argument(
+        '--vs-args',
+        type=array_arg,
+        default=[],
+        help='Arguments to pass to `msbuild` (applied only on `vs` backend).'
+    )
+    parser.add_argument(
+        '--xcode-args',
+        type=array_arg,
+        default=[],
+        help='Arguments to pass to `xcodebuild` (applied only on `xcode` backend).'
+    )
+
+def run(options: 'argparse.Namespace') -> int:
+    bdir = Path(options.wd)
+    validate_builddir(bdir)
+    if options.targets and options.clean:
+        raise MesonException('`TARGET` and `--clean` can\'t be used simultaneously')
+
+    cdata = coredata.load(options.wd)
+    b = build.load(options.wd)
+    setup_vsenv(b.need_vsenv)
+
+    cmd = []    # type: T.List[str]
+    env = None  # type: T.Optional[T.Dict[str, str]]
+
+    backend = cdata.get_option(mesonlib.OptionKey('backend'))
+    assert isinstance(backend, str)
+    if backend == 'ninja':
+        cmd, env = get_parsed_args_ninja(options, bdir)
+    elif backend.startswith('vs'):
+        cmd, env = get_parsed_args_vs(options, bdir)
+    elif backend == 'xcode':
+        cmd, env = get_parsed_args_xcode(options, bdir)
+    else:
+        raise MesonException(
+            f'Backend `{backend}` is not yet supported by `compile`. Use generated project files directly instead.')
+
+    p, *_ = mesonlib.Popen_safe(cmd, stdout=sys.stdout.buffer, stderr=sys.stderr.buffer, env=env)
+
+    return p.returncode
diff -Nru meson-0.53.2/mesonbuild/mconf.py meson-0.61.2/mesonbuild/mconf.py
--- meson-0.53.2/mesonbuild/mconf.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/mconf.py	2021-11-02 19:58:13.000000000 +0000
@@ -12,18 +12,33 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import itertools
+import shutil
 import os
-from . import coredata, environment, mesonlib, build, mintro, mlog
+import textwrap
+import typing as T
+import collections
+
+from . import build
+from . import coredata
+from . import environment
+from . import mesonlib
+from . import mintro
+from . import mlog
 from .ast import AstIDGenerator
+from .mesonlib import MachineChoice, OptionKey
 
-def add_arguments(parser):
+if T.TYPE_CHECKING:
+    import argparse
+    from .coredata import UserOption
+
+def add_arguments(parser: 'argparse.ArgumentParser') -> None:
     coredata.register_builtin_arguments(parser)
     parser.add_argument('builddir', nargs='?', default='.')
     parser.add_argument('--clearcache', action='store_true', default=False,
                         help='Clear cached state (e.g. found dependencies)')
 
-
-def make_lower_case(val):
+def make_lower_case(val: T.Any) -> T.Union[str, T.List[T.Any]]:  # T.Any because of recursion...
     if isinstance(val, bool):
         return str(val).lower()
     elif isinstance(val, list):
@@ -47,9 +62,10 @@
         self.value_col = []
         self.choices_col = []
         self.descr_col = []
+        # XXX: is there a case where this can actually remain false?
         self.has_choices = False
-        self.all_subprojects = set()
-        self.yielding_options = set()
+        self.all_subprojects: T.Set[str] = set()
+        self.yielding_options: T.Set[OptionKey] = set()
 
         if os.path.isdir(os.path.join(self.build_dir, 'meson-private')):
             self.build = build.load(self.build_dir)
@@ -67,11 +83,10 @@
             self.coredata = intr.coredata
             self.default_values_only = True
         else:
-            raise ConfException('Directory {} is neither a Meson build directory nor a project source directory.'.format(build_dir))
+            raise ConfException(f'Directory {build_dir} is neither a Meson build directory nor a project source directory.')
 
     def clear_cache(self):
-        self.coredata.deps.host.clear()
-        self.coredata.deps.build.clear()
+        self.coredata.clear_deps_cache()
 
     def set_options(self, options):
         self.coredata.set_options(options)
@@ -86,38 +101,76 @@
         # are erased when Meson is executed the next time, i.e. when
         # Ninja is run.
 
-    def print_aligned(self):
-        col_widths = (max([len(i) for i in self.name_col], default=0),
-                      max([len(i) for i in self.value_col], default=0),
-                      max([len(i) for i in self.choices_col], default=0))
+    def print_aligned(self) -> None:
+        """Do the actual printing.
+
+        This prints the generated output in an aligned, pretty form. it aims
+        for a total width of 160 characters, but will use whatever the tty
+        reports it's value to be. Though this is much wider than the standard
+        80 characters of terminals, and even than the newer 120, compressing
+        it to those lengths makes the output hard to read.
+
+        Each column will have a specific width, and will be line wrapped.
+        """
+        total_width = shutil.get_terminal_size(fallback=(160, 0))[0]
+        _col = max(total_width // 5, 20)
+        four_column = (_col, _col, _col, total_width - (3 * _col))
+        # In this case we don't have the choices field, so we can redistribute
+        # the extra 40 characters to val and desc
+        three_column = (_col, _col * 2, total_width // 2)
 
         for line in zip(self.name_col, self.value_col, self.choices_col, self.descr_col):
+            if not any(line):
+                print('')
+                continue
+
+            # This is a header, like `Subproject foo:`,
+            # We just want to print that and get on with it
+            if line[0] and not any(line[1:]):
+                print(line[0])
+                continue
+
+            # wrap will take a long string, and create a list of strings no
+            # longer than the size given. Then that list can be zipped into, to
+            # print each line of the output, such the that columns are printed
+            # to the right width, row by row.
             if self.has_choices:
-                print('{0:{width[0]}} {1:{width[1]}} {2:{width[2]}} {3}'.format(*line, width=col_widths))
+                name = textwrap.wrap(line[0], four_column[0])
+                val = textwrap.wrap(line[1], four_column[1])
+                choice = textwrap.wrap(line[2], four_column[2])
+                desc = textwrap.wrap(line[3], four_column[3])
+                for l in itertools.zip_longest(name, val, choice, desc, fillvalue=''):
+                    # We must use the length modifier here to get even rows, as
+                    # `textwrap.wrap` will only shorten, not lengthen each item
+                    print('{:{widths[0]}} {:{widths[1]}} {:{widths[2]}} {}'.format(*l, widths=four_column))
             else:
-                print('{0:{width[0]}} {1:{width[1]}} {3}'.format(*line, width=col_widths))
+                name = textwrap.wrap(line[0], three_column[0])
+                val = textwrap.wrap(line[1], three_column[1])
+                desc = textwrap.wrap(line[3], three_column[2])
+                for l in itertools.zip_longest(name, val, desc, fillvalue=''):
+                    print('{:{widths[0]}} {:{widths[1]}} {}'.format(*l, widths=three_column))
 
-    def split_options_per_subproject(self, options):
-        result = {}
+    def split_options_per_subproject(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, T.Dict[str, 'UserOption']]:
+        result: T.Dict[str, T.Dict[str, 'UserOption']] = {}
         for k, o in options.items():
-            subproject = ''
-            if ':' in k:
-                subproject, optname = k.split(':')
-                if o.yielding and optname in options:
+            subproject = k.subproject
+            if k.subproject:
+                k = k.as_root()
+                if o.yielding and k in options:
                     self.yielding_options.add(k)
                 self.all_subprojects.add(subproject)
-            result.setdefault(subproject, {})[k] = o
+            result.setdefault(subproject, {})[str(k)] = o
         return result
 
-    def _add_line(self, name, value, choices, descr):
-        self.name_col.append(' ' * self.print_margin + name)
+    def _add_line(self, name: OptionKey, value, choices, descr) -> None:
+        self.name_col.append(' ' * self.print_margin + str(name))
         self.value_col.append(value)
         self.choices_col.append(choices)
         self.descr_col.append(descr)
 
     def add_option(self, name, descr, value, choices):
         if isinstance(value, list):
-            value = '[{0}]'.format(', '.join(make_lower_case(value)))
+            value = '[{}]'.format(', '.join(make_lower_case(value)))
         else:
             value = make_lower_case(value)
 
@@ -159,7 +212,7 @@
         self._add_line(section + ':', '', '', '')
         self.print_margin = 2
 
-    def print_options(self, title, options):
+    def print_options(self, title: str, options: 'coredata.KeyedOptionDictType') -> None:
         if not options:
             return
         if title:
@@ -184,49 +237,46 @@
         if not self.default_values_only:
             print('  Build dir ', self.build_dir)
 
-        dir_option_names = ['bindir',
-                            'datadir',
-                            'includedir',
-                            'infodir',
-                            'libdir',
-                            'libexecdir',
-                            'localedir',
-                            'localstatedir',
-                            'mandir',
-                            'prefix',
-                            'sbindir',
-                            'sharedstatedir',
-                            'sysconfdir']
-        test_option_names = ['errorlogs',
-                             'stdsplit']
-        core_option_names = [k for k in self.coredata.builtins if k not in dir_option_names + test_option_names]
-
-        dir_options = {k: o for k, o in self.coredata.builtins.items() if k in dir_option_names}
-        test_options = {k: o for k, o in self.coredata.builtins.items() if k in test_option_names}
-        core_options = {k: o for k, o in self.coredata.builtins.items() if k in core_option_names}
-
-        def insert_build_prefix(k):
-            idx = k.find(':')
-            if idx < 0:
-                return 'build.' + k
-            return k[:idx + 1] + 'build.' + k[idx + 1:]
-
-        core_options = self.split_options_per_subproject(core_options)
-        host_compiler_options = self.split_options_per_subproject(self.coredata.compiler_options.host)
-        build_compiler_options = self.split_options_per_subproject({insert_build_prefix(k): o for k, o in self.coredata.compiler_options.build.items()})
-        project_options = self.split_options_per_subproject(self.coredata.user_options)
+        dir_option_names = set(coredata.BUILTIN_DIR_OPTIONS)
+        test_option_names = {OptionKey('errorlogs'),
+                             OptionKey('stdsplit')}
+
+        dir_options: 'coredata.KeyedOptionDictType' = {}
+        test_options: 'coredata.KeyedOptionDictType' = {}
+        core_options: 'coredata.KeyedOptionDictType' = {}
+        module_options: T.Dict[str, 'coredata.KeyedOptionDictType'] = collections.defaultdict(dict)
+        for k, v in self.coredata.options.items():
+            if k in dir_option_names:
+                dir_options[k] = v
+            elif k in test_option_names:
+                test_options[k] = v
+            elif k.module:
+                # Ignore module options if we did not use that module during
+                # configuration.
+                if self.build and k.module not in self.build.modules:
+                    continue
+                module_options[k.module][k] = v
+            elif k.is_builtin():
+                core_options[k] = v
+
+        host_core_options = self.split_options_per_subproject({k: v for k, v in core_options.items() if k.machine is MachineChoice.HOST})
+        build_core_options = self.split_options_per_subproject({k: v for k, v in core_options.items() if k.machine is MachineChoice.BUILD})
+        host_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_compiler() and k.machine is MachineChoice.HOST})
+        build_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_compiler() and k.machine is MachineChoice.BUILD})
+        project_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_project()})
         show_build_options = self.default_values_only or self.build.environment.is_cross_build()
 
         self.add_section('Main project options')
-        self.print_options('Core options', core_options[''])
-        self.print_options('', self.coredata.builtins_per_machine.host)
+        self.print_options('Core options', host_core_options[''])
         if show_build_options:
-            self.print_options('', {insert_build_prefix(k): o for k, o in self.coredata.builtins_per_machine.build.items()})
-        self.print_options('Backend options', self.coredata.backend_options)
-        self.print_options('Base options', self.coredata.base_options)
+            self.print_options('', build_core_options[''])
+        self.print_options('Backend options', {str(k): v for k, v in self.coredata.options.items() if k.is_backend()})
+        self.print_options('Base options', {str(k): v for k, v in self.coredata.options.items() if k.is_base()})
         self.print_options('Compiler options', host_compiler_options.get('', {}))
         if show_build_options:
             self.print_options('', build_compiler_options.get('', {}))
+        for mod, mod_options in module_options.items():
+            self.print_options(f'{mod} module options', mod_options)
         self.print_options('Directories', dir_options)
         self.print_options('Testing options', test_options)
         self.print_options('Project options', project_options.get('', {}))
@@ -234,8 +284,10 @@
             if subproject == '':
                 continue
             self.add_section('Subproject ' + subproject)
-            if subproject in core_options:
-                self.print_options('Core options', core_options[subproject])
+            if subproject in host_core_options:
+                self.print_options('Core options', host_core_options[subproject])
+            if subproject in build_core_options and show_build_options:
+                self.print_options('', build_core_options[subproject])
             if subproject in host_compiler_options:
                 self.print_options('Compiler options', host_compiler_options[subproject])
             if subproject in build_compiler_options and show_build_options:
@@ -249,6 +301,17 @@
             print('')
             print_default_values_warning()
 
+        self.print_nondefault_buildtype_options()
+
+    def print_nondefault_buildtype_options(self):
+        mismatching = self.coredata.get_nondefault_buildtype_args()
+        if not mismatching:
+            return
+        print("\nThe following option(s) have a different value than the build type default\n")
+        print('               current   default')
+        for m in mismatching:
+            print(f'{m[0]:21}{m[1]:10}{m[2]:10}')
+
 def run(options):
     coredata.parse_cmd_line_options(options)
     builddir = os.path.abspath(os.path.realpath(options.builddir))
@@ -260,7 +323,7 @@
             return 0
 
         save = False
-        if len(options.cmd_line_options) > 0:
+        if options.cmd_line_options:
             c.set_options(options.cmd_line_options)
             coredata.update_cmd_line_file(builddir, options)
             save = True
diff -Nru meson-0.53.2/mesonbuild/mdevenv.py meson-0.61.2/mesonbuild/mdevenv.py
--- meson-0.53.2/mesonbuild/mdevenv.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mdevenv.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,79 @@
+import os, subprocess
+import argparse
+import tempfile
+
+from pathlib import Path
+from . import build
+from .mesonlib import MesonException, RealPathAction, is_windows, setup_vsenv
+
+import typing as T
+
+def add_arguments(parser: argparse.ArgumentParser) -> None:
+    parser.add_argument('-C', dest='wd', action=RealPathAction,
+                        help='directory to cd into before running')
+    parser.add_argument('command', nargs=argparse.REMAINDER,
+                        help='Command to run in developer environment (default: interactive shell)')
+
+def get_windows_shell() -> str:
+    mesonbuild = Path(__file__).parent
+    script = mesonbuild / 'scripts' / 'cmd_or_ps.ps1'
+    command = ['powershell.exe', '-noprofile', '-executionpolicy', 'bypass', '-file', str(script)]
+    result = subprocess.check_output(command)
+    return result.decode().strip()
+
+def get_env(b: build.Build, build_dir: str) -> T.Dict[str, str]:
+    env = os.environ.copy()
+    for i in b.devenv:
+        env = i.get_env(env)
+
+    extra_env = build.EnvironmentVariables()
+    extra_env.set('MESON_DEVENV', ['1'])
+    extra_env.set('MESON_PROJECT_NAME', [b.project_name])
+
+    meson_uninstalled = Path(build_dir) / 'meson-uninstalled'
+    if meson_uninstalled.is_dir():
+        extra_env.prepend('PKG_CONFIG_PATH', [str(meson_uninstalled)])
+
+    return extra_env.get_env(env)
+
+def run(options: argparse.Namespace) -> int:
+    buildfile = Path(options.wd) / 'meson-private' / 'build.dat'
+    if not buildfile.is_file():
+        raise MesonException(f'Directory {options.wd!r} does not seem to be a Meson build directory.')
+    b = build.load(options.wd)
+    setup_vsenv(b.need_vsenv)
+
+    devenv = get_env(b, options.wd)
+
+    args = options.command
+    if not args:
+        prompt_prefix = f'[{b.project_name}]'
+        if is_windows():
+            shell = get_windows_shell()
+            if shell == 'powershell.exe':
+                args = ['powershell.exe']
+                args += ['-NoLogo', '-NoExit']
+                prompt = f'function global:prompt {{  "{prompt_prefix} PS " + $PWD + "> "}}'
+                args += ['-Command', prompt]
+            else:
+                args = [os.environ.get("COMSPEC", r"C:\WINDOWS\system32\cmd.exe")]
+                args += ['/k', f'prompt {prompt_prefix} $P$G']
+        else:
+            args = [os.environ.get("SHELL", os.path.realpath("/bin/sh"))]
+        if "bash" in args[0] and not os.environ.get("MESON_DISABLE_PS1_OVERRIDE"):
+            tmprc = tempfile.NamedTemporaryFile(mode='w')
+            bashrc = os.path.expanduser('~/.bashrc')
+            if os.path.exists(bashrc):
+                tmprc.write(f'. {bashrc}\n')
+            tmprc.write(f'export PS1="{prompt_prefix} $PS1"')
+            tmprc.flush()
+            # Let the GC remove the tmp file
+            args.append("--rcfile")
+            args.append(tmprc.name)
+
+    try:
+        return subprocess.call(args, close_fds=False,
+                               env=devenv,
+                               cwd=options.wd)
+    except subprocess.CalledProcessError as e:
+        return e.returncode
diff -Nru meson-0.53.2/mesonbuild/mdist.py meson-0.61.2/mesonbuild/mdist.py
--- meson-0.53.2/mesonbuild/mdist.py	2020-01-23 22:29:05.000000000 +0000
+++ meson-0.61.2/mesonbuild/mdist.py	2021-11-02 19:58:07.000000000 +0000
@@ -18,116 +18,161 @@
 import sys
 import shutil
 import subprocess
+import tarfile
+import tempfile
 import hashlib
 import json
 from glob import glob
 from pathlib import Path
 from mesonbuild.environment import detect_ninja
-from mesonbuild.mesonlib import windows_proof_rmtree, MesonException
+from mesonbuild.mesonlib import (MesonException, RealPathAction, quiet_git,
+                                 windows_proof_rmtree, setup_vsenv)
 from mesonbuild.wrap import wrap
 from mesonbuild import mlog, build
+from .scripts.meson_exe import run_exe
 
 archive_choices = ['gztar', 'xztar', 'zip']
+
 archive_extension = {'gztar': '.tar.gz',
                      'xztar': '.tar.xz',
                      'zip': '.zip'}
 
 def add_arguments(parser):
-    parser.add_argument('-C', default='.', dest='wd',
+    parser.add_argument('-C', dest='wd', action=RealPathAction,
                         help='directory to cd into before running')
     parser.add_argument('--formats', default='xztar',
-                        help='Comma separated list of archive types to create.')
+                        help='Comma separated list of archive types to create. Supports xztar (default), gztar, and zip.')
     parser.add_argument('--include-subprojects', action='store_true',
                         help='Include source code of subprojects that have been used for the build.')
+    parser.add_argument('--no-tests', action='store_true',
+                        help='Do not build and test generated packages.')
 
 
 def create_hash(fname):
     hashname = fname + '.sha256sum'
     m = hashlib.sha256()
     m.update(open(fname, 'rb').read())
-    with open(hashname, 'w') as f:
-        f.write('%s %s\n' % (m.hexdigest(), os.path.basename(fname)))
-
-
-def del_gitfiles(dirname):
-    for f in glob(os.path.join(dirname, '.git*')):
-        if os.path.isdir(f) and not os.path.islink(f):
-            windows_proof_rmtree(f)
-        else:
-            os.unlink(f)
+    with open(hashname, 'w', encoding='utf-8') as f:
+        # A space and an asterisk because that is the format defined by GNU coreutils
+        # and accepted by busybox and the Perl shasum tool.
+        f.write('{} *{}\n'.format(m.hexdigest(), os.path.basename(fname)))
+
+
+def copy_git(src, distdir, revision='HEAD', prefix=None, subdir=None):
+    cmd = ['git', 'archive', '--format', 'tar', revision]
+    if prefix is not None:
+        cmd.insert(2, f'--prefix={prefix}/')
+    if subdir is not None:
+        cmd.extend(['--', subdir])
+    with tempfile.TemporaryFile() as f:
+        subprocess.check_call(cmd, cwd=src, stdout=f)
+        f.seek(0)
+        t = tarfile.open(fileobj=f) # [ignore encoding]
+        t.extractall(path=distdir)
 
-def process_submodules(dirname):
-    module_file = os.path.join(dirname, '.gitmodules')
+def process_submodules(src, distdir):
+    module_file = os.path.join(src, '.gitmodules')
     if not os.path.exists(module_file):
         return
-    subprocess.check_call(['git', 'submodule', 'update', '--init', '--recursive'], cwd=dirname)
-    for line in open(module_file):
-        line = line.strip()
-        if '=' not in line:
-            continue
-        k, v = line.split('=', 1)
-        k = k.strip()
-        v = v.strip()
-        if k != 'path':
+    cmd = ['git', 'submodule', 'status', '--cached', '--recursive']
+    modlist = subprocess.check_output(cmd, cwd=src, universal_newlines=True).splitlines()
+    for submodule in modlist:
+        status = submodule[:1]
+        sha1, rest = submodule[1:].split(' ', 1)
+        subpath = rest.rsplit(' ', 1)[0]
+
+        if status == '-':
+            mlog.warning(f'Submodule {subpath!r} is not checked out and cannot be added to the dist')
             continue
-        del_gitfiles(os.path.join(dirname, v))
+        elif status in {'+', 'U'}:
+            mlog.warning(f'Submodule {subpath!r} has uncommitted changes that will not be included in the dist tarball')
+
+        copy_git(os.path.join(src, subpath), distdir, revision=sha1, prefix=subpath)
 
 
-def run_dist_scripts(dist_root, dist_scripts):
-    assert(os.path.isabs(dist_root))
-    env = os.environ.copy()
+def run_dist_scripts(src_root, bld_root, dist_root, dist_scripts, subprojects):
+    assert os.path.isabs(dist_root)
+    env = {}
     env['MESON_DIST_ROOT'] = dist_root
+    env['MESON_SOURCE_ROOT'] = src_root
+    env['MESON_BUILD_ROOT'] = bld_root
     for d in dist_scripts:
-        script = d['exe']
-        args = d['args']
-        name = ' '.join(script + args)
-        print('Running custom dist script {!r}'.format(name))
+        if d.subproject and d.subproject not in subprojects:
+            continue
+        subdir = subprojects.get(d.subproject, '')
+        env['MESON_PROJECT_DIST_ROOT'] = os.path.join(dist_root, subdir)
+        env['MESON_PROJECT_SOURCE_ROOT'] = os.path.join(src_root, subdir)
+        env['MESON_PROJECT_BUILD_ROOT'] = os.path.join(bld_root, subdir)
+        name = ' '.join(d.cmd_args)
+        print(f'Running custom dist script {name!r}')
         try:
-            rc = subprocess.call(script + args, env=env)
+            rc = run_exe(d, env)
             if rc != 0:
                 sys.exit('Dist script errored out')
         except OSError:
-            print('Failed to run dist script {!r}'.format(name))
+            print(f'Failed to run dist script {name!r}')
             sys.exit(1)
 
+def git_root(src_root):
+    # Cannot use --show-toplevel here because git in our CI prints cygwin paths
+    # that python cannot resolve. Workaround this by taking parent of src_root.
+    prefix = quiet_git(['rev-parse', '--show-prefix'], src_root, check=True)[1].strip()
+    if not prefix:
+        return Path(src_root)
+    prefix_level = len(Path(prefix).parents)
+    return Path(src_root).parents[prefix_level - 1]
+
 def is_git(src_root):
-    _git = os.path.join(src_root, '.git')
-    return os.path.isdir(_git) or os.path.isfile(_git)
+    '''
+    Checks if meson.build file at the root source directory is tracked by git.
+    It could be a subproject part of the parent project git repository.
+    '''
+    return quiet_git(['ls-files', '--error-unmatch', 'meson.build'], src_root)[0]
 
 def git_have_dirty_index(src_root):
     '''Check whether there are uncommitted changes in git'''
     ret = subprocess.call(['git', '-C', src_root, 'diff-index', '--quiet', 'HEAD'])
     return ret == 1
 
-def git_clone(src_root, distdir):
+def process_git_project(src_root, distdir):
     if git_have_dirty_index(src_root):
         mlog.warning('Repository has uncommitted changes that will not be included in the dist tarball')
     if os.path.exists(distdir):
-        shutil.rmtree(distdir)
-    os.makedirs(distdir)
-    subprocess.check_call(['git', 'clone', '--shared', src_root, distdir])
-    process_submodules(distdir)
-    del_gitfiles(distdir)
+        windows_proof_rmtree(distdir)
+    repo_root = git_root(src_root)
+    if repo_root.samefile(src_root):
+        os.makedirs(distdir)
+        copy_git(src_root, distdir)
+    else:
+        subdir = Path(src_root).relative_to(repo_root)
+        tmp_distdir = distdir + '-tmp'
+        if os.path.exists(tmp_distdir):
+            windows_proof_rmtree(tmp_distdir)
+        os.makedirs(tmp_distdir)
+        copy_git(repo_root, tmp_distdir, subdir=str(subdir))
+        Path(tmp_distdir, subdir).rename(distdir)
+        windows_proof_rmtree(tmp_distdir)
+    process_submodules(src_root, distdir)
 
 def create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, dist_scripts, subprojects):
     distdir = os.path.join(dist_sub, dist_name)
-    git_clone(src_root, distdir)
-    for path in subprojects:
+    process_git_project(src_root, distdir)
+    for path in subprojects.values():
         sub_src_root = os.path.join(src_root, path)
         sub_distdir = os.path.join(distdir, path)
         if os.path.exists(sub_distdir):
             continue
         if is_git(sub_src_root):
-            git_clone(sub_src_root, sub_distdir)
+            process_git_project(sub_src_root, sub_distdir)
         else:
             shutil.copytree(sub_src_root, sub_distdir)
-    run_dist_scripts(distdir, dist_scripts)
+    run_dist_scripts(src_root, bld_root, distdir, dist_scripts, subprojects)
     output_names = []
     for a in archives:
         compressed_name = distdir + archive_extension[a]
         shutil.make_archive(distdir, a, root_dir=dist_sub, base_dir=dist_name)
         output_names.append(compressed_name)
-    shutil.rmtree(distdir)
+    windows_proof_rmtree(distdir)
     return output_names
 
 def is_hg(src_root):
@@ -141,16 +186,25 @@
 def create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, dist_scripts):
     if hg_have_dirty_index(src_root):
         mlog.warning('Repository has uncommitted changes that will not be included in the dist tarball')
+    if dist_scripts:
+        mlog.warning('dist scripts are not supported in Mercurial projects')
 
     os.makedirs(dist_sub, exist_ok=True)
     tarname = os.path.join(dist_sub, dist_name + '.tar')
     xzname = tarname + '.xz'
     gzname = tarname + '.gz'
     zipname = os.path.join(dist_sub, dist_name + '.zip')
-    subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'tar', tarname])
+    # Note that -X interprets relative paths using the current working
+    # directory, not the repository root, so this must be an absolute path:
+    # https://bz.mercurial-scm.org/show_bug.cgi?id=6267
+    #
+    # .hg[a-z]* is used instead of .hg* to keep .hg_archival.txt, which may
+    # be useful to link the tarball to the Mercurial revision for either
+    # manual inspection or in case any code interprets it for a --version or
+    # similar.
+    subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'tar',
+                           '-X', src_root + '/.hg[a-z]*', tarname])
     output_names = []
-    if dist_scripts:
-        mlog.warning('dist scripts are not supported in Mercurial projects')
     if 'xztar' in archives:
         import lzma
         with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf:
@@ -166,66 +220,71 @@
         output_names.append(zipname)
     return output_names
 
+def run_dist_steps(meson_command, unpacked_src_dir, builddir, installdir, ninja_args):
+    if subprocess.call(meson_command + ['--backend=ninja', unpacked_src_dir, builddir]) != 0:
+        print('Running Meson on distribution package failed')
+        return 1
+    if subprocess.call(ninja_args, cwd=builddir) != 0:
+        print('Compiling the distribution package failed')
+        return 1
+    if subprocess.call(ninja_args + ['test'], cwd=builddir) != 0:
+        print('Running unit tests on the distribution package failed')
+        return 1
+    myenv = os.environ.copy()
+    myenv['DESTDIR'] = installdir
+    if subprocess.call(ninja_args + ['install'], cwd=builddir, env=myenv) != 0:
+        print('Installing the distribution package failed')
+        return 1
+    return 0
 
 def check_dist(packagename, meson_command, extra_meson_args, bld_root, privdir):
-    print('Testing distribution package %s' % packagename)
+    print(f'Testing distribution package {packagename}')
     unpackdir = os.path.join(privdir, 'dist-unpack')
     builddir = os.path.join(privdir, 'dist-build')
     installdir = os.path.join(privdir, 'dist-install')
     for p in (unpackdir, builddir, installdir):
         if os.path.exists(p):
-            shutil.rmtree(p)
+            windows_proof_rmtree(p)
         os.mkdir(p)
-    ninja_bin = detect_ninja()
-    try:
-        shutil.unpack_archive(packagename, unpackdir)
-        unpacked_files = glob(os.path.join(unpackdir, '*'))
-        assert(len(unpacked_files) == 1)
-        unpacked_src_dir = unpacked_files[0]
-        with open(os.path.join(bld_root, 'meson-info', 'intro-buildoptions.json')) as boptions:
-            meson_command += ['-D{name}={value}'.format(**o) for o in json.load(boptions)
-                              if o['name'] not in ['backend', 'install_umask']]
-        meson_command += extra_meson_args
-        if subprocess.call(meson_command + ['--backend=ninja', unpacked_src_dir, builddir]) != 0:
-            print('Running Meson on distribution package failed')
-            return 1
-        if subprocess.call([ninja_bin], cwd=builddir) != 0:
-            print('Compiling the distribution package failed')
-            return 1
-        if subprocess.call([ninja_bin, 'test'], cwd=builddir) != 0:
-            print('Running unit tests on the distribution package failed')
-            return 1
-        myenv = os.environ.copy()
-        myenv['DESTDIR'] = installdir
-        if subprocess.call([ninja_bin, 'install'], cwd=builddir, env=myenv) != 0:
-            print('Installing the distribution package failed')
-            return 1
-    finally:
-        shutil.rmtree(unpackdir)
-        shutil.rmtree(builddir)
-        shutil.rmtree(installdir)
-    print('Distribution package %s tested' % packagename)
-    return 0
+    ninja_args = detect_ninja()
+    shutil.unpack_archive(packagename, unpackdir)
+    unpacked_files = glob(os.path.join(unpackdir, '*'))
+    assert len(unpacked_files) == 1
+    unpacked_src_dir = unpacked_files[0]
+    with open(os.path.join(bld_root, 'meson-info', 'intro-buildoptions.json'), encoding='utf-8') as boptions:
+        meson_command += ['-D{name}={value}'.format(**o) for o in json.load(boptions)
+                          if o['name'] not in ['backend', 'install_umask', 'buildtype']]
+    meson_command += extra_meson_args
+
+    ret = run_dist_steps(meson_command, unpacked_src_dir, builddir, installdir, ninja_args)
+    if ret > 0:
+        print(f'Dist check build directory was {builddir}')
+    else:
+        windows_proof_rmtree(unpackdir)
+        windows_proof_rmtree(builddir)
+        windows_proof_rmtree(installdir)
+        print(f'Distribution package {packagename} tested')
+    return ret
 
 def determine_archives_to_generate(options):
     result = []
     for i in options.formats.split(','):
         if i not in archive_choices:
-            sys.exit('Value "{}" not one of permitted values {}.'.format(i, archive_choices))
+            sys.exit(f'Value "{i}" not one of permitted values {archive_choices}.')
         result.append(i)
     if len(i) == 0:
         sys.exit('No archive types specified.')
     return result
 
 def run(options):
-    options.wd = os.path.abspath(options.wd)
     buildfile = Path(options.wd) / 'meson-private' / 'build.dat'
     if not buildfile.is_file():
-        raise MesonException('Directory {!r} does not seem to be a Meson build directory.'.format(options.wd))
+        raise MesonException(f'Directory {options.wd!r} does not seem to be a Meson build directory.')
     b = build.load(options.wd)
+    setup_vsenv(b.need_vsenv)
     # This import must be load delayed, otherwise it will get the default
     # value of None.
-    from mesonbuild.mesonlib import meson_command
+    from mesonbuild.mesonlib import get_meson_command
     src_root = b.environment.source_dir
     bld_root = b.environment.build_dir
     priv_dir = os.path.join(bld_root, 'meson-private')
@@ -235,13 +294,13 @@
 
     archives = determine_archives_to_generate(options)
 
-    subprojects = []
+    subprojects = {}
     extra_meson_args = []
     if options.include_subprojects:
         subproject_dir = os.path.join(src_root, b.subproject_dir)
         for sub in b.subprojects:
-            _, directory = wrap.get_directory(subproject_dir, sub)
-            subprojects.append(os.path.join(b.subproject_dir, directory))
+            directory = wrap.get_directory(subproject_dir, sub)
+            subprojects[sub] = os.path.join(b.subproject_dir, directory)
         extra_meson_args.append('-Dwrap_mode=nodownload')
 
     if is_git(src_root):
@@ -256,9 +315,12 @@
         return 1
     if names is None:
         return 1
-    # Check only one.
-    rc = check_dist(names[0], meson_command, extra_meson_args, bld_root, priv_dir)
+    rc = 0
+    if not options.no_tests:
+        # Check only one.
+        rc = check_dist(names[0], get_meson_command(), extra_meson_args, bld_root, priv_dir)
     if rc == 0:
         for name in names:
             create_hash(name)
+            print('Created', name)
     return rc
diff -Nru meson-0.53.2/mesonbuild/mesondata.py meson-0.61.2/mesonbuild/mesondata.py
--- meson-0.53.2/mesonbuild/mesondata.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesondata.py	2022-01-17 10:50:45.000000000 +0000
@@ -0,0 +1,394 @@
+# Copyright 2021 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 tools/gen_data.py
+####
+
+
+# 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 #
+######################
+
+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 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 = {
+    '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 -Nru meson-0.53.2/mesonbuild/mesonlib/__init__.py meson-0.61.2/mesonbuild/mesonlib/__init__.py
--- meson-0.53.2/mesonbuild/mesonlib/__init__.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesonlib/__init__.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,31 @@
+# SPDX-license-identifier: Apache-2.0
+# Copyright 2012-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+# 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.
+
+"""Helper functions and classes."""
+
+import os
+
+from .universal import *
+from .vsenv import setup_vsenv
+
+# Here we import either the posix implementations, the windows implementations,
+# or a generic no-op implementation
+if os.name == 'posix':
+    from .posix import *
+elif os.name == 'nt':
+    from .win32 import *
+else:
+    from .platform import *
diff -Nru meson-0.53.2/mesonbuild/mesonlib/platform.py meson-0.61.2/mesonbuild/mesonlib/platform.py
--- meson-0.53.2/mesonbuild/mesonlib/platform.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesonlib/platform.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,37 @@
+# SPDX-license-identifier: Apache-2.0
+# Copyright 2012-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+# 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.
+
+"""base classes providing no-op functionality.."""
+
+import os
+import typing as T
+
+from .. import mlog
+
+__all__ = ['BuildDirLock']
+
+# This needs to be inherited by the specific implementations to make type
+# checking happy
+class BuildDirLock:
+
+    def __init__(self, builddir: str) -> None:
+        self.lockfilename = os.path.join(builddir, 'meson-private/meson.lock')
+
+    def __enter__(self) -> None:
+        mlog.debug('Calling the no-op version of BuildDirLock')
+
+    def __exit__(self, *args: T.Any) -> None:
+        pass
diff -Nru meson-0.53.2/mesonbuild/mesonlib/posix.py meson-0.61.2/mesonbuild/mesonlib/posix.py
--- meson-0.53.2/mesonbuild/mesonlib/posix.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesonlib/posix.py	2021-07-20 08:56:20.000000000 +0000
@@ -0,0 +1,39 @@
+# SPDX-license-identifier: Apache-2.0
+# Copyright 2012-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+# 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.
+
+"""Posix specific implementations of mesonlib functionality."""
+
+import fcntl
+import typing as T
+
+from .universal import MesonException
+from .platform import BuildDirLock as BuildDirLockBase
+
+__all__ = ['BuildDirLock']
+
+class BuildDirLock(BuildDirLockBase):
+
+    def __enter__(self) -> None:
+        self.lockfile = open(self.lockfilename, 'w', encoding='utf-8')
+        try:
+            fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
+        except (BlockingIOError, PermissionError):
+            self.lockfile.close()
+            raise MesonException('Some other Meson process is already using this build directory. Exiting.')
+
+    def __exit__(self, *args: T.Any) -> None:
+        fcntl.flock(self.lockfile, fcntl.LOCK_UN)
+        self.lockfile.close()
diff -Nru meson-0.53.2/mesonbuild/mesonlib/universal.py meson-0.61.2/mesonbuild/mesonlib/universal.py
--- meson-0.53.2/mesonbuild/mesonlib/universal.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesonlib/universal.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,2216 @@
+# Copyright 2012-2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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.
+
+"""A library of random helper functionality."""
+from pathlib import Path
+import argparse
+import enum
+import sys
+import stat
+import time
+import abc
+import platform, subprocess, operator, os, shlex, shutil, re
+import collections
+from functools import lru_cache, wraps, total_ordering
+from itertools import tee, filterfalse
+from tempfile import TemporaryDirectory
+import typing as T
+import uuid
+import textwrap
+import copy
+
+from mesonbuild import mlog
+
+if T.TYPE_CHECKING:
+    from .._typing import ImmutableListProtocol
+    from ..build import ConfigurationData
+    from ..coredata import KeyedOptionDictType, UserOption
+    from ..compilers.compilers import Compiler
+
+FileOrString = T.Union['File', str]
+
+_T = T.TypeVar('_T')
+_U = T.TypeVar('_U')
+
+__all__ = [
+    'GIT',
+    'python_command',
+    'project_meson_versions',
+    'HoldableObject',
+    'SecondLevelHolder',
+    'File',
+    'FileMode',
+    'GitException',
+    'LibType',
+    'MachineChoice',
+    'MesonException',
+    'MesonBugException',
+    'EnvironmentException',
+    'FileOrString',
+    'GitException',
+    'OptionKey',
+    'dump_conf_header',
+    'OptionOverrideProxy',
+    'OptionType',
+    'OrderedSet',
+    'PerMachine',
+    'PerMachineDefaultable',
+    'PerThreeMachine',
+    'PerThreeMachineDefaultable',
+    'ProgressBar',
+    'RealPathAction',
+    'TemporaryDirectoryWinProof',
+    'Version',
+    'check_direntry_issues',
+    'classify_unity_sources',
+    'current_vs_supports_modules',
+    'darwin_get_object_archs',
+    'default_libdir',
+    'default_libexecdir',
+    'default_prefix',
+    'detect_subprojects',
+    'detect_vcs',
+    'do_conf_file',
+    'do_conf_str',
+    'do_replacement',
+    'exe_exists',
+    'expand_arguments',
+    'extract_as_list',
+    'generate_list',
+    'get_compiler_for_source',
+    'get_filenames_templates_dict',
+    'get_library_dirs',
+    'get_variable_regex',
+    'get_wine_shortpath',
+    'git',
+    'has_path_sep',
+    'is_aix',
+    'is_android',
+    'is_ascii_string',
+    'is_cygwin',
+    'is_debianlike',
+    'is_dragonflybsd',
+    'is_freebsd',
+    'is_haiku',
+    'is_hurd',
+    'is_irix',
+    'is_linux',
+    'is_netbsd',
+    'is_openbsd',
+    'is_osx',
+    'is_qnx',
+    'is_sunos',
+    'is_windows',
+    'is_wsl',
+    'iter_regexin_iter',
+    'join_args',
+    'listify',
+    'partition',
+    'path_is_in_root',
+    'Popen_safe',
+    'quiet_git',
+    'quote_arg',
+    'relative_to_if_possible',
+    'relpath',
+    'replace_if_different',
+    'run_once',
+    'get_meson_command',
+    'set_meson_command',
+    'split_args',
+    'stringlistify',
+    'substitute_values',
+    'substring_is_in_list',
+    'typeslistify',
+    'verbose_git',
+    'version_compare',
+    'version_compare_condition_with_min',
+    'version_compare_many',
+    'search_version',
+    'windows_proof_rm',
+    'windows_proof_rmtree',
+]
+
+
+# TODO: this is such a hack, this really should be either in coredata or in the
+# interpreter
+# {subproject: project_meson_version}
+project_meson_versions = collections.defaultdict(str)  # type: T.DefaultDict[str, str]
+
+
+from glob import glob
+
+if os.path.basename(sys.executable) == 'meson.exe':
+    # In Windows and using the MSI installed executable.
+    python_command = [sys.executable, 'runpython']
+else:
+    python_command = [sys.executable]
+_meson_command: T.Optional['ImmutableListProtocol[str]'] = None
+
+class MesonException(Exception):
+    '''Exceptions thrown by Meson'''
+
+    def __init__(self, *args: object, file: T.Optional[str] = None,
+                 lineno: T.Optional[int] = None, colno: T.Optional[int] = None):
+        super().__init__(*args)
+        self.file = file
+        self.lineno = lineno
+        self.colno = colno
+
+
+class MesonBugException(MesonException):
+    '''Exceptions thrown when there is a clear Meson bug that should be reported'''
+
+    def __init__(self, msg: str, file: T.Optional[str] = None,
+                 lineno: T.Optional[int] = None, colno: T.Optional[int] = None):
+        super().__init__(msg + '\n\n    This is a Meson bug and should be reported!',
+                         file=file, lineno=lineno, colno=colno)
+
+class EnvironmentException(MesonException):
+    '''Exceptions thrown while processing and creating the build environment'''
+
+class GitException(MesonException):
+    def __init__(self, msg: str, output: T.Optional[str] = None):
+        super().__init__(msg)
+        self.output = output.strip() if output else ''
+
+GIT = shutil.which('git')
+def git(cmd: T.List[str], workingdir: str, check: bool = False, **kwargs: T.Any) -> T.Tuple[subprocess.Popen, str, str]:
+    cmd = [GIT] + cmd
+    p, o, e = Popen_safe(cmd, cwd=workingdir, **kwargs)
+    if check and p.returncode != 0:
+        raise GitException('Git command failed: ' + str(cmd), e)
+    return p, o, e
+
+def quiet_git(cmd: T.List[str], workingdir: str, check: bool = False) -> T.Tuple[bool, str]:
+    if not GIT:
+        m = 'Git program not found.'
+        if check:
+            raise GitException(m)
+        return False, m
+    p, o, e = git(cmd, workingdir, check)
+    if p.returncode != 0:
+        return False, e
+    return True, o
+
+def verbose_git(cmd: T.List[str], workingdir: str, check: bool = False) -> bool:
+    if not GIT:
+        m = 'Git program not found.'
+        if check:
+            raise GitException(m)
+        return False
+    p, _, _ = git(cmd, workingdir, check, stdout=None, stderr=None)
+    return p.returncode == 0
+
+def set_meson_command(mainfile: str) -> None:
+    global python_command
+    global _meson_command
+    # On UNIX-like systems `meson` is a Python script
+    # On Windows `meson` and `meson.exe` are wrapper exes
+    if not mainfile.endswith('.py'):
+        _meson_command = [mainfile]
+    elif os.path.isabs(mainfile) and mainfile.endswith('mesonmain.py'):
+        # Can't actually run meson with an absolute path to mesonmain.py, it must be run as -m mesonbuild.mesonmain
+        _meson_command = python_command + ['-m', 'mesonbuild.mesonmain']
+    else:
+        # Either run uninstalled, or full path to meson-script.py
+        _meson_command = python_command + [mainfile]
+    # We print this value for unit tests.
+    if 'MESON_COMMAND_TESTS' in os.environ:
+        mlog.log(f'meson_command is {_meson_command!r}')
+
+
+def get_meson_command() -> T.Optional['ImmutableListProtocol[str]']:
+    return _meson_command
+
+
+def is_ascii_string(astring: T.Union[str, bytes]) -> bool:
+    try:
+        if isinstance(astring, str):
+            astring.encode('ascii')
+        elif isinstance(astring, bytes):
+            astring.decode('ascii')
+    except UnicodeDecodeError:
+        return False
+    return True
+
+
+def check_direntry_issues(direntry_array: T.Union[T.List[T.Union[str, bytes]], str, bytes]) -> None:
+    import locale
+    # Warn if the locale is not UTF-8. This can cause various unfixable issues
+    # such as os.stat not being able to decode filenames with unicode in them.
+    # There is no way to reset both the preferred encoding and the filesystem
+    # encoding, so we can just warn about it.
+    e = locale.getpreferredencoding()
+    if e.upper() != 'UTF-8' and not is_windows():
+        if not isinstance(direntry_array, list):
+            direntry_array = [direntry_array]
+        for de in direntry_array:
+            if is_ascii_string(de):
+                continue
+            mlog.warning(textwrap.dedent(f'''
+                You are using {e!r} which is not a Unicode-compatible
+                locale but you are trying to access a file system entry called {de!r} which is
+                not pure ASCII. This may cause problems.
+                '''), file=sys.stderr)
+
+class HoldableObject(metaclass=abc.ABCMeta):
+    ''' Dummy base class for all objects that can be
+        held by an interpreter.baseobjects.ObjectHolder '''
+
+class SecondLevelHolder(HoldableObject, metaclass=abc.ABCMeta):
+    ''' A second level object holder. The primary purpose
+        of such objects is to hold multiple objects with one
+        default option. '''
+
+    @abc.abstractmethod
+    def get_default_object(self) -> HoldableObject: ...
+
+class FileMode:
+    # The first triad is for owner permissions, the second for group permissions,
+    # and the third for others (everyone else).
+    # For the 1st character:
+    #  'r' means can read
+    #  '-' means not allowed
+    # For the 2nd character:
+    #  'w' means can write
+    #  '-' means not allowed
+    # For the 3rd character:
+    #  'x' means can execute
+    #  's' means can execute and setuid/setgid is set (owner/group triads only)
+    #  'S' means cannot execute and setuid/setgid is set (owner/group triads only)
+    #  't' means can execute and sticky bit is set ("others" triads only)
+    #  'T' means cannot execute and sticky bit is set ("others" triads only)
+    #  '-' means none of these are allowed
+    #
+    # The meanings of 'rwx' perms is not obvious for directories; see:
+    # https://www.hackinglinuxexposed.com/articles/20030424.html
+    #
+    # For information on this notation such as setuid/setgid/sticky bits, see:
+    # https://en.wikipedia.org/wiki/File_system_permissions#Symbolic_notation
+    symbolic_perms_regex = re.compile('[r-][w-][xsS-]' # Owner perms
+                                      '[r-][w-][xsS-]' # Group perms
+                                      '[r-][w-][xtT-]') # Others perms
+
+    def __init__(self, perms: T.Optional[str] = None, owner: T.Union[str, int, None] = None,
+                 group: T.Union[str, int, None] = None):
+        self.perms_s = perms
+        self.perms = self.perms_s_to_bits(perms)
+        self.owner = owner
+        self.group = group
+
+    def __repr__(self) -> str:
+        ret = ' int:
+        '''
+        Does the opposite of stat.filemode(), converts strings of the form
+        'rwxr-xr-x' to st_mode enums which can be passed to os.chmod()
+        '''
+        if perms_s is None:
+            # No perms specified, we will not touch the permissions
+            return -1
+        eg = 'rwxr-xr-x'
+        if not isinstance(perms_s, str):
+            raise MesonException(f'Install perms must be a string. For example, {eg!r}')
+        if len(perms_s) != 9 or not cls.symbolic_perms_regex.match(perms_s):
+            raise MesonException(f'File perms {perms_s!r} must be exactly 9 chars. For example, {eg!r}')
+        perms = 0
+        # Owner perms
+        if perms_s[0] == 'r':
+            perms |= stat.S_IRUSR
+        if perms_s[1] == 'w':
+            perms |= stat.S_IWUSR
+        if perms_s[2] == 'x':
+            perms |= stat.S_IXUSR
+        elif perms_s[2] == 'S':
+            perms |= stat.S_ISUID
+        elif perms_s[2] == 's':
+            perms |= stat.S_IXUSR
+            perms |= stat.S_ISUID
+        # Group perms
+        if perms_s[3] == 'r':
+            perms |= stat.S_IRGRP
+        if perms_s[4] == 'w':
+            perms |= stat.S_IWGRP
+        if perms_s[5] == 'x':
+            perms |= stat.S_IXGRP
+        elif perms_s[5] == 'S':
+            perms |= stat.S_ISGID
+        elif perms_s[5] == 's':
+            perms |= stat.S_IXGRP
+            perms |= stat.S_ISGID
+        # Others perms
+        if perms_s[6] == 'r':
+            perms |= stat.S_IROTH
+        if perms_s[7] == 'w':
+            perms |= stat.S_IWOTH
+        if perms_s[8] == 'x':
+            perms |= stat.S_IXOTH
+        elif perms_s[8] == 'T':
+            perms |= stat.S_ISVTX
+        elif perms_s[8] == 't':
+            perms |= stat.S_IXOTH
+            perms |= stat.S_ISVTX
+        return perms
+
+dot_C_dot_H_warning = """You are using .C or .H files in your project. This is deprecated.
+         Currently, Meson treats this as C++ code, but they
+            used to be treated as C code.
+         Note that the situation is a bit more complex if you are using the
+         Visual Studio compiler, as it treats .C files as C code, unless you add
+         the /TP compiler flag, but this is unreliable.
+         See https://github.com/mesonbuild/meson/pull/8747 for the discussions."""
+class File(HoldableObject):
+    def __init__(self, is_built: bool, subdir: str, fname: str):
+        if fname.endswith(".C") or fname.endswith(".H"):
+            mlog.warning(dot_C_dot_H_warning, once=True)
+        self.is_built = is_built
+        self.subdir = subdir
+        self.fname = fname
+        self.hash = hash((is_built, subdir, fname))
+
+    def __str__(self) -> str:
+        return self.relative_name()
+
+    def __repr__(self) -> str:
+        ret = ' 'File':
+        if not os.path.isfile(os.path.join(source_root, subdir, fname)):
+            raise MesonException(f'File {fname} does not exist.')
+        return File(False, subdir, fname)
+
+    @staticmethod
+    def from_built_file(subdir: str, fname: str) -> 'File':
+        return File(True, subdir, fname)
+
+    @staticmethod
+    def from_absolute_file(fname: str) -> 'File':
+        return File(False, '', fname)
+
+    @lru_cache(maxsize=None)
+    def rel_to_builddir(self, build_to_src: str) -> str:
+        if self.is_built:
+            return self.relative_name()
+        else:
+            return os.path.join(build_to_src, self.subdir, self.fname)
+
+    @lru_cache(maxsize=None)
+    def absolute_path(self, srcdir: str, builddir: str) -> str:
+        absdir = srcdir
+        if self.is_built:
+            absdir = builddir
+        return os.path.join(absdir, self.relative_name())
+
+    @property
+    def suffix(self) -> str:
+        return os.path.splitext(self.fname)[1][1:].lower()
+
+    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]:
+        return self.fname.split(s, maxsplit=maxsplit)
+
+    def rsplit(self, s: str, maxsplit: int = -1) -> T.List[str]:
+        return self.fname.rsplit(s, maxsplit=maxsplit)
+
+    def __eq__(self, other: object) -> bool:
+        if not isinstance(other, File):
+            return NotImplemented
+        if self.hash != other.hash:
+            return False
+        return (self.fname, self.subdir, self.is_built) == (other.fname, other.subdir, other.is_built)
+
+    def __hash__(self) -> int:
+        return self.hash
+
+    @lru_cache(maxsize=None)
+    def relative_name(self) -> str:
+        return os.path.join(self.subdir, self.fname)
+
+
+def get_compiler_for_source(compilers: T.Iterable['Compiler'], src: 'FileOrString') -> 'Compiler':
+    """Given a set of compilers and a source, find the compiler for that source type."""
+    for comp in compilers:
+        if comp.can_compile(src):
+            return comp
+    raise MesonException(f'No specified compiler can handle file {src!s}')
+
+
+def classify_unity_sources(compilers: T.Iterable['Compiler'], sources: T.Sequence['FileOrString']) -> T.Dict['Compiler', T.List['FileOrString']]:
+    compsrclist: T.Dict['Compiler', T.List['FileOrString']] = {}
+    for src in sources:
+        comp = get_compiler_for_source(compilers, src)
+        if comp not in compsrclist:
+            compsrclist[comp] = [src]
+        else:
+            compsrclist[comp].append(src)
+    return compsrclist
+
+
+class MachineChoice(enum.IntEnum):
+
+    """Enum class representing one of the two abstract machine names used in
+    most places: the build, and host, machines.
+    """
+
+    BUILD = 0
+    HOST = 1
+
+    def get_lower_case_name(self) -> str:
+        return PerMachine('build', 'host')[self]
+
+    def get_prefix(self) -> str:
+        return PerMachine('build.', '')[self]
+
+
+class PerMachine(T.Generic[_T]):
+    def __init__(self, build: _T, host: _T) -> None:
+        self.build = build
+        self.host = host
+
+    def __getitem__(self, machine: MachineChoice) -> _T:
+        return {
+            MachineChoice.BUILD:  self.build,
+            MachineChoice.HOST:   self.host,
+        }[machine]
+
+    def __setitem__(self, machine: MachineChoice, val: _T) -> None:
+        setattr(self, machine.get_lower_case_name(), val)
+
+    def miss_defaulting(self) -> "PerMachineDefaultable[T.Optional[_T]]":
+        """Unset definition duplicated from their previous to None
+
+        This is the inverse of ''default_missing''. By removing defaulted
+        machines, we can elaborate the original and then redefault them and thus
+        avoid repeating the elaboration explicitly.
+        """
+        unfreeze = PerMachineDefaultable() # type: PerMachineDefaultable[T.Optional[_T]]
+        unfreeze.build = self.build
+        unfreeze.host = self.host
+        if unfreeze.host == unfreeze.build:
+            unfreeze.host = None
+        return unfreeze
+
+    def __repr__(self) -> str:
+        return f'PerMachine({self.build!r}, {self.host!r})'
+
+
+class PerThreeMachine(PerMachine[_T]):
+    """Like `PerMachine` but includes `target` too.
+
+    It turns out just one thing do we need track the target machine. There's no
+    need to computer the `target` field so we don't bother overriding the
+    `__getitem__`/`__setitem__` methods.
+    """
+    def __init__(self, build: _T, host: _T, target: _T) -> None:
+        super().__init__(build, host)
+        self.target = target
+
+    def miss_defaulting(self) -> "PerThreeMachineDefaultable[T.Optional[_T]]":
+        """Unset definition duplicated from their previous to None
+
+        This is the inverse of ''default_missing''. By removing defaulted
+        machines, we can elaborate the original and then redefault them and thus
+        avoid repeating the elaboration explicitly.
+        """
+        unfreeze = PerThreeMachineDefaultable() # type: PerThreeMachineDefaultable[T.Optional[_T]]
+        unfreeze.build = self.build
+        unfreeze.host = self.host
+        unfreeze.target = self.target
+        if unfreeze.target == unfreeze.host:
+            unfreeze.target = None
+        if unfreeze.host == unfreeze.build:
+            unfreeze.host = None
+        return unfreeze
+
+    def matches_build_machine(self, machine: MachineChoice) -> bool:
+        return self.build == self[machine]
+
+    def __repr__(self) -> str:
+        return f'PerThreeMachine({self.build!r}, {self.host!r}, {self.target!r})'
+
+
+class PerMachineDefaultable(PerMachine[T.Optional[_T]]):
+    """Extends `PerMachine` with the ability to default from `None`s.
+    """
+    def __init__(self, build: T.Optional[_T] = None, host: T.Optional[_T] = None) -> None:
+        super().__init__(build, host)
+
+    def default_missing(self) -> "PerMachine[_T]":
+        """Default host to build
+
+        This allows just specifying nothing in the native case, and just host in the
+        cross non-compiler case.
+        """
+        freeze = PerMachine(self.build, self.host)
+        if freeze.host is None:
+            freeze.host = freeze.build
+        return freeze
+
+    def __repr__(self) -> str:
+        return f'PerMachineDefaultable({self.build!r}, {self.host!r})'
+
+    @classmethod
+    def default(cls, is_cross: bool, build: _T, host: _T) -> PerMachine[_T]:
+        """Easy way to get a defaulted value
+
+        This allows simplifying the case where you can control whether host and
+        build are separate or not with a boolean. If the is_cross value is set
+        to true then the optional host value will be used, otherwise the host
+        will be set to the build value.
+        """
+        m = cls(build)
+        if is_cross:
+            m.host = host
+        return m.default_missing()
+
+
+class PerThreeMachineDefaultable(PerMachineDefaultable, PerThreeMachine[T.Optional[_T]]):
+    """Extends `PerThreeMachine` with the ability to default from `None`s.
+    """
+    def __init__(self) -> None:
+        PerThreeMachine.__init__(self, None, None, None)
+
+    def default_missing(self) -> "PerThreeMachine[T.Optional[_T]]":
+        """Default host to build and target to host.
+
+        This allows just specifying nothing in the native case, just host in the
+        cross non-compiler case, and just target in the native-built
+        cross-compiler case.
+        """
+        freeze = PerThreeMachine(self.build, self.host, self.target)
+        if freeze.host is None:
+            freeze.host = freeze.build
+        if freeze.target is None:
+            freeze.target = freeze.host
+        return freeze
+
+    def __repr__(self) -> str:
+        return f'PerThreeMachineDefaultable({self.build!r}, {self.host!r}, {self.target!r})'
+
+
+def is_sunos() -> bool:
+    return platform.system().lower() == 'sunos'
+
+
+def is_osx() -> bool:
+    return platform.system().lower() == 'darwin'
+
+
+def is_linux() -> bool:
+    return platform.system().lower() == 'linux'
+
+
+def is_android() -> bool:
+    return platform.system().lower() == 'android'
+
+
+def is_haiku() -> bool:
+    return platform.system().lower() == 'haiku'
+
+
+def is_openbsd() -> bool:
+    return platform.system().lower() == 'openbsd'
+
+
+def is_windows() -> bool:
+    platname = platform.system().lower()
+    return platname == 'windows'
+
+def is_wsl() -> bool:
+    return is_linux() and 'microsoft' in platform.release().lower()
+
+def is_cygwin() -> bool:
+    return sys.platform == 'cygwin'
+
+
+def is_debianlike() -> bool:
+    return os.path.isfile('/etc/debian_version')
+
+
+def is_dragonflybsd() -> bool:
+    return platform.system().lower() == 'dragonfly'
+
+
+def is_netbsd() -> bool:
+    return platform.system().lower() == 'netbsd'
+
+
+def is_freebsd() -> bool:
+    return platform.system().lower() == 'freebsd'
+
+def is_irix() -> bool:
+    return platform.system().startswith('irix')
+
+def is_hurd() -> bool:
+    return platform.system().lower() == 'gnu'
+
+def is_qnx() -> bool:
+    return platform.system().lower() == 'qnx'
+
+def is_aix() -> bool:
+    return platform.system().lower() == 'aix'
+
+def exe_exists(arglist: T.List[str]) -> bool:
+    try:
+        if subprocess.run(arglist, timeout=10).returncode == 0:
+            return True
+    except (FileNotFoundError, subprocess.TimeoutExpired):
+        pass
+    return False
+
+
+@lru_cache(maxsize=None)
+def darwin_get_object_archs(objpath: str) -> 'ImmutableListProtocol[str]':
+    '''
+    For a specific object (executable, static library, dylib, etc), run `lipo`
+    to fetch the list of archs supported by it. Supports both thin objects and
+    'fat' objects.
+    '''
+    _, stdo, stderr = Popen_safe(['lipo', '-info', objpath])
+    if not stdo:
+        mlog.debug(f'lipo {objpath}: {stderr}')
+        return None
+    stdo = stdo.rsplit(': ', 1)[1]
+    # Convert from lipo-style archs to meson-style CPUs
+    stdo = stdo.replace('i386', 'x86')
+    stdo = stdo.replace('arm64', 'aarch64')
+    # Add generic name for armv7 and armv7s
+    if 'armv7' in stdo:
+        stdo += ' arm'
+    return stdo.split()
+
+
+def detect_vcs(source_dir: T.Union[str, Path]) -> T.Optional[T.Dict[str, str]]:
+    vcs_systems = [
+        dict(name = 'git',        cmd = 'git', repo_dir = '.git', get_rev = 'git describe --dirty=+', rev_regex = '(.*)', dep = '.git/logs/HEAD'),
+        dict(name = 'mercurial',  cmd = 'hg',  repo_dir = '.hg',  get_rev = 'hg id -i',               rev_regex = '(.*)', dep = '.hg/dirstate'),
+        dict(name = 'subversion', cmd = 'svn', repo_dir = '.svn', get_rev = 'svn info',               rev_regex = 'Revision: (.*)', dep = '.svn/wc.db'),
+        dict(name = 'bazaar',     cmd = 'bzr', repo_dir = '.bzr', get_rev = 'bzr revno',              rev_regex = '(.*)', dep = '.bzr'),
+    ]
+    if isinstance(source_dir, str):
+        source_dir = Path(source_dir)
+
+    parent_paths_and_self = collections.deque(source_dir.parents)
+    # Prepend the source directory to the front so we can check it;
+    # source_dir.parents doesn't include source_dir
+    parent_paths_and_self.appendleft(source_dir)
+    for curdir in parent_paths_and_self:
+        for vcs in vcs_systems:
+            if Path.is_dir(curdir.joinpath(vcs['repo_dir'])) and shutil.which(vcs['cmd']):
+                vcs['wc_dir'] = str(curdir)
+                return vcs
+    return None
+
+def current_vs_supports_modules() -> bool:
+    vsver = os.environ.get('VSCMD_VER', '')
+    nums = vsver.split('.', 2)
+    major = int(nums[0])
+    if major >= 17:
+        return True
+    if major == 16 and int(nums[1]) >= 10:
+        return True
+    return vsver.startswith('16.9.0') and '-pre.' in vsver
+
+# a helper class which implements the same version ordering as RPM
+class Version:
+    def __init__(self, s: str) -> None:
+        self._s = s
+
+        # split into numeric, alphabetic and non-alphanumeric sequences
+        sequences1 = re.finditer(r'(\d+|[a-zA-Z]+|[^a-zA-Z\d]+)', s)
+
+        # non-alphanumeric separators are discarded
+        sequences2 = [m for m in sequences1 if not re.match(r'[^a-zA-Z\d]+', m.group(1))]
+
+        # numeric sequences are converted from strings to ints
+        sequences3 = [int(m.group(1)) if m.group(1).isdigit() else m.group(1) for m in sequences2]
+
+        self._v = sequences3
+
+    def __str__(self) -> str:
+        return '{} (V={})'.format(self._s, str(self._v))
+
+    def __repr__(self) -> str:
+        return f''
+
+    def __lt__(self, other: object) -> bool:
+        if isinstance(other, Version):
+            return self.__cmp(other, operator.lt)
+        return NotImplemented
+
+    def __gt__(self, other: object) -> bool:
+        if isinstance(other, Version):
+            return self.__cmp(other, operator.gt)
+        return NotImplemented
+
+    def __le__(self, other: object) -> bool:
+        if isinstance(other, Version):
+            return self.__cmp(other, operator.le)
+        return NotImplemented
+
+    def __ge__(self, other: object) -> bool:
+        if isinstance(other, Version):
+            return self.__cmp(other, operator.ge)
+        return NotImplemented
+
+    def __eq__(self, other: object) -> bool:
+        if isinstance(other, Version):
+            return self._v == other._v
+        return NotImplemented
+
+    def __ne__(self, other: object) -> bool:
+        if isinstance(other, Version):
+            return self._v != other._v
+        return NotImplemented
+
+    def __cmp(self, other: 'Version', comparator: T.Callable[[T.Any, T.Any], bool]) -> bool:
+        # compare each sequence in order
+        for ours, theirs in zip(self._v, other._v):
+            # sort a non-digit sequence before a digit sequence
+            ours_is_int = isinstance(ours, int)
+            theirs_is_int = isinstance(theirs, int)
+            if ours_is_int != theirs_is_int:
+                return comparator(ours_is_int, theirs_is_int)
+
+            if ours != theirs:
+                return comparator(ours, theirs)
+
+        # if equal length, all components have matched, so equal
+        # otherwise, the version with a suffix remaining is greater
+        return comparator(len(self._v), len(other._v))
+
+
+def _version_extract_cmpop(vstr2: str) -> T.Tuple[T.Callable[[T.Any, T.Any], bool], str]:
+    if vstr2.startswith('>='):
+        cmpop = operator.ge
+        vstr2 = vstr2[2:]
+    elif vstr2.startswith('<='):
+        cmpop = operator.le
+        vstr2 = vstr2[2:]
+    elif vstr2.startswith('!='):
+        cmpop = operator.ne
+        vstr2 = vstr2[2:]
+    elif vstr2.startswith('=='):
+        cmpop = operator.eq
+        vstr2 = vstr2[2:]
+    elif vstr2.startswith('='):
+        cmpop = operator.eq
+        vstr2 = vstr2[1:]
+    elif vstr2.startswith('>'):
+        cmpop = operator.gt
+        vstr2 = vstr2[1:]
+    elif vstr2.startswith('<'):
+        cmpop = operator.lt
+        vstr2 = vstr2[1:]
+    else:
+        cmpop = operator.eq
+
+    return (cmpop, vstr2)
+
+
+def version_compare(vstr1: str, vstr2: str) -> bool:
+    (cmpop, vstr2) = _version_extract_cmpop(vstr2)
+    return cmpop(Version(vstr1), Version(vstr2))
+
+
+def version_compare_many(vstr1: str, conditions: T.Union[str, T.Iterable[str]]) -> T.Tuple[bool, T.List[str], T.List[str]]:
+    if isinstance(conditions, str):
+        conditions = [conditions]
+    found = []
+    not_found = []
+    for req in conditions:
+        if not version_compare(vstr1, req):
+            not_found.append(req)
+        else:
+            found.append(req)
+    return not_found == [], not_found, found
+
+
+# determine if the minimum version satisfying the condition |condition| exceeds
+# the minimum version for a feature |minimum|
+def version_compare_condition_with_min(condition: str, minimum: str) -> bool:
+    if condition.startswith('>='):
+        cmpop = operator.le
+        condition = condition[2:]
+    elif condition.startswith('<='):
+        return False
+    elif condition.startswith('!='):
+        return False
+    elif condition.startswith('=='):
+        cmpop = operator.le
+        condition = condition[2:]
+    elif condition.startswith('='):
+        cmpop = operator.le
+        condition = condition[1:]
+    elif condition.startswith('>'):
+        cmpop = operator.lt
+        condition = condition[1:]
+    elif condition.startswith('<'):
+        return False
+    else:
+        cmpop = operator.le
+
+    # Declaring a project(meson_version: '>=0.46') and then using features in
+    # 0.46.0 is valid, because (knowing the meson versioning scheme) '0.46.0' is
+    # the lowest version which satisfies the constraint '>=0.46'.
+    #
+    # But this will fail here, because the minimum version required by the
+    # version constraint ('0.46') is strictly less (in our version comparison)
+    # than the minimum version needed for the feature ('0.46.0').
+    #
+    # Map versions in the constraint of the form '0.46' to '0.46.0', to embed
+    # this knowledge of the meson versioning scheme.
+    condition = condition.strip()
+    if re.match(r'^\d+.\d+$', condition):
+        condition += '.0'
+
+    return T.cast(bool, cmpop(Version(minimum), Version(condition)))
+
+def search_version(text: str) -> str:
+    # Usually of the type 4.1.4 but compiler output may contain
+    # stuff like this:
+    # (Sourcery CodeBench Lite 2014.05-29) 4.8.3 20140320 (prerelease)
+    # Limiting major version number to two digits seems to work
+    # thus far. When we get to GCC 100, this will break, but
+    # if we are still relevant when that happens, it can be
+    # considered an achievement in itself.
+    #
+    # This regex is reaching magic levels. If it ever needs
+    # to be updated, do not complexify but convert to something
+    # saner instead.
+    # We'll demystify it a bit with a verbose definition.
+    version_regex = re.compile(r"""
+    (? str:
+    if is_debianlike():
+        try:
+            pc = subprocess.Popen(['dpkg-architecture', '-qDEB_HOST_MULTIARCH'],
+                                  stdout=subprocess.PIPE,
+                                  stderr=subprocess.DEVNULL)
+            (stdo, _) = pc.communicate()
+            if pc.returncode == 0:
+                archpath = stdo.decode().strip()
+                return 'lib/' + archpath
+        except Exception:
+            pass
+    if is_freebsd() or is_irix():
+        return 'lib'
+    if os.path.isdir('/usr/lib64') and not os.path.islink('/usr/lib64'):
+        return 'lib64'
+    return 'lib'
+
+
+def default_libexecdir() -> str:
+    # There is no way to auto-detect this, so it must be set at build time
+    return 'libexec'
+
+
+def default_prefix() -> str:
+    return 'c:/' if is_windows() else '/usr/local'
+
+
+def get_library_dirs() -> T.List[str]:
+    if is_windows():
+        return ['C:/mingw/lib'] # TODO: get programmatically
+    if is_osx():
+        return ['/usr/lib'] # TODO: get programmatically
+    # The following is probably Debian/Ubuntu specific.
+    # /usr/local/lib is first because it contains stuff
+    # installed by the sysadmin and is probably more up-to-date
+    # than /usr/lib. If you feel that this search order is
+    # problematic, please raise the issue on the mailing list.
+    unixdirs = ['/usr/local/lib', '/usr/lib', '/lib']
+
+    if is_freebsd():
+        return unixdirs
+    # FIXME: this needs to be further genericized for aarch64 etc.
+    machine = platform.machine()
+    if machine in ('i386', 'i486', 'i586', 'i686'):
+        plat = 'i386'
+    elif machine.startswith('arm'):
+        plat = 'arm'
+    else:
+        plat = ''
+
+    # Solaris puts 32-bit libraries in the main /lib & /usr/lib directories
+    # and 64-bit libraries in platform specific subdirectories.
+    if is_sunos():
+        if machine == 'i86pc':
+            plat = 'amd64'
+        elif machine.startswith('sun4'):
+            plat = 'sparcv9'
+
+    usr_platdir = Path('/usr/lib/') / plat
+    if usr_platdir.is_dir():
+        unixdirs += [str(x) for x in (usr_platdir).iterdir() if x.is_dir()]
+    if os.path.exists('/usr/lib64'):
+        unixdirs.append('/usr/lib64')
+
+    lib_platdir = Path('/lib/') / plat
+    if lib_platdir.is_dir():
+        unixdirs += [str(x) for x in (lib_platdir).iterdir() if x.is_dir()]
+    if os.path.exists('/lib64'):
+        unixdirs.append('/lib64')
+
+    return unixdirs
+
+
+def has_path_sep(name: str, sep: str = '/\\') -> bool:
+    'Checks if any of the specified @sep path separators are in @name'
+    for each in sep:
+        if each in name:
+            return True
+    return False
+
+
+if is_windows():
+    # shlex.split is not suitable for splitting command line on Window (https://bugs.python.org/issue1724822);
+    # shlex.quote is similarly problematic. Below are "proper" implementations of these functions according to
+    # https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments and
+    # https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
+
+    _whitespace = ' \t\n\r'
+    _find_unsafe_char = re.compile(fr'[{_whitespace}"]').search
+
+    def quote_arg(arg: str) -> str:
+        if arg and not _find_unsafe_char(arg):
+            return arg
+
+        result = '"'
+        num_backslashes = 0
+        for c in arg:
+            if c == '\\':
+                num_backslashes += 1
+            else:
+                if c == '"':
+                    # Escape all backslashes and the following double quotation mark
+                    num_backslashes = num_backslashes * 2 + 1
+
+                result += num_backslashes * '\\' + c
+                num_backslashes = 0
+
+        # Escape all backslashes, but let the terminating double quotation
+        # mark we add below be interpreted as a metacharacter
+        result += (num_backslashes * 2) * '\\' + '"'
+        return result
+
+    def split_args(cmd: str) -> T.List[str]:
+        result = []
+        arg = ''
+        num_backslashes = 0
+        num_quotes = 0
+        in_quotes = False
+        for c in cmd:
+            if c == '\\':
+                num_backslashes += 1
+            else:
+                if c == '"' and not num_backslashes % 2:
+                    # unescaped quote, eat it
+                    arg += (num_backslashes // 2) * '\\'
+                    num_quotes += 1
+                    in_quotes = not in_quotes
+                elif c in _whitespace and not in_quotes:
+                    if arg or num_quotes:
+                        # reached the end of the argument
+                        result.append(arg)
+                        arg = ''
+                        num_quotes = 0
+                else:
+                    if c == '"':
+                        # escaped quote
+                        num_backslashes = (num_backslashes - 1) // 2
+
+                    arg += num_backslashes * '\\' + c
+
+                num_backslashes = 0
+
+        if arg or num_quotes:
+            result.append(arg)
+
+        return result
+else:
+    def quote_arg(arg: str) -> str:
+        return shlex.quote(arg)
+
+    def split_args(cmd: str) -> T.List[str]:
+        return shlex.split(cmd)
+
+
+def join_args(args: T.Iterable[str]) -> str:
+    return ' '.join([quote_arg(x) for x in args])
+
+
+def do_replacement(regex: T.Pattern[str], line: str, variable_format: str,
+                   confdata: T.Union[T.Dict[str, T.Tuple[str, T.Optional[str]]], 'ConfigurationData']) -> T.Tuple[str, T.Set[str]]:
+    missing_variables = set()  # type: T.Set[str]
+    if variable_format == 'cmake':
+        start_tag = '${'
+        backslash_tag = '\\${'
+    else:
+        assert variable_format in ['meson', 'cmake@']
+        start_tag = '@'
+        backslash_tag = '\\@'
+
+    def variable_replace(match: T.Match[str]) -> str:
+        # Pairs of escape characters before '@' or '\@'
+        if match.group(0).endswith('\\'):
+            num_escapes = match.end(0) - match.start(0)
+            return '\\' * (num_escapes // 2)
+        # Single escape character and '@'
+        elif match.group(0) == backslash_tag:
+            return start_tag
+        # Template variable to be replaced
+        else:
+            varname = match.group(1)
+            var_str = ''
+            if varname in confdata:
+                var, _ = confdata.get(varname)
+                if isinstance(var, str):
+                    var_str = var
+                elif isinstance(var, int):
+                    var_str = str(var)
+                else:
+                    msg = f'Tried to replace variable {varname!r} value with ' \
+                          f'something other than a string or int: {var!r}'
+                    raise MesonException(msg)
+            else:
+                missing_variables.add(varname)
+            return var_str
+    return re.sub(regex, variable_replace, line), missing_variables
+
+def do_define(regex: T.Pattern[str], line: str, confdata: 'ConfigurationData', variable_format: str) -> str:
+    def get_cmake_define(line: str, confdata: 'ConfigurationData') -> str:
+        arr = line.split()
+        define_value = []
+        for token in arr[2:]:
+            try:
+                (v, desc) = confdata.get(token)
+                define_value += [str(v)]
+            except KeyError:
+                define_value += [token]
+        return ' '.join(define_value)
+
+    arr = line.split()
+    if variable_format == 'meson' and len(arr) != 2:
+        raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip())
+
+    varname = arr[1]
+    try:
+        (v, desc) = confdata.get(varname)
+    except KeyError:
+        return '/* #undef %s */\n' % varname
+    if isinstance(v, bool):
+        if v:
+            return '#define %s\n' % varname
+        else:
+            return '#undef %s\n' % varname
+    elif isinstance(v, int):
+        return '#define %s %d\n' % (varname, v)
+    elif isinstance(v, str):
+        if variable_format == 'meson':
+            result = v
+        else:
+            result = get_cmake_define(line, confdata)
+        result = f'#define {varname} {result}\n'
+        (result, missing_variable) = do_replacement(regex, result, variable_format, confdata)
+        return result
+    else:
+        raise MesonException('#mesondefine argument "%s" is of unknown type.' % varname)
+
+def get_variable_regex(variable_format: str = 'meson') -> T.Pattern[str]:
+    # Only allow (a-z, A-Z, 0-9, _, -) as valid characters for a define
+    # Also allow escaping '@' with '\@'
+    if variable_format in ['meson', 'cmake@']:
+        regex = re.compile(r'(?:\\\\)+(?=\\?@)|\\@|@([-a-zA-Z0-9_]+)@')
+    elif variable_format == 'cmake':
+        regex = re.compile(r'(?:\\\\)+(?=\\?\$)|\\\${|\${([-a-zA-Z0-9_]+)}')
+    else:
+        raise MesonException(f'Format "{variable_format}" not handled')
+    return regex
+
+def do_conf_str(src: str, data: list, confdata: 'ConfigurationData', variable_format: str,
+                encoding: str = 'utf-8') -> T.Tuple[T.List[str], T.Set[str], bool]:
+    def line_is_valid(line: str, variable_format: str) -> bool:
+        if variable_format == 'meson':
+            if '#cmakedefine' in line:
+                return False
+        else: # cmake format
+            if '#mesondefine' in line:
+                return False
+        return True
+
+    regex = get_variable_regex(variable_format)
+
+    search_token = '#mesondefine'
+    if variable_format != 'meson':
+        search_token = '#cmakedefine'
+
+    result = []
+    missing_variables = set()
+    # Detect when the configuration data is empty and no tokens were found
+    # during substitution so we can warn the user to use the `copy:` kwarg.
+    confdata_useless = not confdata.keys()
+    for line in data:
+        if line.startswith(search_token):
+            confdata_useless = False
+            line = do_define(regex, line, confdata, variable_format)
+        else:
+            if not line_is_valid(line, variable_format):
+                raise MesonException(f'Format error in {src}: saw "{line.strip()}" when format set to "{variable_format}"')
+            line, missing = do_replacement(regex, line, variable_format, confdata)
+            missing_variables.update(missing)
+            if missing:
+                confdata_useless = False
+        result.append(line)
+
+    return result, missing_variables, confdata_useless
+
+def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', variable_format: str,
+                 encoding: str = 'utf-8') -> T.Tuple[T.Set[str], bool]:
+    try:
+        with open(src, encoding=encoding, newline='') as f:
+            data = f.readlines()
+    except Exception as e:
+        raise MesonException(f'Could not read input file {src}: {e!s}')
+
+    (result, missing_variables, confdata_useless) = do_conf_str(src, data, confdata, variable_format, encoding)
+    dst_tmp = dst + '~'
+    try:
+        with open(dst_tmp, 'w', encoding=encoding, newline='') as f:
+            f.writelines(result)
+    except Exception as e:
+        raise MesonException(f'Could not write output file {dst}: {e!s}')
+    shutil.copymode(src, dst_tmp)
+    replace_if_different(dst, dst_tmp)
+    return missing_variables, confdata_useless
+
+CONF_C_PRELUDE = '''/*
+ * Autogenerated by the Meson build system.
+ * Do not edit, your changes will be lost.
+ */
+
+#pragma once
+
+'''
+
+CONF_NASM_PRELUDE = '''; Autogenerated by the Meson build system.
+; Do not edit, your changes will be lost.
+
+'''
+
+def dump_conf_header(ofilename: str, cdata: 'ConfigurationData', output_format: str) -> None:
+    if output_format == 'c':
+        prelude = CONF_C_PRELUDE
+        prefix = '#'
+    elif output_format == 'nasm':
+        prelude = CONF_NASM_PRELUDE
+        prefix = '%'
+    else:
+        raise MesonBugException(f'Undefined output_format: "{output_format}"')
+
+    ofilename_tmp = ofilename + '~'
+    with open(ofilename_tmp, 'w', encoding='utf-8') as ofile:
+        ofile.write(prelude)
+        for k in sorted(cdata.keys()):
+            (v, desc) = cdata.get(k)
+            if desc:
+                if output_format == 'c':
+                    ofile.write('/* %s */\n' % desc)
+                elif output_format == 'nasm':
+                    for line in desc.split('\n'):
+                        ofile.write('; %s\n' % line)
+            if isinstance(v, bool):
+                if v:
+                    ofile.write(f'{prefix}define {k}\n\n')
+                else:
+                    ofile.write(f'{prefix}undef {k}\n\n')
+            elif isinstance(v, (int, str)):
+                ofile.write(f'{prefix}define {k} {v}\n\n')
+            else:
+                raise MesonException('Unknown data type in configuration file entry: ' + k)
+    replace_if_different(ofilename, ofilename_tmp)
+
+
+def replace_if_different(dst: str, dst_tmp: str) -> None:
+    # If contents are identical, don't touch the file to prevent
+    # unnecessary rebuilds.
+    different = True
+    try:
+        with open(dst, 'rb') as f1, open(dst_tmp, 'rb') as f2:
+            if f1.read() == f2.read():
+                different = False
+    except FileNotFoundError:
+        pass
+    if different:
+        os.replace(dst_tmp, dst)
+    else:
+        os.unlink(dst_tmp)
+
+
+def listify(item: T.Any, flatten: bool = True) -> T.List[T.Any]:
+    '''
+    Returns a list with all args embedded in a list if they are not a list.
+    This function preserves order.
+    @flatten: Convert lists of lists to a flat list
+    '''
+    if not isinstance(item, list):
+        return [item]
+    result = []  # type: T.List[T.Any]
+    for i in item:
+        if flatten and isinstance(i, list):
+            result += listify(i, flatten=True)
+        else:
+            result.append(i)
+    return result
+
+
+def extract_as_list(dict_object: T.Dict[_T, _U], key: _T, pop: bool = False) -> T.List[_U]:
+    '''
+    Extracts all values from given dict_object and listifies them.
+    '''
+    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) or [], flatten=True)
+
+
+def typeslistify(item: 'T.Union[_T, T.Sequence[_T]]',
+                 types: 'T.Union[T.Type[_T], T.Tuple[T.Type[_T]]]') -> T.List[_T]:
+    '''
+    Ensure that type(@item) is one of @types or a
+    list of items all of which are of type @types
+    '''
+    if isinstance(item, types):
+        item = T.cast(T.List[_T], [item])
+    if not isinstance(item, list):
+        raise MesonException('Item must be a list or one of {!r}, not {!r}'.format(types, type(item)))
+    for i in item:
+        if i is not None and not isinstance(i, types):
+            raise MesonException('List item must be one of {!r}, not {!r}'.format(types, type(i)))
+    return item
+
+
+def stringlistify(item: T.Union[T.Any, T.Sequence[T.Any]]) -> T.List[str]:
+    return typeslistify(item, str)
+
+
+def expand_arguments(args: T.Iterable[str]) -> T.Optional[T.List[str]]:
+    expended_args = []  # type: T.List[str]
+    for arg in args:
+        if not arg.startswith('@'):
+            expended_args.append(arg)
+            continue
+
+        args_file = arg[1:]
+        try:
+            with open(args_file, encoding='utf-8') as f:
+                extended_args = f.read().split()
+            expended_args += extended_args
+        except Exception as e:
+            mlog.error('Expanding command line arguments:',  args_file, 'not found')
+            mlog.exception(e)
+            return None
+    return expended_args
+
+
+def partition(pred: T.Callable[[_T], object], iterable: T.Iterable[_T]) -> T.Tuple[T.Iterator[_T], T.Iterator[_T]]:
+    """Use a predicate to partition entries into false entries and true
+    entries.
+
+    >>> x, y = partition(is_odd, range(10))
+    >>> (list(x), list(y))
+    ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9])
+    """
+    t1, t2 = tee(iterable)
+    return filterfalse(pred, t1), filter(pred, t2)
+
+
+def Popen_safe(args: T.List[str], write: T.Optional[str] = None,
+               stdout: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE,
+               stderr: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE,
+               **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]:
+    import locale
+    encoding = locale.getpreferredencoding()
+    # Redirect stdin to DEVNULL otherwise the command run by us here might mess
+    # up the console and ANSI colors will stop working on Windows.
+    if 'stdin' not in kwargs:
+        kwargs['stdin'] = subprocess.DEVNULL
+    if not sys.stdout.encoding or encoding.upper() != 'UTF-8':
+        p, o, e = Popen_safe_legacy(args, write=write, stdout=stdout, stderr=stderr, **kwargs)
+    else:
+        p = subprocess.Popen(args, universal_newlines=True, close_fds=False,
+                             stdout=stdout, stderr=stderr, **kwargs)
+        o, e = p.communicate(write)
+    # Sometimes the command that we run will call another command which will be
+    # without the above stdin workaround, so set the console mode again just in
+    # case.
+    mlog.setup_console()
+    return p, o, e
+
+
+def Popen_safe_legacy(args: T.List[str], write: T.Optional[str] = None,
+                      stdout: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE,
+                      stderr: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE,
+                      **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]:
+    p = subprocess.Popen(args, universal_newlines=False, close_fds=False,
+                         stdout=stdout, stderr=stderr, **kwargs)
+    input_ = None  # type: T.Optional[bytes]
+    if write is not None:
+        input_ = write.encode('utf-8')
+    o, e = p.communicate(input_)
+    if o is not None:
+        if sys.stdout.encoding:
+            o = o.decode(encoding=sys.stdout.encoding, errors='replace').replace('\r\n', '\n')
+        else:
+            o = o.decode(errors='replace').replace('\r\n', '\n')
+    if e is not None:
+        if sys.stderr is not None and sys.stderr.encoding:
+            e = e.decode(encoding=sys.stderr.encoding, errors='replace').replace('\r\n', '\n')
+        else:
+            e = e.decode(errors='replace').replace('\r\n', '\n')
+    return p, o, e
+
+
+def iter_regexin_iter(regexiter: T.Iterable[str], initer: T.Iterable[str]) -> T.Optional[str]:
+    '''
+    Takes each regular expression in @regexiter and tries to search for it in
+    every item in @initer. If there is a match, returns that match.
+    Else returns False.
+    '''
+    for regex in regexiter:
+        for ii in initer:
+            if not isinstance(ii, str):
+                continue
+            match = re.search(regex, ii)
+            if match:
+                return match.group()
+    return None
+
+
+def _substitute_values_check_errors(command: T.List[str], values: T.Dict[str, T.Union[str, T.List[str]]]) -> None:
+    # Error checking
+    inregex = ['@INPUT([0-9]+)?@', '@PLAINNAME@', '@BASENAME@']  # type: T.List[str]
+    outregex = ['@OUTPUT([0-9]+)?@', '@OUTDIR@']                 # type: T.List[str]
+    if '@INPUT@' not in values:
+        # Error out if any input-derived templates are present in the command
+        match = iter_regexin_iter(inregex, command)
+        if match:
+            raise MesonException(f'Command cannot have {match!r}, since no input files were specified')
+    else:
+        if len(values['@INPUT@']) > 1:
+            # Error out if @PLAINNAME@ or @BASENAME@ is present in the command
+            match = iter_regexin_iter(inregex[1:], command)
+            if match:
+                raise MesonException(f'Command cannot have {match!r} when there is '
+                                     'more than one input file')
+        # Error out if an invalid @INPUTnn@ template was specified
+        for each in command:
+            if not isinstance(each, str):
+                continue
+            match2 = re.search(inregex[0], each)
+            if match2 and match2.group() not in values:
+                m = 'Command cannot have {!r} since there are only {!r} inputs'
+                raise MesonException(m.format(match2.group(), len(values['@INPUT@'])))
+    if '@OUTPUT@' not in values:
+        # Error out if any output-derived templates are present in the command
+        match = iter_regexin_iter(outregex, command)
+        if match:
+            raise MesonException(f'Command cannot have {match!r} since there are no outputs')
+    else:
+        # Error out if an invalid @OUTPUTnn@ template was specified
+        for each in command:
+            if not isinstance(each, str):
+                continue
+            match2 = re.search(outregex[0], each)
+            if match2 and match2.group() not in values:
+                m = 'Command cannot have {!r} since there are only {!r} outputs'
+                raise MesonException(m.format(match2.group(), len(values['@OUTPUT@'])))
+
+
+def substitute_values(command: T.List[str], values: T.Dict[str, T.Union[str, T.List[str]]]) -> T.List[str]:
+    '''
+    Substitute the template strings in the @values dict into the list of
+    strings @command and return a new list. For a full list of the templates,
+    see get_filenames_templates_dict()
+
+    If multiple inputs/outputs are given in the @values dictionary, we
+    substitute @INPUT@ and @OUTPUT@ only if they are the entire string, not
+    just a part of it, and in that case we substitute *all* of them.
+
+    The typing of this function is difficult, as only @OUTPUT@ and @INPUT@ can
+    be lists, everything else is a string. However, TypeDict cannot represent
+    this, as you can have optional keys, but not extra keys. We end up just
+    having to us asserts to convince type checkers that this is okay.
+
+    https://github.com/python/mypy/issues/4617
+    '''
+
+    def replace(m: T.Match[str]) -> str:
+        v = values[m.group(0)]
+        assert isinstance(v, str), 'for mypy'
+        return v
+
+    # Error checking
+    _substitute_values_check_errors(command, values)
+
+    # Substitution
+    outcmd = []  # type: T.List[str]
+    rx_keys = [re.escape(key) for key in values if key not in ('@INPUT@', '@OUTPUT@')]
+    value_rx = re.compile('|'.join(rx_keys)) if rx_keys else None
+    for vv in command:
+        more: T.Optional[str] = None
+        if not isinstance(vv, str):
+            outcmd.append(vv)
+        elif '@INPUT@' in vv:
+            inputs = values['@INPUT@']
+            if vv == '@INPUT@':
+                outcmd += inputs
+            elif len(inputs) == 1:
+                outcmd.append(vv.replace('@INPUT@', inputs[0]))
+            else:
+                raise MesonException("Command has '@INPUT@' as part of a "
+                                     "string and more than one input file")
+        elif '@OUTPUT@' in vv:
+            outputs = values['@OUTPUT@']
+            if vv == '@OUTPUT@':
+                outcmd += outputs
+            elif len(outputs) == 1:
+                outcmd.append(vv.replace('@OUTPUT@', outputs[0]))
+            else:
+                raise MesonException("Command has '@OUTPUT@' as part of a "
+                                     "string and more than one output file")
+
+        # Append values that are exactly a template string.
+        # This is faster than a string replace.
+        elif vv in values:
+            o = values[vv]
+            assert isinstance(o, str), 'for mypy'
+            more = o
+        # Substitute everything else with replacement
+        elif value_rx:
+            more = value_rx.sub(replace, vv)
+        else:
+            more = vv
+
+        if more is not None:
+            outcmd.append(more)
+
+    return outcmd
+
+
+def get_filenames_templates_dict(inputs: T.List[str], outputs: T.List[str]) -> T.Dict[str, T.Union[str, T.List[str]]]:
+    '''
+    Create a dictionary with template strings as keys and values as values for
+    the following templates:
+
+    @INPUT@  - the full path to one or more input files, from @inputs
+    @OUTPUT@ - the full path to one or more output files, from @outputs
+    @OUTDIR@ - the full path to the directory containing the output files
+
+    If there is only one input file, the following keys are also created:
+
+    @PLAINNAME@ - the filename of the input file
+    @BASENAME@ - the filename of the input file with the extension removed
+
+    If there is more than one input file, the following keys are also created:
+
+    @INPUT0@, @INPUT1@, ... one for each input file
+
+    If there is more than one output file, the following keys are also created:
+
+    @OUTPUT0@, @OUTPUT1@, ... one for each output file
+    '''
+    values = {}  # type: T.Dict[str, T.Union[str, T.List[str]]]
+    # Gather values derived from the input
+    if inputs:
+        # We want to substitute all the inputs.
+        values['@INPUT@'] = inputs
+        for (ii, vv) in enumerate(inputs):
+            # Write out @INPUT0@, @INPUT1@, ...
+            values[f'@INPUT{ii}@'] = vv
+        if len(inputs) == 1:
+            # Just one value, substitute @PLAINNAME@ and @BASENAME@
+            values['@PLAINNAME@'] = plain = os.path.basename(inputs[0])
+            values['@BASENAME@'] = os.path.splitext(plain)[0]
+    if outputs:
+        # Gather values derived from the outputs, similar to above.
+        values['@OUTPUT@'] = outputs
+        for (ii, vv) in enumerate(outputs):
+            values[f'@OUTPUT{ii}@'] = vv
+        # Outdir should be the same for all outputs
+        values['@OUTDIR@'] = os.path.dirname(outputs[0])
+        # Many external programs fail on empty arguments.
+        if values['@OUTDIR@'] == '':
+            values['@OUTDIR@'] = '.'
+    return values
+
+
+def _make_tree_writable(topdir: str) -> None:
+    # Ensure all files and directories under topdir are writable
+    # (and readable) by owner.
+    for d, _, files in os.walk(topdir):
+        os.chmod(d, os.stat(d).st_mode | stat.S_IWRITE | stat.S_IREAD)
+        for fname in files:
+            fpath = os.path.join(d, fname)
+            if os.path.isfile(fpath):
+                os.chmod(fpath, os.stat(fpath).st_mode | stat.S_IWRITE | stat.S_IREAD)
+
+
+def windows_proof_rmtree(f: str) -> None:
+    # On Windows if anyone is holding a file open you can't
+    # delete it. As an example an anti virus scanner might
+    # be scanning files you are trying to delete. The only
+    # way to fix this is to try again and again.
+    delays = [0.1, 0.1, 0.2, 0.2, 0.2, 0.5, 0.5, 1, 1, 1, 1, 2]
+    writable = False
+    for d in delays:
+        try:
+            # Start by making the tree writable.
+            if not writable:
+                _make_tree_writable(f)
+                writable = True
+        except PermissionError:
+            time.sleep(d)
+            continue
+        try:
+            shutil.rmtree(f)
+            return
+        except FileNotFoundError:
+            return
+        except OSError:
+            time.sleep(d)
+    # Try one last time and throw if it fails.
+    shutil.rmtree(f)
+
+
+def windows_proof_rm(fpath: str) -> None:
+    """Like windows_proof_rmtree, but for a single file."""
+    if os.path.isfile(fpath):
+        os.chmod(fpath, os.stat(fpath).st_mode | stat.S_IWRITE | stat.S_IREAD)
+    delays = [0.1, 0.1, 0.2, 0.2, 0.2, 0.5, 0.5, 1, 1, 1, 1, 2]
+    for d in delays:
+        try:
+            os.unlink(fpath)
+            return
+        except FileNotFoundError:
+            return
+        except OSError:
+            time.sleep(d)
+    os.unlink(fpath)
+
+
+class TemporaryDirectoryWinProof(TemporaryDirectory):
+    """
+    Like TemporaryDirectory, but cleans things up using
+    windows_proof_rmtree()
+    """
+
+    def __exit__(self, exc: T.Any, value: T.Any, tb: T.Any) -> None:
+        try:
+            super().__exit__(exc, value, tb)
+        except OSError:
+            windows_proof_rmtree(self.name)
+
+    def cleanup(self) -> None:
+        try:
+            super().cleanup()
+        except OSError:
+            windows_proof_rmtree(self.name)
+
+
+def detect_subprojects(spdir_name: str, current_dir: str = '',
+                       result: T.Optional[T.Dict[str, T.List[str]]] = None) -> T.Dict[str, T.List[str]]:
+    if result is None:
+        result = {}
+    spdir = os.path.join(current_dir, spdir_name)
+    if not os.path.exists(spdir):
+        return result
+    for trial in glob(os.path.join(spdir, '*')):
+        basename = os.path.basename(trial)
+        if trial == 'packagecache':
+            continue
+        append_this = True
+        if os.path.isdir(trial):
+            detect_subprojects(spdir_name, trial, result)
+        elif trial.endswith('.wrap') and os.path.isfile(trial):
+            basename = os.path.splitext(basename)[0]
+        else:
+            append_this = False
+        if append_this:
+            if basename in result:
+                result[basename].append(trial)
+            else:
+                result[basename] = [trial]
+    return result
+
+
+def substring_is_in_list(substr: str, strlist: T.List[str]) -> bool:
+    for s in strlist:
+        if substr in s:
+            return True
+    return False
+
+
+class OrderedSet(T.MutableSet[_T]):
+    """A set that preserves the order in which items are added, by first
+    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]
+        if iterable:
+            self.update(iterable)
+
+    def __contains__(self, value: object) -> bool:
+        return value in self.__container
+
+    def __iter__(self) -> T.Iterator[_T]:
+        return iter(self.__container.keys())
+
+    def __len__(self) -> int:
+        return len(self.__container)
+
+    def __repr__(self) -> str:
+        # Don't print 'OrderedSet("")' for an empty set.
+        if self.__container:
+            return 'OrderedSet("{}")'.format(
+                '", "'.join(repr(e) for e in self.__container.keys()))
+        return 'OrderedSet()'
+
+    def __reversed__(self) -> T.Iterator[_T]:
+        return reversed(self.__container.keys())
+
+    def add(self, value: _T) -> None:
+        self.__container[value] = None
+
+    def discard(self, value: _T) -> None:
+        if value in self.__container:
+            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
+
+    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
+        return item
+
+    def update(self, iterable: T.Iterable[_T]) -> None:
+        for item in iterable:
+            self.__container[item] = None
+
+    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
+    # original absolute path.
+    try:
+        return os.path.relpath(path, start)
+    except (TypeError, ValueError):
+        return path
+
+def path_is_in_root(path: Path, root: Path, resolve: bool = False) -> bool:
+    # Check whether a path is within the root directory root
+    try:
+        if resolve:
+            path.resolve().relative_to(root.resolve())
+        else:
+            path.relative_to(root)
+    except ValueError:
+        return False
+    return True
+
+def relative_to_if_possible(path: Path, root: Path, resolve: bool = False) -> Path:
+    try:
+        if resolve:
+            return path.resolve().relative_to(root.resolve())
+        else:
+            return path.relative_to(root)
+    except ValueError:
+        return path
+
+class LibType(enum.IntEnum):
+
+    """Enumeration for library types."""
+
+    SHARED = 0
+    STATIC = 1
+    PREFER_SHARED = 2
+    PREFER_STATIC = 3
+
+
+class ProgressBarFallback:  # lgtm [py/iter-returns-non-self]
+    '''
+    Fallback progress bar implementation when tqdm is not found
+
+    Since this class is not an actual iterator, but only provides a minimal
+    fallback, it is safe to ignore the 'Iterator does not return self from
+    __iter__ method' warning.
+    '''
+    def __init__(self, iterable: T.Optional[T.Iterable[str]] = None, total: T.Optional[int] = None,
+                 bar_type: T.Optional[str] = None, desc: T.Optional[str] = None):
+        if iterable is not None:
+            self.iterable = iter(iterable)
+            return
+        self.total = total
+        self.done = 0
+        self.printed_dots = 0
+        if self.total and bar_type == 'download':
+            print('Download size:', self.total)
+        if desc:
+            print(f'{desc}: ', end='')
+
+    # Pretend to be an iterator when called as one and don't print any
+    # progress
+    def __iter__(self) -> T.Iterator[str]:
+        return self.iterable
+
+    def __next__(self) -> str:
+        return next(self.iterable)
+
+    def print_dot(self) -> None:
+        print('.', end='')
+        sys.stdout.flush()
+        self.printed_dots += 1
+
+    def update(self, progress: int) -> None:
+        self.done += progress
+        if not self.total:
+            # Just print one dot per call if we don't have a total length
+            self.print_dot()
+            return
+        ratio = int(self.done / self.total * 10)
+        while self.printed_dots < ratio:
+            self.print_dot()
+
+    def close(self) -> None:
+        print('')
+
+try:
+    from tqdm import tqdm
+except ImportError:
+    # ideally we would use a typing.Protocol here, but it's part of typing_extensions until 3.8
+    ProgressBar = ProgressBarFallback  # type: T.Union[T.Type[ProgressBarFallback], T.Type[ProgressBarTqdm]]
+else:
+    class ProgressBarTqdm(tqdm):
+        def __init__(self, *args: T.Any, bar_type: T.Optional[str] = None, **kwargs: T.Any) -> None:
+            if bar_type == 'download':
+                kwargs.update({'unit': 'bytes', 'leave': True})
+            else:
+                kwargs.update({'leave': False})
+            kwargs['ncols'] = 100
+            super().__init__(*args, **kwargs)
+
+    ProgressBar = ProgressBarTqdm
+
+
+class RealPathAction(argparse.Action):
+    def __init__(self, option_strings: T.List[str], dest: str, default: str = '.', **kwargs: T.Any):
+        default = os.path.abspath(os.path.realpath(default))
+        super().__init__(option_strings, dest, nargs=None, default=default, **kwargs)
+
+    def __call__(self, parser: argparse.ArgumentParser, namespace: argparse.Namespace,
+                 values: T.Union[str, T.Sequence[T.Any], None], option_string: str = None) -> None:
+        assert isinstance(values, str)
+        setattr(namespace, self.dest, os.path.abspath(os.path.realpath(values)))
+
+
+def get_wine_shortpath(winecmd: T.List[str], wine_paths: T.Sequence[str]) -> str:
+    """Get A short version of @wine_paths to avoid reaching WINEPATH number
+    of char limit.
+    """
+
+    wine_paths = list(OrderedSet(wine_paths))
+
+    getShortPathScript = '%s.bat' % str(uuid.uuid4()).lower()[:5]
+    with open(getShortPathScript, mode='w', encoding='utf-8') as f:
+        f.write("@ECHO OFF\nfor %%x in (%*) do (\n echo|set /p=;%~sx\n)\n")
+        f.flush()
+    try:
+        with open(os.devnull, 'w', encoding='utf-8') as stderr:
+            wine_path = subprocess.check_output(
+                winecmd +
+                ['cmd', '/C', getShortPathScript] + wine_paths,
+                stderr=stderr).decode('utf-8')
+    except subprocess.CalledProcessError as e:
+        print("Could not get short paths: %s" % e)
+        wine_path = ';'.join(wine_paths)
+    finally:
+        os.remove(getShortPathScript)
+    if len(wine_path) > 2048:
+        raise MesonException(
+            'WINEPATH size {} > 2048'
+            ' this will cause random failure.'.format(
+                len(wine_path)))
+
+    return wine_path.strip(';')
+
+
+def run_once(func: T.Callable[..., _T]) -> T.Callable[..., _T]:
+    ret = []  # type: T.List[_T]
+
+    @wraps(func)
+    def wrapper(*args: T.Any, **kwargs: T.Any) -> _T:
+        if ret:
+            return ret[0]
+
+        val = func(*args, **kwargs)
+        ret.append(val)
+        return val
+
+    return wrapper
+
+
+def generate_list(func: T.Callable[..., T.Generator[_T, None, None]]) -> T.Callable[..., T.List[_T]]:
+    @wraps(func)
+    def wrapper(*args: T.Any, **kwargs: T.Any) -> T.List[_T]:
+        return list(func(*args, **kwargs))
+
+    return wrapper
+
+
+class OptionOverrideProxy(collections.abc.MutableMapping):
+
+    '''Mimic an option list but transparently override selected option
+    values.
+    '''
+
+    # TODO: the typing here could be made more explicit using a TypeDict from
+    # python 3.8 or typing_extensions
+
+    def __init__(self, overrides: T.Dict['OptionKey', T.Any], *options: 'KeyedOptionDictType'):
+        self.overrides = overrides.copy()
+        self.options: T.Dict['OptionKey', UserOption] = {}
+        for o in options:
+            self.options.update(o)
+
+    def __getitem__(self, key: 'OptionKey') -> T.Union['UserOption']:
+        if key in self.options:
+            opt = self.options[key]
+            if key in self.overrides:
+                opt = copy.copy(opt)
+                opt.set_value(self.overrides[key])
+            return opt
+        raise KeyError('Option not found', key)
+
+    def __setitem__(self, key: 'OptionKey', value: T.Union['UserOption']) -> None:
+        self.overrides[key] = value.value
+
+    def __delitem__(self, key: 'OptionKey') -> None:
+        del self.overrides[key]
+
+    def __iter__(self) -> T.Iterator['OptionKey']:
+        return iter(self.options)
+
+    def __len__(self) -> int:
+        return len(self.options)
+
+    def copy(self) -> 'OptionOverrideProxy':
+        return OptionOverrideProxy(self.overrides.copy(), self.options.copy())
+
+
+class OptionType(enum.IntEnum):
+
+    """Enum used to specify what kind of argument a thing is."""
+
+    BUILTIN = 0
+    BACKEND = 1
+    BASE = 2
+    COMPILER = 3
+    PROJECT = 4
+
+# This is copied from coredata. There is no way to share this, because this
+# is used in the OptionKey constructor, and the coredata lists are
+# OptionKeys...
+_BUILTIN_NAMES = {
+    'prefix',
+    'bindir',
+    'datadir',
+    'includedir',
+    'infodir',
+    'libdir',
+    'libexecdir',
+    'localedir',
+    'localstatedir',
+    'mandir',
+    'sbindir',
+    'sharedstatedir',
+    'sysconfdir',
+    'auto_features',
+    'backend',
+    'buildtype',
+    'debug',
+    'default_library',
+    'errorlogs',
+    'install_umask',
+    'layout',
+    'optimization',
+    'stdsplit',
+    'strip',
+    'unity',
+    'unity_size',
+    'warning_level',
+    'werror',
+    'wrap_mode',
+    'force_fallback_for',
+    'pkg_config_path',
+    'cmake_prefix_path',
+}
+
+
+def _classify_argument(key: 'OptionKey') -> OptionType:
+    """Classify arguments into groups so we know which dict to assign them to."""
+
+    if key.name.startswith('b_'):
+        return OptionType.BASE
+    elif key.lang is not None:
+        return OptionType.COMPILER
+    elif key.name in _BUILTIN_NAMES or key.module:
+        return OptionType.BUILTIN
+    elif key.name.startswith('backend_'):
+        assert key.machine is MachineChoice.HOST, str(key)
+        return OptionType.BACKEND
+    else:
+        assert key.machine is MachineChoice.HOST, str(key)
+        return OptionType.PROJECT
+
+
+@total_ordering
+class OptionKey:
+
+    """Represents an option key in the various option dictionaries.
+
+    This provides a flexible, powerful way to map option names from their
+    external form (things like subproject:build.option) to something that
+    internally easier to reason about and produce.
+    """
+
+    __slots__ = ['name', 'subproject', 'machine', 'lang', '_hash', 'type', 'module']
+
+    name: str
+    subproject: str
+    machine: MachineChoice
+    lang: T.Optional[str]
+    _hash: int
+    type: OptionType
+    module: T.Optional[str]
+
+    def __init__(self, name: str, subproject: str = '',
+                 machine: MachineChoice = MachineChoice.HOST,
+                 lang: T.Optional[str] = None,
+                 module: T.Optional[str] = None,
+                 _type: T.Optional[OptionType] = None):
+        # the _type option to the constructor is kinda private. We want to be
+        # able tos ave the state and avoid the lookup function when
+        # pickling/unpickling, but we need to be able to calculate it when
+        # constructing a new OptionKey
+        object.__setattr__(self, 'name', name)
+        object.__setattr__(self, 'subproject', subproject)
+        object.__setattr__(self, 'machine', machine)
+        object.__setattr__(self, 'lang', lang)
+        object.__setattr__(self, 'module', module)
+        object.__setattr__(self, '_hash', hash((name, subproject, machine, lang, module)))
+        if _type is None:
+            _type = _classify_argument(self)
+        object.__setattr__(self, 'type', _type)
+
+    def __setattr__(self, key: str, value: T.Any) -> None:
+        raise AttributeError('OptionKey instances do not support mutation.')
+
+    def __getstate__(self) -> T.Dict[str, T.Any]:
+        return {
+            'name': self.name,
+            'subproject': self.subproject,
+            'machine': self.machine,
+            'lang': self.lang,
+            '_type': self.type,
+            'module': self.module,
+        }
+
+    def __setstate__(self, state: T.Dict[str, T.Any]) -> None:
+        """De-serialize the state of a pickle.
+
+        This is very clever. __init__ is not a constructor, it's an
+        initializer, therefore it's safe to call more than once. We create a
+        state in the custom __getstate__ method, which is valid to pass
+        splatted to the initializer.
+        """
+        # Mypy doesn't like this, because it's so clever.
+        self.__init__(**state)  # type: ignore
+
+    def __hash__(self) -> int:
+        return self._hash
+
+    def _to_tuple(self) -> T.Tuple[str, OptionType, str, str, MachineChoice, str]:
+        return (self.subproject, self.type, self.lang or '', self.module or '', self.machine, self.name)
+
+    def __eq__(self, other: object) -> bool:
+        if isinstance(other, OptionKey):
+            return self._to_tuple() == other._to_tuple()
+        return NotImplemented
+
+    def __lt__(self, other: object) -> bool:
+        if isinstance(other, OptionKey):
+            return self._to_tuple() < other._to_tuple()
+        return NotImplemented
+
+    def __str__(self) -> str:
+        out = self.name
+        if self.lang:
+            out = f'{self.lang}_{out}'
+        if self.machine is MachineChoice.BUILD:
+            out = f'build.{out}'
+        if self.module:
+            out = f'{self.module}.{out}'
+        if self.subproject:
+            out = f'{self.subproject}:{out}'
+        return out
+
+    def __repr__(self) -> str:
+        return f'OptionKey({self.name!r}, {self.subproject!r}, {self.machine!r}, {self.lang!r}, {self.module!r}, {self.type!r})'
+
+    @classmethod
+    def from_string(cls, raw: str) -> 'OptionKey':
+        """Parse the raw command line format into a three part tuple.
+
+        This takes strings like `mysubproject:build.myoption` and Creates an
+        OptionKey out of them.
+        """
+        try:
+            subproject, raw2 = raw.split(':')
+        except ValueError:
+            subproject, raw2 = '', raw
+
+        module = None
+        for_machine = MachineChoice.HOST
+        try:
+            prefix, raw3 = raw2.split('.')
+            if prefix == 'build':
+                for_machine = MachineChoice.BUILD
+            else:
+                module = prefix
+        except ValueError:
+            raw3 = raw2
+
+        from ..compilers import all_languages
+        if any(raw3.startswith(f'{l}_') for l in all_languages):
+            lang, opt = raw3.split('_', 1)
+        else:
+            lang, opt = None, raw3
+        assert ':' not in opt
+        assert '.' not in opt
+
+        return cls(opt, subproject, for_machine, lang, module)
+
+    def evolve(self, name: T.Optional[str] = None, subproject: T.Optional[str] = None,
+               machine: T.Optional[MachineChoice] = None, lang: T.Optional[str] = '',
+               module: T.Optional[str] = '') -> 'OptionKey':
+        """Create a new copy of this key, but with alterted members.
+
+        For example:
+        >>> a = OptionKey('foo', '', MachineChoice.Host)
+        >>> b = OptionKey('foo', 'bar', MachineChoice.Host)
+        >>> b == a.evolve(subproject='bar')
+        True
+        """
+        # We have to be a little clever with lang here, because lang is valid
+        # as None, for non-compiler options
+        return OptionKey(
+            name if name is not None else self.name,
+            subproject if subproject is not None else self.subproject,
+            machine if machine is not None else self.machine,
+            lang if lang != '' else self.lang,
+            module if module != '' else self.module
+        )
+
+    def as_root(self) -> 'OptionKey':
+        """Convenience method for key.evolve(subproject='')."""
+        return self.evolve(subproject='')
+
+    def as_build(self) -> 'OptionKey':
+        """Convenience method for key.evolve(machine=MachinceChoice.BUILD)."""
+        return self.evolve(machine=MachineChoice.BUILD)
+
+    def as_host(self) -> 'OptionKey':
+        """Convenience method for key.evolve(machine=MachinceChoice.HOST)."""
+        return self.evolve(machine=MachineChoice.HOST)
+
+    def is_backend(self) -> bool:
+        """Convenience method to check if this is a backend option."""
+        return self.type is OptionType.BACKEND
+
+    def is_builtin(self) -> bool:
+        """Convenience method to check if this is a builtin option."""
+        return self.type is OptionType.BUILTIN
+
+    def is_compiler(self) -> bool:
+        """Convenience method to check if this is a builtin option."""
+        return self.type is OptionType.COMPILER
+
+    def is_project(self) -> bool:
+        """Convenience method to check if this is a project option."""
+        return self.type is OptionType.PROJECT
+
+    def is_base(self) -> bool:
+        """Convenience method to check if this is a base option."""
+        return self.type is OptionType.BASE
diff -Nru meson-0.53.2/mesonbuild/mesonlib/vsenv.py meson-0.61.2/mesonbuild/mesonlib/vsenv.py
--- meson-0.53.2/mesonbuild/mesonlib/vsenv.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesonlib/vsenv.py	2022-01-17 10:50:38.000000000 +0000
@@ -0,0 +1,112 @@
+import os
+import subprocess
+import json
+import pathlib
+import platform
+import shutil
+import tempfile
+
+from .. import mlog
+from .universal import MesonException, is_windows
+
+
+bat_template = '''@ECHO OFF
+
+call "{}"
+
+ECHO {}
+SET
+'''
+
+# If on Windows and VS is installed but not set up in the environment,
+# set it to be runnable. In this way Meson can be directly invoked
+# from any shell, VS Code etc.
+def _setup_vsenv(force: bool) -> bool:
+    if not is_windows():
+        return False
+    if os.environ.get('OSTYPE') == 'cygwin':
+        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
+        if shutil.which('gcc'):
+            return False
+        if shutil.which('clang'):
+            return False
+        if shutil.which('clang-cl'):
+            return False
+
+    root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles")
+    bat_locator_bin = pathlib.Path(root, 'Microsoft Visual Studio/Installer/vswhere.exe')
+    if not bat_locator_bin.exists():
+        raise MesonException(f'Could not find {bat_locator_bin}')
+    bat_json = subprocess.check_output(
+        [
+            str(bat_locator_bin),
+            '-latest',
+            '-prerelease',
+            '-requiresAny',
+            '-requires', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
+            '-requires', 'Microsoft.VisualStudio.Workload.WDExpress',
+            '-products', '*',
+            '-utf8',
+            '-format',
+            'json'
+        ]
+    )
+    bat_info = json.loads(bat_json)
+    if not bat_info:
+        # VS installer instelled but not VS itself maybe?
+        raise MesonException(f'Could not parse vswhere.exe output')
+    bat_root = pathlib.Path(bat_info[0]['installationPath'])
+    if platform.machine() == 'ARM64':
+        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}')
+
+    mlog.log('Activating VS', bat_info[0]['catalog']['productDisplayVersion'])
+    bat_separator = '---SPLIT---'
+    bat_contents = bat_template.format(bat_path, bat_separator)
+    bat_file = tempfile.NamedTemporaryFile('w', suffix='.bat', encoding='utf-8', delete=False)
+    bat_file.write(bat_contents)
+    bat_file.flush()
+    bat_file.close()
+    bat_output = subprocess.check_output(bat_file.name, universal_newlines=True)
+    os.unlink(bat_file.name)
+    bat_lines = bat_output.split('\n')
+    bat_separator_seen = False
+    for bat_line in bat_lines:
+        if bat_line == bat_separator:
+            bat_separator_seen = True
+            continue
+        if not bat_separator_seen:
+            continue
+        if not bat_line:
+            continue
+        k, v = bat_line.split('=', 1)
+        os.environ[k] = v
+    return True
+
+def setup_vsenv(force: bool = False) -> bool:
+    try:
+        return _setup_vsenv(force)
+    except MesonException as e:
+        if force:
+            raise
+        mlog.warning('Failed to activate VS environment:', str(e))
+        return False
diff -Nru meson-0.53.2/mesonbuild/mesonlib/win32.py meson-0.61.2/mesonbuild/mesonlib/win32.py
--- meson-0.53.2/mesonbuild/mesonlib/win32.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesonlib/win32.py	2021-07-20 08:56:20.000000000 +0000
@@ -0,0 +1,39 @@
+# SPDX-license-identifier: Apache-2.0
+# Copyright 2012-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+# 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.
+
+"""Windows specific implementations of mesonlib functionality."""
+
+import msvcrt
+import typing as T
+
+from .universal import MesonException
+from .platform import BuildDirLock as BuildDirLockBase
+
+__all__ = ['BuildDirLock']
+
+class BuildDirLock(BuildDirLockBase):
+
+    def __enter__(self) -> None:
+        self.lockfile = open(self.lockfilename, 'w', encoding='utf-8')
+        try:
+            msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1)
+        except (BlockingIOError, PermissionError):
+            self.lockfile.close()
+            raise MesonException('Some other Meson process is already using this build directory. Exiting.')
+
+    def __exit__(self, *args: T.Any) -> None:
+        msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1)
+        self.lockfile.close()
diff -Nru meson-0.53.2/mesonbuild/mesonlib.py meson-0.61.2/mesonbuild/mesonlib.py
--- meson-0.53.2/mesonbuild/mesonlib.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesonlib.py	1970-01-01 00:00:00.000000000 +0000
@@ -1,1577 +0,0 @@
-# Copyright 2012-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.
-
-"""A library of random helper functionality."""
-from pathlib import Path
-import sys
-import stat
-import time
-import platform, subprocess, operator, os, shlex, shutil, re
-import collections
-from enum import Enum
-from functools import lru_cache, update_wrapper
-from itertools import tee, filterfalse
-import typing as T
-import uuid
-
-from mesonbuild import mlog
-
-_T = T.TypeVar('_T')
-_U = T.TypeVar('_U')
-
-have_fcntl = False
-have_msvcrt = False
-# {subproject: project_meson_version}
-project_meson_versions = {}
-
-try:
-    import fcntl
-    have_fcntl = True
-except Exception:
-    pass
-
-try:
-    import msvcrt
-    have_msvcrt = True
-except Exception:
-    pass
-
-from glob import glob
-
-if os.path.basename(sys.executable) == 'meson.exe':
-    # In Windows and using the MSI installed executable.
-    python_command = [sys.executable, 'runpython']
-else:
-    python_command = [sys.executable]
-meson_command = None
-
-GIT = shutil.which('git')
-def git(cmd: T.List[str], workingdir: str, **kwargs) -> subprocess.CompletedProcess:
-    pc = subprocess.run([GIT, '-C', workingdir] + cmd,
-                        # Redirect stdin to DEVNULL otherwise git messes up the
-                        # console and ANSI colors stop working on Windows.
-                        stdin=subprocess.DEVNULL, **kwargs)
-    # Sometimes git calls git recursively, such as `git submodule update
-    # --recursive` which will be without the above workaround, so set the
-    # console mode again just in case.
-    mlog.setup_console()
-    return pc
-
-
-def set_meson_command(mainfile):
-    global python_command
-    global meson_command
-    # On UNIX-like systems `meson` is a Python script
-    # On Windows `meson` and `meson.exe` are wrapper exes
-    if not mainfile.endswith('.py'):
-        meson_command = [mainfile]
-    elif os.path.isabs(mainfile) and mainfile.endswith('mesonmain.py'):
-        # Can't actually run meson with an absolute path to mesonmain.py, it must be run as -m mesonbuild.mesonmain
-        meson_command = python_command + ['-m', 'mesonbuild.mesonmain']
-    else:
-        # Either run uninstalled, or full path to meson-script.py
-        meson_command = python_command + [mainfile]
-    # We print this value for unit tests.
-    if 'MESON_COMMAND_TESTS' in os.environ:
-        mlog.log('meson_command is {!r}'.format(meson_command))
-
-def is_ascii_string(astring) -> bool:
-    try:
-        if isinstance(astring, str):
-            astring.encode('ascii')
-        elif isinstance(astring, bytes):
-            astring.decode('ascii')
-    except UnicodeDecodeError:
-        return False
-    return True
-
-def check_direntry_issues(direntry_array):
-    import locale
-    # Warn if the locale is not UTF-8. This can cause various unfixable issues
-    # such as os.stat not being able to decode filenames with unicode in them.
-    # There is no way to reset both the preferred encoding and the filesystem
-    # encoding, so we can just warn about it.
-    e = locale.getpreferredencoding()
-    if e.upper() != 'UTF-8' and not is_windows():
-        if not isinstance(direntry_array, list):
-            direntry_array = [direntry_array]
-        for de in direntry_array:
-            if is_ascii_string(de):
-                continue
-            mlog.warning('''You are using {!r} which is not a Unicode-compatible '
-locale but you are trying to access a file system entry called {!r} which is
-not pure ASCII. This may cause problems.
-'''.format(e, de), file=sys.stderr)
-
-# Put this in objects that should not get dumped to pickle files
-# by accident.
-import threading
-an_unpicklable_object = threading.Lock()
-
-class MesonException(Exception):
-    '''Exceptions thrown by Meson'''
-
-    def get_msg_with_context(self):
-        s = ''
-        if hasattr(self, 'lineno') and hasattr(self, 'file'):
-            s = get_error_location_string(self.file, self.lineno) + ' '
-        s += str(self)
-        return s
-
-class EnvironmentException(MesonException):
-    '''Exceptions thrown while processing and creating the build environment'''
-
-class FileMode:
-    # The first triad is for owner permissions, the second for group permissions,
-    # and the third for others (everyone else).
-    # For the 1st character:
-    #  'r' means can read
-    #  '-' means not allowed
-    # For the 2nd character:
-    #  'w' means can write
-    #  '-' means not allowed
-    # For the 3rd character:
-    #  'x' means can execute
-    #  's' means can execute and setuid/setgid is set (owner/group triads only)
-    #  'S' means cannot execute and setuid/setgid is set (owner/group triads only)
-    #  't' means can execute and sticky bit is set ("others" triads only)
-    #  'T' means cannot execute and sticky bit is set ("others" triads only)
-    #  '-' means none of these are allowed
-    #
-    # The meanings of 'rwx' perms is not obvious for directories; see:
-    # https://www.hackinglinuxexposed.com/articles/20030424.html
-    #
-    # For information on this notation such as setuid/setgid/sticky bits, see:
-    # https://en.wikipedia.org/wiki/File_system_permissions#Symbolic_notation
-    symbolic_perms_regex = re.compile('[r-][w-][xsS-]' # Owner perms
-                                      '[r-][w-][xsS-]' # Group perms
-                                      '[r-][w-][xtT-]') # Others perms
-
-    def __init__(self, perms=None, owner=None, group=None):
-        self.perms_s = perms
-        self.perms = self.perms_s_to_bits(perms)
-        self.owner = owner
-        self.group = group
-
-    def __repr__(self):
-        ret = ' str:
-        return self.relative_name()
-
-    def __repr__(self) -> str:
-        ret = ' str:
-        if self.is_built:
-            return self.relative_name()
-        else:
-            return os.path.join(build_to_src, self.subdir, self.fname)
-
-    @lru_cache(maxsize=None)
-    def absolute_path(self, srcdir: str, builddir: str) -> str:
-        absdir = srcdir
-        if self.is_built:
-            absdir = builddir
-        return os.path.join(absdir, self.relative_name())
-
-    def endswith(self, ending: str) -> bool:
-        return self.fname.endswith(ending)
-
-    def split(self, s: str) -> T.List[str]:
-        return self.fname.split(s)
-
-    def __eq__(self, other) -> bool:
-        return (self.fname, self.subdir, self.is_built) == (other.fname, other.subdir, other.is_built)
-
-    def __hash__(self) -> int:
-        return hash((self.fname, self.subdir, self.is_built))
-
-    @lru_cache(maxsize=None)
-    def relative_name(self) -> str:
-        return os.path.join(self.subdir, self.fname)
-
-
-def get_compiler_for_source(compilers, src):
-    for comp in compilers:
-        if comp.can_compile(src):
-            return comp
-    raise MesonException('No specified compiler can handle file {!s}'.format(src))
-
-def classify_unity_sources(compilers, sources):
-    compsrclist = {}
-    for src in sources:
-        comp = get_compiler_for_source(compilers, src)
-        if comp not in compsrclist:
-            compsrclist[comp] = [src]
-        else:
-            compsrclist[comp].append(src)
-    return compsrclist
-
-class OrderedEnum(Enum):
-    """
-    An Enum which additionally offers homogeneous ordered comparison.
-    """
-    def __ge__(self, other):
-        if self.__class__ is other.__class__:
-            return self.value >= other.value
-        return NotImplemented
-
-    def __gt__(self, other):
-        if self.__class__ is other.__class__:
-            return self.value > other.value
-        return NotImplemented
-
-    def __le__(self, other):
-        if self.__class__ is other.__class__:
-            return self.value <= other.value
-        return NotImplemented
-
-    def __lt__(self, other):
-        if self.__class__ is other.__class__:
-            return self.value < other.value
-        return NotImplemented
-
-
-class MachineChoice(OrderedEnum):
-
-    """Enum class representing one of the two abstract machine names used in
-    most places: the build, and host, machines.
-    """
-
-    BUILD = 0
-    HOST = 1
-
-    def get_lower_case_name(self):
-        return PerMachine('build', 'host')[self]
-
-    def get_prefix(self):
-        return PerMachine('build.', '')[self]
-
-
-class PerMachine(T.Generic[_T]):
-    def __init__(self, build: _T, host: _T):
-        self.build = build
-        self.host = host
-
-    def __getitem__(self, machine: MachineChoice) -> _T:
-        return {
-            MachineChoice.BUILD:  self.build,
-            MachineChoice.HOST:   self.host,
-        }[machine]
-
-    def __setitem__(self, machine: MachineChoice, val: _T) -> None:
-        setattr(self, machine.get_lower_case_name(), val)
-
-    def miss_defaulting(self) -> "PerMachineDefaultable[T.Optional[_T]]":
-        """Unset definition duplicated from their previous to None
-
-        This is the inverse of ''default_missing''. By removing defaulted
-        machines, we can elaborate the original and then redefault them and thus
-        avoid repeating the elaboration explicitly.
-        """
-        unfreeze = PerMachineDefaultable() # type: PerMachineDefaultable[T.Optional[_T]]
-        unfreeze.build = self.build
-        unfreeze.host = self.host
-        if unfreeze.host == unfreeze.build:
-            unfreeze.host = None
-        return unfreeze
-
-
-class PerThreeMachine(PerMachine[_T]):
-    """Like `PerMachine` but includes `target` too.
-
-    It turns out just one thing do we need track the target machine. There's no
-    need to computer the `target` field so we don't bother overriding the
-    `__getitem__`/`__setitem__` methods.
-    """
-    def __init__(self, build: _T, host: _T, target: _T):
-        super().__init__(build, host)
-        self.target = target
-
-    def miss_defaulting(self) -> "PerThreeMachineDefaultable[T.Optional[_T]]":
-        """Unset definition duplicated from their previous to None
-
-        This is the inverse of ''default_missing''. By removing defaulted
-        machines, we can elaborate the original and then redefault them and thus
-        avoid repeating the elaboration explicitly.
-        """
-        unfreeze = PerThreeMachineDefaultable() # type: PerThreeMachineDefaultable[T.Optional[_T]]
-        unfreeze.build = self.build
-        unfreeze.host = self.host
-        unfreeze.target = self.target
-        if unfreeze.target == unfreeze.host:
-            unfreeze.target = None
-        if unfreeze.host == unfreeze.build:
-            unfreeze.host = None
-        return unfreeze
-
-    def matches_build_machine(self, machine: MachineChoice) -> bool:
-        return self.build == self[machine]
-
-class PerMachineDefaultable(PerMachine[T.Optional[_T]]):
-    """Extends `PerMachine` with the ability to default from `None`s.
-    """
-    def __init__(self) -> None:
-        super().__init__(None, None)
-
-    def default_missing(self) -> "PerMachine[T.Optional[_T]]":
-        """Default host to build
-
-        This allows just specifying nothing in the native case, and just host in the
-        cross non-compiler case.
-        """
-        freeze = PerMachine(self.build, self.host)
-        if freeze.host is None:
-            freeze.host = freeze.build
-        return freeze
-
-
-class PerThreeMachineDefaultable(PerMachineDefaultable, PerThreeMachine[T.Optional[_T]]):
-    """Extends `PerThreeMachine` with the ability to default from `None`s.
-    """
-    def __init__(self) -> None:
-        PerThreeMachine.__init__(self, None, None, None)
-
-    def default_missing(self) -> "PerThreeMachine[T.Optional[_T]]":
-        """Default host to build and target to host.
-
-        This allows just specifying nothing in the native case, just host in the
-        cross non-compiler case, and just target in the native-built
-        cross-compiler case.
-        """
-        freeze = PerThreeMachine(self.build, self.host, self.target)
-        if freeze.host is None:
-            freeze.host = freeze.build
-        if freeze.target is None:
-            freeze.target = freeze.host
-        return freeze
-
-
-def is_sunos() -> bool:
-    return platform.system().lower() == 'sunos'
-
-def is_osx() -> bool:
-    return platform.system().lower() == 'darwin'
-
-def is_linux() -> bool:
-    return platform.system().lower() == 'linux'
-
-def is_android() -> bool:
-    return platform.system().lower() == 'android'
-
-def is_haiku() -> bool:
-    return platform.system().lower() == 'haiku'
-
-def is_openbsd() -> bool:
-    return platform.system().lower() == 'openbsd'
-
-def is_windows() -> bool:
-    platname = platform.system().lower()
-    return platname == 'windows' or 'mingw' in platname
-
-def is_cygwin() -> bool:
-    return platform.system().lower().startswith('cygwin')
-
-def is_debianlike() -> bool:
-    return os.path.isfile('/etc/debian_version')
-
-def is_dragonflybsd() -> bool:
-    return platform.system().lower() == 'dragonfly'
-
-def is_netbsd() -> bool:
-    return platform.system().lower() == 'netbsd'
-
-def is_freebsd() -> bool:
-    return platform.system().lower() == 'freebsd'
-
-def exe_exists(arglist: T.List[str]) -> bool:
-    try:
-        if subprocess.run(arglist, timeout=10).returncode == 0:
-            return True
-    except (FileNotFoundError, subprocess.TimeoutExpired):
-        pass
-    return False
-
-@lru_cache(maxsize=None)
-def darwin_get_object_archs(objpath):
-    '''
-    For a specific object (executable, static library, dylib, etc), run `lipo`
-    to fetch the list of archs supported by it. Supports both thin objects and
-    'fat' objects.
-    '''
-    _, stdo, stderr = Popen_safe(['lipo', '-info', objpath])
-    if not stdo:
-        mlog.debug('lipo {}: {}'.format(objpath, stderr))
-        return None
-    stdo = stdo.rsplit(': ', 1)[1]
-    # Convert from lipo-style archs to meson-style CPUs
-    stdo = stdo.replace('i386', 'x86')
-    stdo = stdo.replace('arm64', 'aarch64')
-    # Add generic name for armv7 and armv7s
-    if 'armv7' in stdo:
-        stdo += ' arm'
-    return stdo.split()
-
-def detect_vcs(source_dir):
-    vcs_systems = [
-        dict(name = 'git',        cmd = 'git', repo_dir = '.git', get_rev = 'git describe --dirty=+', rev_regex = '(.*)', dep = '.git/logs/HEAD'),
-        dict(name = 'mercurial',  cmd = 'hg',  repo_dir = '.hg',  get_rev = 'hg id -i',               rev_regex = '(.*)', dep = '.hg/dirstate'),
-        dict(name = 'subversion', cmd = 'svn', repo_dir = '.svn', get_rev = 'svn info',               rev_regex = 'Revision: (.*)', dep = '.svn/wc.db'),
-        dict(name = 'bazaar',     cmd = 'bzr', repo_dir = '.bzr', get_rev = 'bzr revno',              rev_regex = '(.*)', dep = '.bzr'),
-    ]
-    # FIXME: this is much cleaner with pathlib.Path
-    segs = source_dir.replace('\\', '/').split('/')
-    for i in range(len(segs), -1, -1):
-        curdir = '/'.join(segs[:i])
-        for vcs in vcs_systems:
-            if os.path.isdir(os.path.join(curdir, vcs['repo_dir'])) and shutil.which(vcs['cmd']):
-                vcs['wc_dir'] = curdir
-                return vcs
-    return None
-
-# a helper class which implements the same version ordering as RPM
-class Version:
-    def __init__(self, s):
-        self._s = s
-
-        # split into numeric, alphabetic and non-alphanumeric sequences
-        sequences = re.finditer(r'(\d+|[a-zA-Z]+|[^a-zA-Z\d]+)', s)
-        # non-alphanumeric separators are discarded
-        sequences = [m for m in sequences if not re.match(r'[^a-zA-Z\d]+', m.group(1))]
-        # numeric sequences are converted from strings to ints
-        sequences = [int(m.group(1)) if m.group(1).isdigit() else m.group(1) for m in sequences]
-
-        self._v = sequences
-
-    def __str__(self):
-        return '%s (V=%s)' % (self._s, str(self._v))
-
-    def __repr__(self):
-        return ''.format(self._s)
-
-    def __lt__(self, other):
-        if isinstance(other, Version):
-            return self.__cmp(other, operator.lt)
-        return NotImplemented
-
-    def __gt__(self, other):
-        if isinstance(other, Version):
-            return self.__cmp(other, operator.gt)
-        return NotImplemented
-
-    def __le__(self, other):
-        if isinstance(other, Version):
-            return self.__cmp(other, operator.le)
-        return NotImplemented
-
-    def __ge__(self, other):
-        if isinstance(other, Version):
-            return self.__cmp(other, operator.ge)
-        return NotImplemented
-
-    def __eq__(self, other):
-        if isinstance(other, Version):
-            return self._v == other._v
-        return NotImplemented
-
-    def __ne__(self, other):
-        if isinstance(other, Version):
-            return self._v != other._v
-        return NotImplemented
-
-    def __cmp(self, other, comparator):
-        # compare each sequence in order
-        for ours, theirs in zip(self._v, other._v):
-            # sort a non-digit sequence before a digit sequence
-            ours_is_int = isinstance(ours, int)
-            theirs_is_int = isinstance(theirs, int)
-            if ours_is_int != theirs_is_int:
-                return comparator(ours_is_int, theirs_is_int)
-
-            if ours != theirs:
-                return comparator(ours, theirs)
-
-        # if equal length, all components have matched, so equal
-        # otherwise, the version with a suffix remaining is greater
-        return comparator(len(self._v), len(other._v))
-
-def _version_extract_cmpop(vstr2: str) -> T.Tuple[T.Callable[[T.Any, T.Any], bool], str]:
-    if vstr2.startswith('>='):
-        cmpop = operator.ge
-        vstr2 = vstr2[2:]
-    elif vstr2.startswith('<='):
-        cmpop = operator.le
-        vstr2 = vstr2[2:]
-    elif vstr2.startswith('!='):
-        cmpop = operator.ne
-        vstr2 = vstr2[2:]
-    elif vstr2.startswith('=='):
-        cmpop = operator.eq
-        vstr2 = vstr2[2:]
-    elif vstr2.startswith('='):
-        cmpop = operator.eq
-        vstr2 = vstr2[1:]
-    elif vstr2.startswith('>'):
-        cmpop = operator.gt
-        vstr2 = vstr2[1:]
-    elif vstr2.startswith('<'):
-        cmpop = operator.lt
-        vstr2 = vstr2[1:]
-    else:
-        cmpop = operator.eq
-
-    return (cmpop, vstr2)
-
-def version_compare(vstr1: str, vstr2: str) -> bool:
-    (cmpop, vstr2) = _version_extract_cmpop(vstr2)
-    return cmpop(Version(vstr1), Version(vstr2))
-
-def version_compare_many(vstr1, conditions):
-    if not isinstance(conditions, (list, tuple, frozenset)):
-        conditions = [conditions]
-    found = []
-    not_found = []
-    for req in conditions:
-        if not version_compare(vstr1, req):
-            not_found.append(req)
-        else:
-            found.append(req)
-    return not_found == [], not_found, found
-
-# determine if the minimum version satisfying the condition |condition| exceeds
-# the minimum version for a feature |minimum|
-def version_compare_condition_with_min(condition: str, minimum: str) -> bool:
-    if condition.startswith('>='):
-        cmpop = operator.le
-        condition = condition[2:]
-    elif condition.startswith('<='):
-        return False
-    elif condition.startswith('!='):
-        return False
-    elif condition.startswith('=='):
-        cmpop = operator.le
-        condition = condition[2:]
-    elif condition.startswith('='):
-        cmpop = operator.le
-        condition = condition[1:]
-    elif condition.startswith('>'):
-        cmpop = operator.lt
-        condition = condition[1:]
-    elif condition.startswith('<'):
-        return False
-    else:
-        cmpop = operator.le
-
-    # Declaring a project(meson_version: '>=0.46') and then using features in
-    # 0.46.0 is valid, because (knowing the meson versioning scheme) '0.46.0' is
-    # the lowest version which satisfies the constraint '>=0.46'.
-    #
-    # But this will fail here, because the minimum version required by the
-    # version constraint ('0.46') is strictly less (in our version comparison)
-    # than the minimum version needed for the feature ('0.46.0').
-    #
-    # Map versions in the constraint of the form '0.46' to '0.46.0', to embed
-    # this knowledge of the meson versioning scheme.
-    condition = condition.strip()
-    if re.match(r'^\d+.\d+$', condition):
-        condition += '.0'
-
-    return cmpop(Version(minimum), Version(condition))
-
-def default_libdir():
-    if is_debianlike():
-        try:
-            pc = subprocess.Popen(['dpkg-architecture', '-qDEB_HOST_MULTIARCH'],
-                                  stdout=subprocess.PIPE,
-                                  stderr=subprocess.DEVNULL)
-            (stdo, _) = pc.communicate()
-            if pc.returncode == 0:
-                archpath = stdo.decode().strip()
-                return 'lib/' + archpath
-        except Exception:
-            pass
-    if is_freebsd():
-        return 'lib'
-    if os.path.isdir('/usr/lib64') and not os.path.islink('/usr/lib64'):
-        return 'lib64'
-    return 'lib'
-
-def default_libexecdir():
-    # There is no way to auto-detect this, so it must be set at build time
-    return 'libexec'
-
-def default_prefix():
-    return 'c:/' if is_windows() else '/usr/local'
-
-def get_library_dirs() -> T.List[str]:
-    if is_windows():
-        return ['C:/mingw/lib'] # TODO: get programmatically
-    if is_osx():
-        return ['/usr/lib'] # TODO: get programmatically
-    # The following is probably Debian/Ubuntu specific.
-    # /usr/local/lib is first because it contains stuff
-    # installed by the sysadmin and is probably more up-to-date
-    # than /usr/lib. If you feel that this search order is
-    # problematic, please raise the issue on the mailing list.
-    unixdirs = ['/usr/local/lib', '/usr/lib', '/lib']
-
-    if is_freebsd():
-        return unixdirs
-    # FIXME: this needs to be further genericized for aarch64 etc.
-    machine = platform.machine()
-    if machine in ('i386', 'i486', 'i586', 'i686'):
-        plat = 'i386'
-    elif machine.startswith('arm'):
-        plat = 'arm'
-    else:
-        plat = ''
-
-    # Solaris puts 32-bit libraries in the main /lib & /usr/lib directories
-    # and 64-bit libraries in platform specific subdirectories.
-    if is_sunos():
-        if machine == 'i86pc':
-            plat = 'amd64'
-        elif machine.startswith('sun4'):
-            plat = 'sparcv9'
-
-    usr_platdir = Path('/usr/lib/') / plat
-    if usr_platdir.is_dir():
-        unixdirs += [str(x) for x in (usr_platdir).iterdir() if x.is_dir()]
-    if os.path.exists('/usr/lib64'):
-        unixdirs.append('/usr/lib64')
-
-    lib_platdir = Path('/lib/') / plat
-    if lib_platdir.is_dir():
-        unixdirs += [str(x) for x in (lib_platdir).iterdir() if x.is_dir()]
-    if os.path.exists('/lib64'):
-        unixdirs.append('/lib64')
-
-    return unixdirs
-
-def has_path_sep(name, sep='/\\'):
-    'Checks if any of the specified @sep path separators are in @name'
-    for each in sep:
-        if each in name:
-            return True
-    return False
-
-
-if is_windows():
-    # shlex.split is not suitable for splitting command line on Window (https://bugs.python.org/issue1724822);
-    # shlex.quote is similarly problematic. Below are "proper" implementations of these functions according to
-    # https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments and
-    # https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
-
-    _whitespace = ' \t\n\r'
-    _find_unsafe_char = re.compile(r'[{}"]'.format(_whitespace)).search
-
-    def quote_arg(arg):
-        if arg and not _find_unsafe_char(arg):
-            return arg
-
-        result = '"'
-        num_backslashes = 0
-        for c in arg:
-            if c == '\\':
-                num_backslashes += 1
-            else:
-                if c == '"':
-                    # Escape all backslashes and the following double quotation mark
-                    num_backslashes = num_backslashes * 2 + 1
-
-                result += num_backslashes * '\\' + c
-                num_backslashes = 0
-
-        # Escape all backslashes, but let the terminating double quotation
-        # mark we add below be interpreted as a metacharacter
-        result += (num_backslashes * 2) * '\\' + '"'
-        return result
-
-    def split_args(cmd: T.Sequence[str]) -> T.List[str]:
-        result = []
-        arg = ''
-        num_backslashes = 0
-        num_quotes = 0
-        in_quotes = False
-        for c in cmd:
-            if c == '\\':
-                num_backslashes += 1
-            else:
-                if c == '"' and not (num_backslashes % 2):
-                    # unescaped quote, eat it
-                    arg += (num_backslashes // 2) * '\\'
-                    num_quotes += 1
-                    in_quotes = not in_quotes
-                elif c in _whitespace and not in_quotes:
-                    if arg or num_quotes:
-                        # reached the end of the argument
-                        result.append(arg)
-                        arg = ''
-                        num_quotes = 0
-                else:
-                    if c == '"':
-                        # escaped quote
-                        num_backslashes = (num_backslashes - 1) // 2
-
-                    arg += num_backslashes * '\\' + c
-
-                num_backslashes = 0
-
-        if arg or num_quotes:
-            result.append(arg)
-
-        return result
-else:
-    def quote_arg(arg):
-        return shlex.quote(arg)
-
-    def split_args(cmd):
-        return shlex.split(cmd)
-
-
-def join_args(args):
-    return ' '.join([quote_arg(x) for x in args])
-
-
-def do_replacement(regex, line, variable_format, confdata):
-    missing_variables = set()
-    start_tag = '@'
-    backslash_tag = '\\@'
-    if variable_format == 'cmake':
-        start_tag = '${'
-        backslash_tag = '\\${'
-
-    def variable_replace(match):
-        # Pairs of escape characters before '@' or '\@'
-        if match.group(0).endswith('\\'):
-            num_escapes = match.end(0) - match.start(0)
-            return '\\' * (num_escapes // 2)
-        # Single escape character and '@'
-        elif match.group(0) == backslash_tag:
-            return start_tag
-        # Template variable to be replaced
-        else:
-            varname = match.group(1)
-            if varname in confdata:
-                (var, desc) = confdata.get(varname)
-                if isinstance(var, str):
-                    pass
-                elif isinstance(var, int):
-                    var = str(var)
-                else:
-                    msg = 'Tried to replace variable {!r} value with ' \
-                          'something other than a string or int: {!r}'
-                    raise MesonException(msg.format(varname, var))
-            else:
-                missing_variables.add(varname)
-                var = ''
-            return var
-    return re.sub(regex, variable_replace, line), missing_variables
-
-def do_mesondefine(line, confdata):
-    arr = line.split()
-    if len(arr) != 2:
-        raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip())
-    varname = arr[1]
-    try:
-        (v, desc) = confdata.get(varname)
-    except KeyError:
-        return '/* #undef %s */\n' % varname
-    if isinstance(v, bool):
-        if v:
-            return '#define %s\n' % varname
-        else:
-            return '#undef %s\n' % varname
-    elif isinstance(v, int):
-        return '#define %s %d\n' % (varname, v)
-    elif isinstance(v, str):
-        return '#define %s %s\n' % (varname, v)
-    else:
-        raise MesonException('#mesondefine argument "%s" is of unknown type.' % varname)
-
-
-def do_conf_file(src, dst, confdata, variable_format, encoding='utf-8'):
-    try:
-        with open(src, encoding=encoding, newline='') as f:
-            data = f.readlines()
-    except Exception as e:
-        raise MesonException('Could not read input file %s: %s' % (src, str(e)))
-    # Only allow (a-z, A-Z, 0-9, _, -) as valid characters for a define
-    # Also allow escaping '@' with '\@'
-    if variable_format in ['meson', 'cmake@']:
-        regex = re.compile(r'(?:\\\\)+(?=\\?@)|\\@|@([-a-zA-Z0-9_]+)@')
-    elif variable_format == 'cmake':
-        regex = re.compile(r'(?:\\\\)+(?=\\?\$)|\\\${|\${([-a-zA-Z0-9_]+)}')
-    else:
-        raise MesonException('Format "{}" not handled'.format(variable_format))
-
-    search_token = '#mesondefine'
-    if variable_format != 'meson':
-        search_token = '#cmakedefine'
-
-    result = []
-    missing_variables = set()
-    # Detect when the configuration data is empty and no tokens were found
-    # during substitution so we can warn the user to use the `copy:` kwarg.
-    confdata_useless = not confdata.keys()
-    for line in data:
-        if line.startswith(search_token):
-            confdata_useless = False
-            line = do_mesondefine(line, confdata)
-        else:
-            line, missing = do_replacement(regex, line, variable_format, confdata)
-            missing_variables.update(missing)
-            if missing:
-                confdata_useless = False
-        result.append(line)
-    dst_tmp = dst + '~'
-    try:
-        with open(dst_tmp, 'w', encoding=encoding, newline='') as f:
-            f.writelines(result)
-    except Exception as e:
-        raise MesonException('Could not write output file %s: %s' % (dst, str(e)))
-    shutil.copymode(src, dst_tmp)
-    replace_if_different(dst, dst_tmp)
-    return missing_variables, confdata_useless
-
-CONF_C_PRELUDE = '''/*
- * Autogenerated by the Meson build system.
- * Do not edit, your changes will be lost.
- */
-
-#pragma once
-
-'''
-
-CONF_NASM_PRELUDE = '''; Autogenerated by the Meson build system.
-; Do not edit, your changes will be lost.
-
-'''
-
-def dump_conf_header(ofilename, cdata, output_format):
-    if output_format == 'c':
-        prelude = CONF_C_PRELUDE
-        prefix = '#'
-    elif output_format == 'nasm':
-        prelude = CONF_NASM_PRELUDE
-        prefix = '%'
-
-    ofilename_tmp = ofilename + '~'
-    with open(ofilename_tmp, 'w', encoding='utf-8') as ofile:
-        ofile.write(prelude)
-        for k in sorted(cdata.keys()):
-            (v, desc) = cdata.get(k)
-            if desc:
-                if output_format == 'c':
-                    ofile.write('/* %s */\n' % desc)
-                elif output_format == 'nasm':
-                    for line in desc.split('\n'):
-                        ofile.write('; %s\n' % line)
-            if isinstance(v, bool):
-                if v:
-                    ofile.write('%sdefine %s\n\n' % (prefix, k))
-                else:
-                    ofile.write('%sundef %s\n\n' % (prefix, k))
-            elif isinstance(v, (int, str)):
-                ofile.write('%sdefine %s %s\n\n' % (prefix, k, v))
-            else:
-                raise MesonException('Unknown data type in configuration file entry: ' + k)
-    replace_if_different(ofilename, ofilename_tmp)
-
-def replace_if_different(dst, dst_tmp):
-    # If contents are identical, don't touch the file to prevent
-    # unnecessary rebuilds.
-    different = True
-    try:
-        with open(dst, 'rb') as f1, open(dst_tmp, 'rb') as f2:
-            if f1.read() == f2.read():
-                different = False
-    except FileNotFoundError:
-        pass
-    if different:
-        os.replace(dst_tmp, dst)
-    else:
-        os.unlink(dst_tmp)
-
-def listify(item: T.Any,
-            flatten: bool = True,
-            unholder: bool = False) -> T.List[T.Any]:
-    '''
-    Returns a list with all args embedded in a list if they are not a list.
-    This function preserves order.
-    @flatten: Convert lists of lists to a flat list
-    @unholder: Replace each item with the object it holds, if required
-
-    Note: unholding only works recursively when flattening
-    '''
-    if not isinstance(item, list):
-        if unholder and hasattr(item, 'held_object'):
-            item = item.held_object
-        return [item]
-    result = []
-    for i in item:
-        if unholder and hasattr(i, 'held_object'):
-            i = i.held_object
-        if flatten and isinstance(i, list):
-            result += listify(i, flatten=True, unholder=unholder)
-        else:
-            result.append(i)
-    return result
-
-
-def extract_as_list(dict_object, *keys, pop=False, **kwargs):
-    '''
-    Extracts all values from given dict_object and listifies them.
-    '''
-    result = []
-    fetch = dict_object.get
-    if pop:
-        fetch = dict_object.pop
-    # If there's only one key, we don't return a list with one element
-    if len(keys) == 1:
-        return listify(fetch(keys[0], []), **kwargs)
-    # Return a list of values corresponding to *keys
-    for key in keys:
-        result.append(listify(fetch(key, []), **kwargs))
-    return result
-
-def typeslistify(item: 'T.Union[_T, T.List[_T]]',
-                 types: 'T.Union[T.Type[_T], T.Tuple[T.Type[_T]]]') -> T.List[_T]:
-    '''
-    Ensure that type(@item) is one of @types or a
-    list of items all of which are of type @types
-    '''
-    if isinstance(item, types):
-        item = T.cast(T.List[_T], [item])
-    if not isinstance(item, list):
-        raise MesonException('Item must be a list or one of {!r}'.format(types))
-    for i in item:
-        if i is not None and not isinstance(i, types):
-            raise MesonException('List item must be one of {!r}'.format(types))
-    return item
-
-def stringlistify(item: T.Union[str, T.List[str]]) -> T.List[str]:
-    return typeslistify(item, str)
-
-def expand_arguments(args):
-    expended_args = []
-    for arg in args:
-        if not arg.startswith('@'):
-            expended_args.append(arg)
-            continue
-
-        args_file = arg[1:]
-        try:
-            with open(args_file) as f:
-                extended_args = f.read().split()
-            expended_args += extended_args
-        except Exception as e:
-            print('Error expanding command line arguments, %s not found' % args_file)
-            print(e)
-            return None
-    return expended_args
-
-def partition(pred, iterable):
-    'Use a predicate to partition entries into false entries and true entries'
-    # partition(is_odd, range(10)) --> 0 2 4 6 8   and  1 3 5 7 9
-    t1, t2 = tee(iterable)
-    return filterfalse(pred, t1), filter(pred, t2)
-
-def Popen_safe(args: T.List[str], write: T.Optional[str] = None,
-               stdout: T.Union[T.BinaryIO, int] = subprocess.PIPE,
-               stderr: T.Union[T.BinaryIO, int] = subprocess.PIPE,
-               **kwargs: T.Any) -> T.Tuple[subprocess.Popen, str, str]:
-    import locale
-    encoding = locale.getpreferredencoding()
-    # Redirect stdin to DEVNULL otherwise the command run by us here might mess
-    # up the console and ANSI colors will stop working on Windows.
-    if 'stdin' not in kwargs:
-        kwargs['stdin'] = subprocess.DEVNULL
-    if sys.version_info < (3, 6) or not sys.stdout.encoding or encoding.upper() != 'UTF-8':
-        p, o, e = Popen_safe_legacy(args, write=write, stdout=stdout, stderr=stderr, **kwargs)
-    else:
-        p = subprocess.Popen(args, universal_newlines=True, close_fds=False,
-                             stdout=stdout, stderr=stderr, **kwargs)
-        o, e = p.communicate(write)
-    # Sometimes the command that we run will call another command which will be
-    # without the above stdin workaround, so set the console mode again just in
-    # case.
-    mlog.setup_console()
-    return p, o, e
-
-def Popen_safe_legacy(args: T.List[str], write: T.Optional[str] = None,
-                      stdout: T.Union[T.BinaryIO, int] = subprocess.PIPE,
-                      stderr: T.Union[T.BinaryIO, int] = subprocess.PIPE,
-                      **kwargs: T.Any) -> T.Tuple[subprocess.Popen, str, str]:
-    p = subprocess.Popen(args, universal_newlines=False, close_fds=False,
-                         stdout=stdout, stderr=stderr, **kwargs)
-    input_ = None  # type: T.Optional[bytes]
-    if write is not None:
-        input_ = write.encode('utf-8')
-    o, e = p.communicate(input_)
-    if o is not None:
-        if sys.stdout.encoding:
-            o = o.decode(encoding=sys.stdout.encoding, errors='replace').replace('\r\n', '\n')
-        else:
-            o = o.decode(errors='replace').replace('\r\n', '\n')
-    if e is not None:
-        if sys.stderr.encoding:
-            e = e.decode(encoding=sys.stderr.encoding, errors='replace').replace('\r\n', '\n')
-        else:
-            e = e.decode(errors='replace').replace('\r\n', '\n')
-    return p, o, e
-
-def iter_regexin_iter(regexiter, initer):
-    '''
-    Takes each regular expression in @regexiter and tries to search for it in
-    every item in @initer. If there is a match, returns that match.
-    Else returns False.
-    '''
-    for regex in regexiter:
-        for ii in initer:
-            if not isinstance(ii, str):
-                continue
-            match = re.search(regex, ii)
-            if match:
-                return match.group()
-    return False
-
-def _substitute_values_check_errors(command, values):
-    # Error checking
-    inregex = ('@INPUT([0-9]+)?@', '@PLAINNAME@', '@BASENAME@')
-    outregex = ('@OUTPUT([0-9]+)?@', '@OUTDIR@')
-    if '@INPUT@' not in values:
-        # Error out if any input-derived templates are present in the command
-        match = iter_regexin_iter(inregex, command)
-        if match:
-            m = 'Command cannot have {!r}, since no input files were specified'
-            raise MesonException(m.format(match))
-    else:
-        if len(values['@INPUT@']) > 1:
-            # Error out if @PLAINNAME@ or @BASENAME@ is present in the command
-            match = iter_regexin_iter(inregex[1:], command)
-            if match:
-                raise MesonException('Command cannot have {!r} when there is '
-                                     'more than one input file'.format(match))
-        # Error out if an invalid @INPUTnn@ template was specified
-        for each in command:
-            if not isinstance(each, str):
-                continue
-            match = re.search(inregex[0], each)
-            if match and match.group() not in values:
-                m = 'Command cannot have {!r} since there are only {!r} inputs'
-                raise MesonException(m.format(match.group(), len(values['@INPUT@'])))
-    if '@OUTPUT@' not in values:
-        # Error out if any output-derived templates are present in the command
-        match = iter_regexin_iter(outregex, command)
-        if match:
-            m = 'Command cannot have {!r} since there are no outputs'
-            raise MesonException(m.format(match))
-    else:
-        # Error out if an invalid @OUTPUTnn@ template was specified
-        for each in command:
-            if not isinstance(each, str):
-                continue
-            match = re.search(outregex[0], each)
-            if match and match.group() not in values:
-                m = 'Command cannot have {!r} since there are only {!r} outputs'
-                raise MesonException(m.format(match.group(), len(values['@OUTPUT@'])))
-
-def substitute_values(command, values):
-    '''
-    Substitute the template strings in the @values dict into the list of
-    strings @command and return a new list. For a full list of the templates,
-    see get_filenames_templates_dict()
-
-    If multiple inputs/outputs are given in the @values dictionary, we
-    substitute @INPUT@ and @OUTPUT@ only if they are the entire string, not
-    just a part of it, and in that case we substitute *all* of them.
-    '''
-    # Error checking
-    _substitute_values_check_errors(command, values)
-    # Substitution
-    outcmd = []
-    rx_keys = [re.escape(key) for key in values if key not in ('@INPUT@', '@OUTPUT@')]
-    value_rx = re.compile('|'.join(rx_keys)) if rx_keys else None
-    for vv in command:
-        if not isinstance(vv, str):
-            outcmd.append(vv)
-        elif '@INPUT@' in vv:
-            inputs = values['@INPUT@']
-            if vv == '@INPUT@':
-                outcmd += inputs
-            elif len(inputs) == 1:
-                outcmd.append(vv.replace('@INPUT@', inputs[0]))
-            else:
-                raise MesonException("Command has '@INPUT@' as part of a "
-                                     "string and more than one input file")
-        elif '@OUTPUT@' in vv:
-            outputs = values['@OUTPUT@']
-            if vv == '@OUTPUT@':
-                outcmd += outputs
-            elif len(outputs) == 1:
-                outcmd.append(vv.replace('@OUTPUT@', outputs[0]))
-            else:
-                raise MesonException("Command has '@OUTPUT@' as part of a "
-                                     "string and more than one output file")
-        # Append values that are exactly a template string.
-        # This is faster than a string replace.
-        elif vv in values:
-            outcmd.append(values[vv])
-        # Substitute everything else with replacement
-        elif value_rx:
-            outcmd.append(value_rx.sub(lambda m: values[m.group(0)], vv))
-        else:
-            outcmd.append(vv)
-    return outcmd
-
-def get_filenames_templates_dict(inputs, outputs):
-    '''
-    Create a dictionary with template strings as keys and values as values for
-    the following templates:
-
-    @INPUT@  - the full path to one or more input files, from @inputs
-    @OUTPUT@ - the full path to one or more output files, from @outputs
-    @OUTDIR@ - the full path to the directory containing the output files
-
-    If there is only one input file, the following keys are also created:
-
-    @PLAINNAME@ - the filename of the input file
-    @BASENAME@ - the filename of the input file with the extension removed
-
-    If there is more than one input file, the following keys are also created:
-
-    @INPUT0@, @INPUT1@, ... one for each input file
-
-    If there is more than one output file, the following keys are also created:
-
-    @OUTPUT0@, @OUTPUT1@, ... one for each output file
-    '''
-    values = {}
-    # Gather values derived from the input
-    if inputs:
-        # We want to substitute all the inputs.
-        values['@INPUT@'] = inputs
-        for (ii, vv) in enumerate(inputs):
-            # Write out @INPUT0@, @INPUT1@, ...
-            values['@INPUT{}@'.format(ii)] = vv
-        if len(inputs) == 1:
-            # Just one value, substitute @PLAINNAME@ and @BASENAME@
-            values['@PLAINNAME@'] = plain = os.path.basename(inputs[0])
-            values['@BASENAME@'] = os.path.splitext(plain)[0]
-    if outputs:
-        # Gather values derived from the outputs, similar to above.
-        values['@OUTPUT@'] = outputs
-        for (ii, vv) in enumerate(outputs):
-            values['@OUTPUT{}@'.format(ii)] = vv
-        # Outdir should be the same for all outputs
-        values['@OUTDIR@'] = os.path.dirname(outputs[0])
-        # Many external programs fail on empty arguments.
-        if values['@OUTDIR@'] == '':
-            values['@OUTDIR@'] = '.'
-    return values
-
-
-def _make_tree_writable(topdir):
-    # Ensure all files and directories under topdir are writable
-    # (and readable) by owner.
-    for d, _, files in os.walk(topdir):
-        os.chmod(d, os.stat(d).st_mode | stat.S_IWRITE | stat.S_IREAD)
-        for fname in files:
-            fpath = os.path.join(d, fname)
-            if os.path.isfile(fpath):
-                os.chmod(fpath, os.stat(fpath).st_mode | stat.S_IWRITE | stat.S_IREAD)
-
-
-def windows_proof_rmtree(f):
-    # On Windows if anyone is holding a file open you can't
-    # delete it. As an example an anti virus scanner might
-    # be scanning files you are trying to delete. The only
-    # way to fix this is to try again and again.
-    delays = [0.1, 0.1, 0.2, 0.2, 0.2, 0.5, 0.5, 1, 1, 1, 1, 2]
-    # Start by making the tree wriable.
-    _make_tree_writable(f)
-    for d in delays:
-        try:
-            shutil.rmtree(f)
-            return
-        except FileNotFoundError:
-            return
-        except OSError:
-            time.sleep(d)
-    # Try one last time and throw if it fails.
-    shutil.rmtree(f)
-
-
-def windows_proof_rm(fpath):
-    """Like windows_proof_rmtree, but for a single file."""
-    if os.path.isfile(fpath):
-        os.chmod(fpath, os.stat(fpath).st_mode | stat.S_IWRITE | stat.S_IREAD)
-    delays = [0.1, 0.1, 0.2, 0.2, 0.2, 0.5, 0.5, 1, 1, 1, 1, 2]
-    for d in delays:
-        try:
-            os.unlink(fpath)
-            return
-        except FileNotFoundError:
-            return
-        except OSError:
-            time.sleep(d)
-    os.unlink(fpath)
-
-
-def detect_subprojects(spdir_name, current_dir='', result=None):
-    if result is None:
-        result = {}
-    spdir = os.path.join(current_dir, spdir_name)
-    if not os.path.exists(spdir):
-        return result
-    for trial in glob(os.path.join(spdir, '*')):
-        basename = os.path.basename(trial)
-        if trial == 'packagecache':
-            continue
-        append_this = True
-        if os.path.isdir(trial):
-            detect_subprojects(spdir_name, trial, result)
-        elif trial.endswith('.wrap') and os.path.isfile(trial):
-            basename = os.path.splitext(basename)[0]
-        else:
-            append_this = False
-        if append_this:
-            if basename in result:
-                result[basename].append(trial)
-            else:
-                result[basename] = [trial]
-    return result
-
-# This isn't strictly correct. What we really want here is something like:
-# class StringProtocol(typing_extensions.Protocol):
-#
-#      def __str__(self) -> str: ...
-#
-# This would more accurately embody what this funcitonc an handle, but we
-# don't have that yet, so instead we'll do some casting to work around it
-def get_error_location_string(fname: str, lineno: str) -> str:
-    return '{}:{}:'.format(fname, lineno)
-
-def substring_is_in_list(substr: str, strlist: T.List[str]) -> bool:
-    for s in strlist:
-        if substr in s:
-            return True
-    return False
-
-class OrderedSet(collections.abc.MutableSet):
-    """A set that preserves the order in which items are added, by first
-    insertion.
-    """
-    def __init__(self, iterable=None):
-        self.__container = collections.OrderedDict()
-        if iterable:
-            self.update(iterable)
-
-    def __contains__(self, value):
-        return value in self.__container
-
-    def __iter__(self):
-        return iter(self.__container.keys())
-
-    def __len__(self):
-        return len(self.__container)
-
-    def __repr__(self):
-        # Don't print 'OrderedSet("")' for an empty set.
-        if self.__container:
-            return 'OrderedSet("{}")'.format(
-                '", "'.join(repr(e) for e in self.__container.keys()))
-        return 'OrderedSet()'
-
-    def __reversed__(self):
-        return reversed(self.__container)
-
-    def add(self, value):
-        self.__container[value] = None
-
-    def discard(self, value):
-        if value in self.__container:
-            del self.__container[value]
-
-    def update(self, iterable):
-        for item in iterable:
-            self.__container[item] = None
-
-    def difference(self, set_):
-        return type(self)(e for e in self if e not in set_)
-
-class BuildDirLock:
-
-    def __init__(self, builddir):
-        self.lockfilename = os.path.join(builddir, 'meson-private/meson.lock')
-
-    def __enter__(self):
-        self.lockfile = open(self.lockfilename, 'w')
-        try:
-            if have_fcntl:
-                fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
-            elif have_msvcrt:
-                msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1)
-        except (BlockingIOError, PermissionError):
-            self.lockfile.close()
-            raise MesonException('Some other Meson process is already using this build directory. Exiting.')
-
-    def __exit__(self, *args):
-        if have_fcntl:
-            fcntl.flock(self.lockfile, fcntl.LOCK_UN)
-        elif have_msvcrt:
-            msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1)
-        self.lockfile.close()
-
-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
-    # original absolute path.
-    try:
-        return os.path.relpath(path, start)
-    except (TypeError, ValueError):
-        return path
-
-
-class LibType(Enum):
-
-    """Enumeration for library types."""
-
-    SHARED = 0
-    STATIC = 1
-    PREFER_SHARED = 2
-    PREFER_STATIC = 3
-
-
-class ProgressBarFallback:  # lgtm [py/iter-returns-non-self]
-    '''
-    Fallback progress bar implementation when tqdm is not found
-
-    Since this class is not an actual iterator, but only provides a minimal
-    fallback, it is safe to ignore the 'Iterator does not return self from
-    __iter__ method' warning.
-    '''
-    def __init__(self, iterable=None, total=None, bar_type=None, desc=None):
-        if iterable is not None:
-            self.iterable = iter(iterable)
-            return
-        self.total = total
-        self.done = 0
-        self.printed_dots = 0
-        if self.total and bar_type == 'download':
-            print('Download size:', self.total)
-        if desc:
-            print('{}: '.format(desc), end='')
-
-    # Pretend to be an iterator when called as one and don't print any
-    # progress
-    def __iter__(self):
-        return self.iterable
-
-    def __next__(self):
-        return next(self.iterable)
-
-    def print_dot(self):
-        print('.', end='')
-        sys.stdout.flush()
-        self.printed_dots += 1
-
-    def update(self, progress):
-        self.done += progress
-        if not self.total:
-            # Just print one dot per call if we don't have a total length
-            self.print_dot()
-            return
-        ratio = int(self.done / self.total * 10)
-        while self.printed_dots < ratio:
-            self.print_dot()
-
-    def close(self):
-        print('')
-
-try:
-    from tqdm import tqdm
-
-    class ProgressBar(tqdm):
-        def __init__(self, *args, bar_type=None, **kwargs):
-            if bar_type == 'download':
-                kwargs.update({'unit': 'bytes', 'leave': True})
-            else:
-                kwargs.update({'leave': False})
-            kwargs['ncols'] = 100
-            super().__init__(*args, **kwargs)
-except ImportError:
-    ProgressBar = ProgressBarFallback
-
-
-def get_wine_shortpath(winecmd, wine_paths):
-
-    """ Get A short version of @wine_paths to avoid
-    reaching WINEPATH number of char limit.
-    """
-
-    seen = set()
-    wine_paths = [p for p in wine_paths if not (p in seen or seen.add(p))]
-
-    getShortPathScript = '%s.bat' % str(uuid.uuid4()).lower()[:5]
-    with open(getShortPathScript, mode='w') as f:
-        f.write("@ECHO OFF\nfor %%x in (%*) do (\n echo|set /p=;%~sx\n)\n")
-        f.flush()
-    try:
-        with open(os.devnull, 'w') as stderr:
-            wine_path = subprocess.check_output(
-                winecmd +
-                ['cmd', '/C', getShortPathScript] + wine_paths,
-                stderr=stderr).decode('utf-8')
-    except subprocess.CalledProcessError as e:
-        print("Could not get short paths: %s" % e)
-        wine_path = ';'.join(wine_paths)
-    finally:
-        os.remove(getShortPathScript)
-    if len(wine_path) > 2048:
-        raise MesonException(
-            'WINEPATH size {} > 2048'
-            ' this will cause random failure.'.format(
-                len(wine_path)))
-
-    return wine_path.strip(';')
-
-def run_once(func):
-    ret = []
-
-    def wrapper(*args, **kwargs):
-        if ret:
-            return ret[0]
-
-        val = func(*args, **kwargs)
-        ret.append(val)
-        return val
-
-    return update_wrapper(wrapper, func)
-
-
-class OptionProxy:
-    def __init__(self, value):
-        self.value = value
-
-class OptionOverrideProxy:
-    '''Mimic an option list but transparently override
-    selected option values.'''
-    def __init__(self, overrides, *options):
-        self.overrides = overrides
-        self.options = options
-
-    def __getitem__(self, option_name):
-        for opts in self.options:
-            if option_name in opts:
-                return self._get_override(option_name, opts[option_name])
-        raise KeyError('Option not found', option_name)
-
-    def _get_override(self, option_name, base_opt):
-        if option_name in self.overrides:
-            return OptionProxy(base_opt.validate_value(self.overrides[option_name]))
-        return base_opt
-
-    def copy(self):
-        result = {}
-        for opts in self.options:
-            for option_name in opts:
-                result[option_name] = self._get_override(option_name, opts[option_name])
-        return result
diff -Nru meson-0.53.2/mesonbuild/mesonmain.py meson-0.61.2/mesonbuild/mesonmain.py
--- meson-0.53.2/mesonbuild/mesonmain.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/mesonmain.py	2022-02-14 19:03:13.000000000 +0000
@@ -1,4 +1,4 @@
-# Copyright 2012-2016 The Meson development team
+# Copyright 2012-2021 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.
@@ -12,7 +12,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Work around some pathlib bugs...
+from . import _pathlib
 import sys
+sys.modules['pathlib'] = _pathlib
+
 import os.path
 import importlib
 import traceback
@@ -22,8 +26,8 @@
 
 from . import mesonlib
 from . import mlog
-from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata
-from .mesonlib import MesonException
+from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile, mdevenv
+from .mesonlib import MesonException, MesonBugException
 from .environment import detect_msys2_arch
 from .wrap import wraptool
 
@@ -38,7 +42,7 @@
         self.commands = {}
         self.hidden_commands = []
         self.parser = argparse.ArgumentParser(prog='meson', formatter_class=self.formatter)
-        self.subparsers = self.parser.add_subparsers(title='Commands',
+        self.subparsers = self.parser.add_subparsers(title='Commands', dest='command',
                                                      description='If no command is specified it defaults to setup command.')
         self.add_command('setup', msetup.add_arguments, msetup.run,
                          help_msg='Configure the project')
@@ -62,6 +66,10 @@
                          help_msg='Print help of a subcommand')
         self.add_command('rewrite', lambda parser: rewriter.add_arguments(parser, self.formatter), rewriter.run,
                          help_msg='Modify the project definition')
+        self.add_command('compile', mcompile.add_arguments, mcompile.run,
+                         help_msg='Build the project')
+        self.add_command('devenv', mdevenv.add_arguments, mdevenv.run,
+                         help_msg='Run commands in developer environment')
 
         # Hidden commands
         self.add_command('runpython', self.add_runpython_arguments, self.run_runpython_command,
@@ -109,6 +117,7 @@
         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']
@@ -117,14 +126,22 @@
 
         # Hidden commands have their own parser instead of using the global one
         if args[0] in self.hidden_commands:
-            parser = self.commands[args[0]]
+            command = args[0]
+            parser = self.commands[command]
             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
+
+        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:
@@ -135,12 +152,26 @@
             if os.environ.get('MESON_FORCE_BACKTRACE'):
                 raise
             return 1
-        except Exception:
+        except PermissionError:
+            if os.environ.get('MESON_FORCE_BACKTRACE'):
+                raise
+            traceback.print_exc()
+            return 2
+        except Exception as e:
             if os.environ.get('MESON_FORCE_BACKTRACE'):
                 raise
             traceback.print_exc()
+            msg = 'Unhandled python exception'
+            if all(getattr(e, a, None) is not None for a in ['file', 'lineno', 'colno']):
+                e = MesonBugException(msg, e.file, e.lineno, e.colno) # type: ignore
+            else:
+                e = MesonBugException(msg)
+            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):
@@ -162,7 +193,7 @@
     try:
         return module.run(script_args)
     except MesonException as e:
-        mlog.error('Error in {} helper script:'.format(script_name))
+        mlog.error(f'Error in {script_name} helper script:')
         mlog.exception(e)
         return 1
 
@@ -178,9 +209,9 @@
                 sys.stdout.buffer = sys.stdout.raw if hasattr(sys.stdout, 'raw') else sys.stdout
 
 def run(original_args, mainfile):
-    if sys.version_info < (3, 5):
-        print('Meson works correctly only with python 3.5+.')
-        print('You have python %s.' % sys.version)
+    if sys.version_info < (3, 6):
+        print('Meson works correctly only with python 3.6+.')
+        print(f'You have python {sys.version}.')
         print('Please update your environment')
         return 1
 
@@ -219,7 +250,7 @@
 def main():
     # Always resolve the command path so Ninja can find it for regen, tests, etc.
     if 'meson.exe' in sys.executable:
-        assert(os.path.isabs(sys.executable))
+        assert os.path.isabs(sys.executable)
         launcher = sys.executable
     else:
         launcher = os.path.realpath(sys.argv[0])
diff -Nru meson-0.53.2/mesonbuild/minit.py meson-0.61.2/mesonbuild/minit.py
--- meson-0.53.2/mesonbuild/minit.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/minit.py	2021-12-26 16:24:25.000000000 +0000
@@ -15,93 +15,79 @@
 """Code that creates simple startup projects."""
 
 from pathlib import Path
-import re, shutil, subprocess
+from enum import Enum
+import subprocess
+import shutil
+import sys
+import os
+import re
 from glob import glob
 from mesonbuild import mesonlib
 from mesonbuild.environment import detect_ninja
+from mesonbuild.templates.samplefactory import sameple_generator
+import typing as T
 
-from mesonbuild.templates.ctemplates import (create_exe_c_sample, create_lib_c_sample)
-from mesonbuild.templates.cpptemplates import (create_exe_cpp_sample, create_lib_cpp_sample)
-from mesonbuild.templates.objctemplates import (create_exe_objc_sample, create_lib_objc_sample)
-from mesonbuild.templates.dlangtemplates import (create_exe_d_sample, create_lib_d_sample)
-from mesonbuild.templates.fortrantemplates import (create_exe_fortran_sample, create_lib_fortran_sample)
-from mesonbuild.templates.rusttemplates import (create_exe_rust_sample, create_lib_rust_sample)
+if T.TYPE_CHECKING:
+    import argparse
 
-FORTRAN_SUFFIXES = ['.f', '.for', '.F', '.f90', '.F90']
+'''
+we currently have one meson template at this time.
+'''
+from mesonbuild.templates.mesontemplates import create_meson_build
 
-info_message = '''Sample project created. To build it run the
+FORTRAN_SUFFIXES = {'.f', '.for', '.F', '.f90', '.F90'}
+LANG_SUFFIXES = {'.c', '.cc', '.cpp', '.cs', '.cu', '.d', '.m', '.mm', '.rs', '.java', '.vala'} | FORTRAN_SUFFIXES
+LANG_SUPPORTED = {'c', 'cpp', 'cs', 'cuda', 'd', 'fortran', 'java', 'rust', 'objc', 'objcpp', 'vala'}
+
+DEFAULT_PROJECT = 'executable'
+DEFAULT_VERSION = '0.1'
+class DEFAULT_TYPES(Enum):
+    EXE = 'executable'
+    LIB = 'library'
+
+INFO_MESSAGE = '''Sample project created. To build it run the
 following commands:
 
-meson builddir
-ninja -C builddir
+meson setup builddir
+meson compile -C builddir
 '''
 
-def create_sample(options):
-    if options.language == 'c':
-        if options.type == 'executable':
-            create_exe_c_sample(options.name, options.version)
-        elif options.type == 'library':
-            create_lib_c_sample(options.name, options.version)
-        else:
-            raise RuntimeError('Unreachable code')
-    elif options.language == 'cpp':
-        if options.type == 'executable':
-            create_exe_cpp_sample(options.name, options.version)
-        elif options.type == 'library':
-            create_lib_cpp_sample(options.name, options.version)
-        else:
-            raise RuntimeError('Unreachable code')
-    elif options.language == 'd':
-        if options.type == 'executable':
-            create_exe_d_sample(options.name, options.version)
-        elif options.type == 'library':
-            create_lib_d_sample(options.name, options.version)
-        else:
-            raise RuntimeError('Unreachable code')
-    elif options.language == 'fortran':
-        if options.type == 'executable':
-            create_exe_fortran_sample(options.name, options.version)
-        elif options.type == 'library':
-            create_lib_fortran_sample(options.name, options.version)
-        else:
-            raise RuntimeError('Unreachable code')
-    elif options.language == 'rust':
-        if options.type == 'executable':
-            create_exe_rust_sample(options.name, options.version)
-        elif options.type == 'library':
-            create_lib_rust_sample(options.name, options.version)
-        else:
-            raise RuntimeError('Unreachable code')
-    elif options.language == 'objc':
-        if options.type == 'executable':
-            create_exe_objc_sample(options.name, options.version)
-        elif options.type == 'library':
-            create_lib_objc_sample(options.name, options.version)
-        else:
-            raise RuntimeError('Unreachable code')
+
+def create_sample(options: 'argparse.Namespace') -> None:
+    '''
+    Based on what arguments are passed we check for a match in language
+    then check for project type and create new Meson samples project.
+    '''
+    sample_gen = sameple_generator(options)
+    if options.type == DEFAULT_TYPES['EXE'].value:
+        sample_gen.create_executable()
+    elif options.type == DEFAULT_TYPES['LIB'].value:
+        sample_gen.create_library()
     else:
         raise RuntimeError('Unreachable code')
-    print(info_message)
+    print(INFO_MESSAGE)
 
-def autodetect_options(options, sample: bool = False):
+def autodetect_options(options: 'argparse.Namespace', sample: bool = False) -> None:
+    '''
+    Here we autodetect options for args not passed in so don't have to
+    think about it.
+    '''
     if not options.name:
         options.name = Path().resolve().stem
         if not re.match('[a-zA-Z_][a-zA-Z0-9]*', options.name) and sample:
-            raise SystemExit('Name of current directory "{}" is not usable as a sample project name.\n'
-                             'Specify a project name with --name.'.format(options.name))
-        print('Using "{}" (name of current directory) as project name.'
-              .format(options.name))
+            raise SystemExit(f'Name of current directory "{options.name}" is not usable as a sample project name.\n'
+                             'Specify a project name with --name.')
+        print(f'Using "{options.name}" (name of current directory) as project name.')
     if not options.executable:
         options.executable = options.name
-        print('Using "{}" (project name) as name of executable to build.'
-              .format(options.executable))
+        print(f'Using "{options.executable}" (project name) as name of executable to build.')
     if sample:
         # The rest of the autodetection is not applicable to generating sample projects.
         return
     if not options.srcfiles:
         srcfiles = []
         for f in (f for f in Path().iterdir() if f.is_file()):
-            if f.suffix in (['.cc', '.cpp', '.c', '.d', '.m', '.rs'] + FORTRAN_SUFFIXES):
+            if f.suffix in LANG_SUFFIXES:
                 srcfiles.append(f)
         if not srcfiles:
             raise SystemExit('No recognizable source files found.\n'
@@ -111,11 +97,17 @@
     options.srcfiles = [Path(f) for f in options.srcfiles]
     if not options.language:
         for f in options.srcfiles:
+            if f.suffix == '.c':
+                options.language = 'c'
+                break
             if f.suffix in ('.cc', '.cpp'):
                 options.language = 'cpp'
                 break
-            if f.suffix == '.c':
-                options.language = 'c'
+            if f.suffix == '.cs':
+                options.language = 'cs'
+                break
+            if f.suffix == '.cu':
+                options.language = 'cuda'
                 break
             if f.suffix == '.d':
                 options.language = 'd'
@@ -129,66 +121,45 @@
             if f.suffix == '.m':
                 options.language = 'objc'
                 break
+            if f.suffix == '.mm':
+                options.language = 'objcpp'
+                break
+            if f.suffix == '.java':
+                options.language = 'java'
+                break
+            if f.suffix == '.vala':
+                options.language = 'vala'
+                break
         if not options.language:
             raise SystemExit("Can't autodetect language, please specify it with -l.")
         print("Detected language: " + options.language)
 
-
-meson_executable_template = '''project('{project_name}', '{language}',
-  version : '{version}',
-  default_options : [{default_options}])
-
-executable('{executable}',
-           {sourcespec},{depspec}
-           install : true)
-'''
-
-def create_meson_build(options):
-    if options.type != 'executable':
-        raise SystemExit('\nGenerating a meson.build file from existing sources is\n'
-                         'supported only for project type "executable".\n'
-                         'Run meson init in an empty directory to create a sample project.')
-    default_options = ['warning_level=3']
-    if options.language == 'cpp':
-        # This shows how to set this very common option.
-        default_options += ['cpp_std=c++14']
-    # If we get a meson.build autoformatter one day, this code could
-    # be simplified quite a bit.
-    formatted_default_options = ', '.join("'{}'".format(x) for x in default_options)
-    sourcespec = ',\n           '.join("'{}'".format(x) for x in options.srcfiles)
-    depspec = ''
-    if options.deps:
-        depspec = '\n           dependencies : [\n              '
-        depspec += ',\n              '.join("dependency('{}')".format(x)
-                                            for x in options.deps.split(','))
-        depspec += '],'
-    content = meson_executable_template.format(project_name=options.name,
-                                               language=options.language,
-                                               version=options.version,
-                                               executable=options.executable,
-                                               sourcespec=sourcespec,
-                                               depspec=depspec,
-                                               default_options=formatted_default_options)
-    open('meson.build', 'w').write(content)
-    print('Generated meson.build file:\n\n' + content)
-
-def add_arguments(parser):
-    parser.add_argument("srcfiles", metavar="sourcefile", nargs="*",
-                        help="source files. default: all recognized files in current directory")
+def add_arguments(parser: 'argparse.ArgumentParser') -> None:
+    '''
+    Here we add args for that the user can passed when making a new
+    Meson project.
+    '''
+    parser.add_argument("srcfiles", metavar="sourcefile", nargs="*", help="source files. default: all recognized files in current directory")
+    parser.add_argument('-C', dest='wd', action=mesonlib.RealPathAction,
+                        help='directory to cd into before running')
     parser.add_argument("-n", "--name", help="project name. default: name of current directory")
     parser.add_argument("-e", "--executable", help="executable name. default: project name")
     parser.add_argument("-d", "--deps", help="dependencies, comma-separated")
-    parser.add_argument("-l", "--language", choices=['c', 'cpp', 'd', 'fortran', 'rust', 'objc'],
-                        help="project language. default: autodetected based on source files")
-    parser.add_argument("-b", "--build", help="build after generation", action='store_true')
-    parser.add_argument("--builddir", help="directory for build", default='build')
-    parser.add_argument("-f", "--force", action="store_true",
-                        help="force overwrite of existing files and directories.")
-    parser.add_argument('--type', default='executable',
-                        choices=['executable', 'library'])
-    parser.add_argument('--version', default='0.1')
+    parser.add_argument("-l", "--language", choices=sorted(LANG_SUPPORTED), help="project language. default: autodetected based on source files")
+    parser.add_argument("-b", "--build", action='store_true', help="build after generation")
+    parser.add_argument("--builddir", default='build', help="directory for build")
+    parser.add_argument("-f", "--force", action="store_true", help="force overwrite of existing files and directories.")
+    parser.add_argument('--type', default=DEFAULT_PROJECT, choices=('executable', 'library'), help=f"project type. default: {DEFAULT_PROJECT} based project")
+    parser.add_argument('--version', default=DEFAULT_VERSION, help=f"project version. default: {DEFAULT_VERSION}")
+
+def run(options: 'argparse.Namespace') -> int:
+    '''
+    Here we generate the new Meson sample project.
+    '''
+    if not Path(options.wd).exists():
+        sys.exit('Project source root directory not found. Run this command in source directory root.')
+    os.chdir(options.wd)
 
-def run(options) -> int:
     if not glob('*'):
         autodetect_options(options, sample=True)
         if not options.language:
@@ -205,11 +176,11 @@
             print('Build directory already exists, deleting it.')
             shutil.rmtree(options.builddir)
         print('Building...')
-        cmd = mesonlib.meson_command + [options.builddir]
+        cmd = mesonlib.get_meson_command() + [options.builddir]
         ret = subprocess.run(cmd)
         if ret.returncode:
             raise SystemExit
-        cmd = [detect_ninja(), '-C', options.builddir]
+        cmd = detect_ninja() + ['-C', options.builddir]
         ret = subprocess.run(cmd)
         if ret.returncode:
             raise SystemExit
diff -Nru meson-0.53.2/mesonbuild/minstall.py meson-0.61.2/mesonbuild/minstall.py
--- meson-0.53.2/mesonbuild/minstall.py	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/minstall.py	2022-02-14 19:03:13.000000000 +0000
@@ -12,13 +12,30 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import sys, pickle, os, shutil, subprocess, errno
-import shlex
 from glob import glob
-from .scripts import depfixer
-from .scripts import destdir_join
-from .mesonlib import is_windows, Popen_safe
-from .mtest import rebuild_all
+from pathlib import Path
+import argparse
+import errno
+import os
+import pickle
+import platform
+import shlex
+import shutil
+import subprocess
+import sys
+import typing as T
+
+from . import build
+from . import environment
+from .backend.backends import (
+    InstallData, InstallDataBase, InstallEmptyDir, InstallSymlinkData,
+    TargetInstallData, ExecutableSerialisation
+)
+from .coredata import major_versions_differ, MesonVersionMismatchException
+from .coredata import version as coredata_version
+from .mesonlib import MesonException, Popen_safe, RealPathAction, is_windows, setup_vsenv
+from .scripts import depfixer, destdir_join
+from .scripts.meson_exe import run_exe
 try:
     from __main__ import __file__ as main_file
 except ImportError:
@@ -26,33 +43,73 @@
     # This is only used for pkexec which is not, so this is fine.
     main_file = None
 
+if T.TYPE_CHECKING:
+    from .mesonlib import FileMode
+
+    try:
+        from typing import Protocol
+    except AttributeError:
+        from typing_extensions import Protocol  # type: ignore
+
+    class ArgumentType(Protocol):
+        """Typing information for the object returned by argparse."""
+        no_rebuild: bool
+        only_changed: bool
+        profile: bool
+        quiet: bool
+        wd: str
+        destdir: str
+        dry_run: bool
+        skip_subprojects: str
+        tags: str
+
+
 symlink_warning = '''Warning: trying to copy a symlink that points to a file. This will copy the file,
 but this will be changed in a future version of Meson to copy the symlink as is. Please update your
 build definitions so that it will not break when the change happens.'''
 
-selinux_updates = []
+selinux_updates: T.List[str] = []
 
-def add_arguments(parser):
-    parser.add_argument('-C', default='.', dest='wd',
+def add_arguments(parser: argparse.ArgumentParser) -> None:
+    parser.add_argument('-C', dest='wd', action=RealPathAction,
                         help='directory to cd into before running')
+    parser.add_argument('--profile-self', action='store_true', dest='profile',
+                        help=argparse.SUPPRESS)
     parser.add_argument('--no-rebuild', default=False, action='store_true',
                         help='Do not rebuild before installing.')
     parser.add_argument('--only-changed', default=False, action='store_true',
                         help='Only overwrite files that are older than the copied file.')
+    parser.add_argument('--quiet', default=False, action='store_true',
+                        help='Do not print every file that was installed.')
+    parser.add_argument('--destdir', default=None,
+                        help='Sets or overrides DESTDIR environment. (Since 0.57.0)')
+    parser.add_argument('--dry-run', '-n', action='store_true',
+                        help='Doesn\'t actually install, but print logs. (Since 0.57.0)')
+    parser.add_argument('--skip-subprojects', nargs='?', const='*', default='',
+                        help='Do not install files from given subprojects. (Since 0.58.0)')
+    parser.add_argument('--tags', default=None,
+                        help='Install only targets having one of the given tags. (Since 0.60.0)')
 
 class DirMaker:
-    def __init__(self, lf):
+    def __init__(self, lf: T.TextIO, makedirs: T.Callable[..., None]):
         self.lf = lf
-        self.dirs = []
+        self.dirs: T.List[str] = []
+        self.all_dirs: T.Set[str] = set()
+        self.makedirs_impl = makedirs
 
-    def makedirs(self, path, exist_ok=False):
+    def makedirs(self, path: str, exist_ok: bool = False) -> None:
         dirname = os.path.normpath(path)
+        self.all_dirs.add(dirname)
         dirs = []
         while dirname != os.path.dirname(dirname):
+            if dirname in self.dirs:
+                # In dry-run mode the directory does not exist but we would have
+                # created it with all its parents otherwise.
+                break
             if not os.path.exists(dirname):
                 dirs.append(dirname)
             dirname = os.path.dirname(dirname)
-        os.makedirs(path, exist_ok=exist_ok)
+        self.makedirs_impl(path, exist_ok=exist_ok)
 
         # store the directories in creation order, with the parent directory
         # before the child directories. Future calls of makedir() will not
@@ -62,25 +119,30 @@
         dirs.reverse()
         self.dirs += dirs
 
-    def __enter__(self):
+    def __enter__(self) -> 'DirMaker':
         return self
 
-    def __exit__(self, exception_type, value, traceback):
+    def __exit__(self, exception_type: T.Type[Exception], value: T.Any, traceback: T.Any) -> None:
         self.dirs.reverse()
         for d in self.dirs:
             append_to_log(self.lf, d)
 
-def is_executable(path, follow_symlinks=False):
+
+def is_executable(path: str, follow_symlinks: bool = False) -> bool:
     '''Checks whether any of the "x" bits are set in the source file mode.'''
     return bool(os.stat(path, follow_symlinks=follow_symlinks).st_mode & 0o111)
 
-def append_to_log(lf, line):
+
+def append_to_log(lf: T.TextIO, line: str) -> None:
     lf.write(line)
     if not line.endswith('\n'):
         lf.write('\n')
     lf.flush()
 
-def set_chown(path, user=None, group=None, dir_fd=None, follow_symlinks=True):
+
+def set_chown(path: str, user: T.Union[str, int, None] = None,
+              group: T.Union[str, int, None] = None,
+              dir_fd: T.Optional[int] = None, follow_symlinks: bool = True) -> None:
     # shutil.chown will call os.chown without passing all the parameters
     # and particularly follow_symlinks, thus we replace it temporary
     # with a lambda with all the parameters so that follow_symlinks will
@@ -88,53 +150,63 @@
     # Not nice, but better than actually rewriting shutil.chown until
     # this python bug is fixed: https://bugs.python.org/issue18108
     real_os_chown = os.chown
+
+    def chown(path: T.Union[int, str, 'os.PathLike[str]', bytes, 'os.PathLike[bytes]'],
+              uid: int, gid: int, *, dir_fd: T.Optional[int] = dir_fd,
+              follow_symlinks: bool = follow_symlinks) -> None:
+        """Override the default behavior of os.chown
+
+        Use a real function rather than a lambda to help mypy out. Also real
+        functions are faster.
+        """
+        real_os_chown(path, uid, gid, dir_fd=dir_fd, follow_symlinks=follow_symlinks)
+
     try:
-        os.chown = lambda p, u, g: real_os_chown(p, u, g,
-                                                 dir_fd=dir_fd,
-                                                 follow_symlinks=follow_symlinks)
+        os.chown = chown
         shutil.chown(path, user, group)
-    except Exception:
-        raise
     finally:
         os.chown = real_os_chown
 
-def set_chmod(path, mode, dir_fd=None, follow_symlinks=True):
+
+def set_chmod(path: str, mode: int, dir_fd: T.Optional[int] = None,
+              follow_symlinks: bool = True) -> None:
     try:
         os.chmod(path, mode, dir_fd=dir_fd, follow_symlinks=follow_symlinks)
     except (NotImplementedError, OSError, SystemError):
         if not os.path.islink(path):
             os.chmod(path, mode, dir_fd=dir_fd)
 
-def sanitize_permissions(path, umask):
+
+def sanitize_permissions(path: str, umask: T.Union[str, int]) -> None:
+    # TODO: with python 3.8 or typing_extensions we could replace this with
+    # `umask: T.Union[T.Literal['preserve'], int]`, which would be more correct
     if umask == 'preserve':
         return
+    assert isinstance(umask, int), 'umask should only be "preserver" or an integer'
     new_perms = 0o777 if is_executable(path, follow_symlinks=False) else 0o666
     new_perms &= ~umask
     try:
         set_chmod(path, new_perms, follow_symlinks=False)
     except PermissionError as e:
-        msg = '{!r}: Unable to set permissions {!r}: {}, ignoring...'
-        print(msg.format(path, new_perms, e.strerror))
+        print(f'{path!r}: Unable to set permissions {new_perms!r}: {e.strerror}, ignoring...')
+
 
-def set_mode(path, mode, default_umask):
-    if mode is None or (mode.perms_s or mode.owner or mode.group) is None:
+def set_mode(path: str, mode: T.Optional['FileMode'], default_umask: T.Union[str, int]) -> None:
+    if mode is None or all(m is None for m in [mode.perms_s, mode.owner, mode.group]):
         # Just sanitize permissions with the default umask
         sanitize_permissions(path, default_umask)
         return
     # No chown() on Windows, and must set one of owner/group
-    if not is_windows() and (mode.owner or mode.group) is not None:
+    if not is_windows() and (mode.owner is not None or mode.group is not None):
         try:
             set_chown(path, mode.owner, mode.group, follow_symlinks=False)
         except PermissionError as e:
-            msg = '{!r}: Unable to set owner {!r} and group {!r}: {}, ignoring...'
-            print(msg.format(path, mode.owner, mode.group, e.strerror))
+            print(f'{path!r}: Unable to set owner {mode.owner!r} and group {mode.group!r}: {e.strerror}, ignoring...')
         except LookupError:
-            msg = '{!r}: Non-existent owner {!r} or group {!r}: ignoring...'
-            print(msg.format(path, mode.owner, mode.group))
+            print(f'{path!r}: Non-existent owner {mode.owner!r} or group {mode.group!r}: ignoring...')
         except OSError as e:
             if e.errno == errno.EINVAL:
-                msg = '{!r}: Non-existent numeric owner {!r} or group {!r}: ignoring...'
-                print(msg.format(path, mode.owner, mode.group))
+                print(f'{path!r}: Non-existent numeric owner {mode.owner!r} or group {mode.group!r}: ignoring...')
             else:
                 raise
     # Must set permissions *after* setting owner/group otherwise the
@@ -144,12 +216,12 @@
         try:
             set_chmod(path, mode.perms, follow_symlinks=False)
         except PermissionError as e:
-            msg = '{!r}: Unable to set permissions {!r}: {}, ignoring...'
-            print(msg.format(path, mode.perms_s, e.strerror))
+            print('{path!r}: Unable to set permissions {mode.perms_s!r}: {e.strerror}, ignoring...')
     else:
         sanitize_permissions(path, default_umask)
 
-def restore_selinux_contexts():
+
+def restore_selinux_contexts() -> None:
     '''
     Restores the SELinux context for files in @selinux_updates
 
@@ -166,24 +238,60 @@
         # If we don't have restorecon, failure is ignored quietly.
         return
 
-    with subprocess.Popen(['restorecon', '-F', '-f-', '-0'],
-                          stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc:
-        out, err = proc.communicate(input=b'\0'.join(os.fsencode(f) for f in selinux_updates) + b'\0')
-        if proc.returncode != 0 and not os.environ.get('DESTDIR'):
-            print('Failed to restore SELinux context of installed files...',
-                  'Standard output:', out.decode(),
-                  'Standard error:', err.decode(), sep='\n')
+    if not selinux_updates:
+        # If the list of files is empty, do not try to call restorecon.
+        return
+
+    proc, out, err = Popen_safe(['restorecon', '-F', '-f-', '-0'], ('\0'.join(f for f in selinux_updates) + '\0'))
+    if proc.returncode != 0:
+        print('Failed to restore SELinux context of installed files...',
+              'Standard output:', out,
+              'Standard error:', err, sep='\n')
+
+def apply_ldconfig(dm: DirMaker, libdir: str) -> None:
+    '''
+    Apply ldconfig to update the ld.so.cache.
+    '''
+    if not shutil.which('ldconfig'):
+        # If we don't have ldconfig, failure is ignored quietly.
+        return
+
+    platlower = platform.system().lower()
+    if platlower == 'dragonfly' or 'bsd' in platlower:
+        if libdir in dm.all_dirs:
+            proc, out, err = Popen_safe(['ldconfig', '-m', libdir])
+            if proc.returncode != 0:
+                print('Failed to apply ldconfig ...',
+                      'Standard output:', out,
+                      'Standard error:', err, sep='\n')
+        return
+
+    # Try to update ld cache, it could fail if we don't have permission.
+    proc, out, err = Popen_safe(['ldconfig', '-v'])
+    if proc.returncode == 0:
+        return
 
+    # ldconfig failed, print the error only if we actually installed files in
+    # any of the directories it lookup for libraries. Otherwise quietly ignore
+    # the error.
+    for l in out.splitlines():
+        # Lines that start with a \t are libraries, not directories.
+        if not l or l[0].isspace():
+            continue
+        # Example: `/usr/lib/i386-linux-gnu/i686: (hwcap: 0x0002000000000000)`
+        if l[:l.find(':')] in dm.all_dirs:
+            print(f'Failed to apply ldconfig:\n{err}')
+            break
 
-def get_destdir_path(d, path):
+def get_destdir_path(destdir: str, fullprefix: str, path: str) -> str:
     if os.path.isabs(path):
-        output = destdir_join(d.destdir, path)
+        output = destdir_join(destdir, path)
     else:
-        output = os.path.join(d.fullprefix, path)
+        output = os.path.join(fullprefix, path)
     return output
 
 
-def check_for_stampfile(fname):
+def check_for_stampfile(fname: str) -> str:
     '''Some languages e.g. Rust have output files
     whose names are not known at configure time.
     Check if this is the case and return the real
@@ -208,14 +316,104 @@
                 return files[0]
     return fname
 
+
 class Installer:
 
-    def __init__(self, options, lf):
+    def __init__(self, options: 'ArgumentType', lf: T.TextIO):
         self.did_install_something = False
+        self.printed_symlink_error = False
         self.options = options
         self.lf = lf
+        self.preserved_file_count = 0
+        self.dry_run = options.dry_run
+        # [''] means skip none,
+        # ['*'] means skip all,
+        # ['sub1', ...] means skip only those.
+        self.skip_subprojects = [i.strip() for i in options.skip_subprojects.split(',')]
+        self.tags = [i.strip() for i in options.tags.split(',')] if options.tags else None
+
+    def remove(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            os.remove(*args, **kwargs)
+
+    def symlink(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            os.symlink(*args, **kwargs)
+
+    def makedirs(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            os.makedirs(*args, **kwargs)
+
+    def copy(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            shutil.copy(*args, **kwargs)
+
+    def copy2(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            shutil.copy2(*args, **kwargs)
+
+    def copyfile(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            shutil.copyfile(*args, **kwargs)
+
+    def copystat(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            shutil.copystat(*args, **kwargs)
+
+    def fix_rpath(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            depfixer.fix_rpath(*args, **kwargs)
+
+    def set_chown(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            set_chown(*args, **kwargs)
+
+    def set_chmod(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            set_chmod(*args, **kwargs)
+
+    def sanitize_permissions(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            sanitize_permissions(*args, **kwargs)
+
+    def set_mode(self, *args: T.Any, **kwargs: T.Any) -> None:
+        if not self.dry_run:
+            set_mode(*args, **kwargs)
+
+    def restore_selinux_contexts(self, destdir: str) -> None:
+        if not self.dry_run and not destdir:
+            restore_selinux_contexts()
+
+    def apply_ldconfig(self, dm: DirMaker, destdir: str, is_cross_build: bool, libdir: str) -> None:
+        if any([self.dry_run, destdir, is_cross_build]):
+            return
+        apply_ldconfig(dm, libdir)
+
+    def Popen_safe(self, *args: T.Any, **kwargs: T.Any) -> T.Tuple[int, str, str]:
+        if not self.dry_run:
+            p, o, e = Popen_safe(*args, **kwargs)
+            return p.returncode, o, e
+        return 0, '', ''
+
+    def run_exe(self, *args: T.Any, **kwargs: T.Any) -> int:
+        if not self.dry_run:
+            return run_exe(*args, **kwargs)
+        return 0
+
+    def should_install(self, d: T.Union[TargetInstallData, InstallEmptyDir,
+                                        InstallDataBase, InstallSymlinkData,
+                                        ExecutableSerialisation]) -> bool:
+        if d.subproject and (d.subproject in self.skip_subprojects or '*' in self.skip_subprojects):
+            return False
+        if self.tags and d.tag not in self.tags:
+            return False
+        return True
+
+    def log(self, msg: str) -> None:
+        if not self.options.quiet:
+            print(msg)
 
-    def should_preserve_existing_file(self, from_file, to_file):
+    def should_preserve_existing_file(self, from_file: str, to_file: str) -> bool:
         if not self.options.only_changed:
             return False
         # Always replace danging symlinks
@@ -225,42 +423,69 @@
         to_time = os.stat(to_file).st_mtime
         return from_time <= to_time
 
-    def do_copyfile(self, from_file, to_file):
+    def do_copyfile(self, from_file: str, to_file: str,
+                    makedirs: T.Optional[T.Tuple[T.Any, str]] = None) -> bool:
         outdir = os.path.split(to_file)[0]
         if not os.path.isfile(from_file) and not os.path.islink(from_file):
-            raise RuntimeError('Tried to install something that isn\'t a file:'
-                               '{!r}'.format(from_file))
+            raise MesonException(f'Tried to install something that isn\'t a file: {from_file!r}')
         # copyfile fails if the target file already exists, so remove it to
         # allow overwriting a previous install. If the target is not a file, we
         # want to give a readable error.
         if os.path.exists(to_file):
             if not os.path.isfile(to_file):
-                raise RuntimeError('Destination {!r} already exists and is not '
-                                   'a file'.format(to_file))
+                raise MesonException(f'Destination {to_file!r} already exists and is not a file')
             if self.should_preserve_existing_file(from_file, to_file):
-                append_to_log(self.lf, '# Preserving old file %s\n' % to_file)
-                print('Preserving existing file %s' % to_file)
+                append_to_log(self.lf, f'# Preserving old file {to_file}\n')
+                self.preserved_file_count += 1
                 return False
-            os.remove(to_file)
-        print('Installing %s to %s' % (from_file, outdir))
+            self.remove(to_file)
+        elif makedirs:
+            # Unpack tuple
+            dirmaker, outdir = makedirs
+            # Create dirs if needed
+            dirmaker.makedirs(outdir, exist_ok=True)
+        self.log(f'Installing {from_file} to {outdir}')
         if os.path.islink(from_file):
             if not os.path.exists(from_file):
                 # Dangling symlink. Replicate as is.
-                shutil.copy(from_file, outdir, follow_symlinks=False)
+                self.copy(from_file, outdir, follow_symlinks=False)
             else:
                 # Remove this entire branch when changing the behaviour to duplicate
                 # symlinks rather than copying what they point to.
                 print(symlink_warning)
-                shutil.copyfile(from_file, to_file)
-                shutil.copystat(from_file, to_file)
+                self.copy2(from_file, to_file)
         else:
-            shutil.copyfile(from_file, to_file)
-            shutil.copystat(from_file, to_file)
+            self.copy2(from_file, to_file)
         selinux_updates.append(to_file)
         append_to_log(self.lf, to_file)
         return True
 
-    def do_copydir(self, data, src_dir, dst_dir, exclude, install_mode):
+    def do_symlink(self, target: str, link: str, full_dst_dir: str) -> bool:
+        abs_target = target
+        if not os.path.isabs(target):
+            abs_target = os.path.join(full_dst_dir, target)
+        if not os.path.exists(abs_target):
+            raise MesonException(f'Tried to install symlink to missing file {abs_target}')
+        if os.path.exists(link):
+            if not os.path.islink(link):
+                raise MesonException(f'Destination {link!r} already exists and is not a symlink')
+            self.remove(link)
+        if not self.printed_symlink_error:
+            self.log(f'Installing symlink pointing to {target} to {link}')
+        try:
+            self.symlink(target, link, target_is_directory=os.path.isdir(abs_target))
+        except (NotImplementedError, OSError):
+            if not self.printed_symlink_error:
+                print("Symlink creation does not work on this platform. "
+                      "Skipping all symlinking.")
+                self.printed_symlink_error = True
+            return False
+        append_to_log(self.lf, link)
+        return True
+
+    def do_copydir(self, data: InstallData, src_dir: str, dst_dir: str,
+                   exclude: T.Optional[T.Tuple[T.Set[str], T.Set[str]]],
+                   install_mode: 'FileMode', dm: DirMaker) -> None:
         '''
         Copies the contents of directory @src_dir into @dst_dir.
 
@@ -284,9 +509,9 @@
                      each element of the set is a path relative to src_dir.
         '''
         if not os.path.isabs(src_dir):
-            raise ValueError('src_dir must be absolute, got %s' % src_dir)
+            raise ValueError(f'src_dir must be absolute, got {src_dir}')
         if not os.path.isabs(dst_dir):
-            raise ValueError('dst_dir must be absolute, got %s' % dst_dir)
+            raise ValueError(f'dst_dir must be absolute, got {dst_dir}')
         if exclude is not None:
             exclude_files, exclude_dirs = exclude
         else:
@@ -304,11 +529,11 @@
                 if os.path.isdir(abs_dst):
                     continue
                 if os.path.exists(abs_dst):
-                    print('Tried to copy directory %s but a file of that name already exists.' % abs_dst)
+                    print(f'Tried to copy directory {abs_dst} but a file of that name already exists.')
                     sys.exit(1)
-                data.dirmaker.makedirs(abs_dst)
-                shutil.copystat(abs_src, abs_dst)
-                sanitize_permissions(abs_dst, data.install_umask)
+                dm.makedirs(abs_dst)
+                self.copystat(abs_src, abs_dst)
+                self.sanitize_permissions(abs_dst, data.install_umask)
             for f in files:
                 abs_src = os.path.join(root, f)
                 filepart = os.path.relpath(abs_src, start=src_dir)
@@ -316,39 +541,65 @@
                     continue
                 abs_dst = os.path.join(dst_dir, filepart)
                 if os.path.isdir(abs_dst):
-                    print('Tried to copy file %s but a directory of that name already exists.' % abs_dst)
+                    print(f'Tried to copy file {abs_dst} but a directory of that name already exists.')
+                    sys.exit(1)
                 parent_dir = os.path.dirname(abs_dst)
                 if not os.path.isdir(parent_dir):
-                    os.mkdir(parent_dir)
-                    shutil.copystat(os.path.dirname(abs_src), parent_dir)
+                    dm.makedirs(parent_dir)
+                    self.copystat(os.path.dirname(abs_src), parent_dir)
                 # FIXME: what about symlinks?
                 self.do_copyfile(abs_src, abs_dst)
-                set_mode(abs_dst, install_mode, data.install_umask)
+                self.set_mode(abs_dst, install_mode, data.install_umask)
 
-    def do_install(self, datafilename):
+    @staticmethod
+    def check_installdata(obj: InstallData) -> InstallData:
+        if not isinstance(obj, InstallData) or not hasattr(obj, 'version'):
+            raise MesonVersionMismatchException('', coredata_version)
+        if major_versions_differ(obj.version, coredata_version):
+            raise MesonVersionMismatchException(obj.version, coredata_version)
+        return obj
+
+    def do_install(self, datafilename: str) -> None:
         with open(datafilename, 'rb') as ifile:
-            d = pickle.load(ifile)
-        d.destdir = os.environ.get('DESTDIR', '')
-        d.fullprefix = destdir_join(d.destdir, d.prefix)
+            d = self.check_installdata(pickle.load(ifile))
+
+        destdir = self.options.destdir
+        if destdir is None:
+            destdir = os.environ.get('DESTDIR')
+        if destdir and not os.path.isabs(destdir):
+            destdir = os.path.join(d.build_dir, destdir)
+        # Override in the env because some scripts could use it and require an
+        # absolute path.
+        if destdir is not None:
+            os.environ['DESTDIR'] = destdir
+        destdir = destdir or ''
+        fullprefix = destdir_join(destdir, d.prefix)
+        libdir = os.path.join(d.prefix, d.libdir)
 
         if d.install_umask != 'preserve':
+            assert isinstance(d.install_umask, int)
             os.umask(d.install_umask)
 
         self.did_install_something = False
         try:
-            d.dirmaker = DirMaker(self.lf)
-            with d.dirmaker:
-                self.install_subdirs(d) # Must be first, because it needs to delete the old subtree.
-                self.install_targets(d)
-                self.install_headers(d)
-                self.install_man(d)
-                self.install_data(d)
-                restore_selinux_contexts()
-                self.run_install_script(d)
+            with DirMaker(self.lf, self.makedirs) as dm:
+                self.install_subdirs(d, dm, destdir, fullprefix) # Must be first, because it needs to delete the old subtree.
+                self.install_targets(d, dm, destdir, fullprefix)
+                self.install_headers(d, dm, destdir, fullprefix)
+                self.install_man(d, dm, destdir, fullprefix)
+                self.install_emptydir(d, dm, destdir, fullprefix)
+                self.install_data(d, dm, destdir, fullprefix)
+                self.install_symlinks(d, dm, destdir, fullprefix)
+                self.restore_selinux_contexts(destdir)
+                self.apply_ldconfig(dm, destdir, d.is_cross_build, libdir)
+                self.run_install_script(d, destdir, fullprefix)
                 if not self.did_install_something:
-                    print('Nothing to install.')
+                    self.log('Nothing to install.')
+                if not self.options.quiet and self.preserved_file_count > 0:
+                    self.log('Preserved {} unchanged files, see {} for the full list'
+                             .format(self.preserved_file_count, os.path.normpath(self.lf.name)))
         except PermissionError:
-            if shutil.which('pkexec') is not None and 'PKEXEC_UID' not in os.environ:
+            if shutil.which('pkexec') is not None and 'PKEXEC_UID' not in os.environ and destdir == '':
                 print('Installation failed due to insufficient permissions.')
                 print('Attempting to use polkit to gain elevated privileges...')
                 os.execlp('pkexec', 'pkexec', sys.executable, main_file, *sys.argv[1:],
@@ -356,85 +607,116 @@
             else:
                 raise
 
-    def install_subdirs(self, d):
-        for (src_dir, dst_dir, mode, exclude) in d.install_subdirs:
+    def install_subdirs(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
+        for i in d.install_subdirs:
+            if not self.should_install(i):
+                continue
             self.did_install_something = True
-            full_dst_dir = get_destdir_path(d, dst_dir)
-            print('Installing subdir %s to %s' % (src_dir, full_dst_dir))
-            d.dirmaker.makedirs(full_dst_dir, exist_ok=True)
-            self.do_copydir(d, src_dir, full_dst_dir, exclude, mode)
+            full_dst_dir = get_destdir_path(destdir, fullprefix, i.install_path)
+            self.log(f'Installing subdir {i.path} to {full_dst_dir}')
+            dm.makedirs(full_dst_dir, exist_ok=True)
+            self.do_copydir(d, i.path, full_dst_dir, i.exclude, i.install_mode, dm)
 
-    def install_data(self, d):
+    def install_data(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
         for i in d.data:
-            self.did_install_something = True
-            fullfilename = i[0]
-            outfilename = get_destdir_path(d, i[1])
-            mode = i[2]
+            if not self.should_install(i):
+                continue
+            fullfilename = i.path
+            outfilename = get_destdir_path(destdir, fullprefix, i.install_path)
             outdir = os.path.dirname(outfilename)
-            d.dirmaker.makedirs(outdir, exist_ok=True)
-            self.do_copyfile(fullfilename, outfilename)
-            set_mode(outfilename, mode, d.install_umask)
+            if self.do_copyfile(fullfilename, outfilename, makedirs=(dm, outdir)):
+                self.did_install_something = True
+            self.set_mode(outfilename, i.install_mode, d.install_umask)
+
+    def install_symlinks(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
+        for s in d.symlinks:
+            if not self.should_install(s):
+                continue
+            full_dst_dir = get_destdir_path(destdir, fullprefix, s.install_path)
+            full_link_name = get_destdir_path(destdir, fullprefix, s.name)
+            dm.makedirs(full_dst_dir, exist_ok=True)
+            if self.do_symlink(s.target, full_link_name, full_dst_dir):
+                self.did_install_something = True
 
-    def install_man(self, d):
+    def install_man(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
         for m in d.man:
-            self.did_install_something = True
-            full_source_filename = m[0]
-            outfilename = get_destdir_path(d, m[1])
+            if not self.should_install(m):
+                continue
+            full_source_filename = m.path
+            outfilename = get_destdir_path(destdir, fullprefix, m.install_path)
             outdir = os.path.dirname(outfilename)
-            d.dirmaker.makedirs(outdir, exist_ok=True)
-            install_mode = m[2]
-            self.do_copyfile(full_source_filename, outfilename)
-            set_mode(outfilename, install_mode, d.install_umask)
+            if self.do_copyfile(full_source_filename, outfilename, makedirs=(dm, outdir)):
+                self.did_install_something = True
+            self.set_mode(outfilename, m.install_mode, d.install_umask)
+
+    def install_emptydir(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
+        for e in d.emptydir:
+            if not self.should_install(e):
+                continue
+            self.did_install_something = True
+            full_dst_dir = get_destdir_path(destdir, fullprefix, e.path)
+            self.log(f'Installing new directory {full_dst_dir}')
+            if os.path.isfile(full_dst_dir):
+                print(f'Tried to create directory {full_dst_dir} but a file of that name already exists.')
+                sys.exit(1)
+            dm.makedirs(full_dst_dir, exist_ok=True)
+            self.set_mode(full_dst_dir, e.install_mode, d.install_umask)
 
-    def install_headers(self, d):
+    def install_headers(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
         for t in d.headers:
-            self.did_install_something = True
-            fullfilename = t[0]
+            if not self.should_install(t):
+                continue
+            fullfilename = t.path
             fname = os.path.basename(fullfilename)
-            outdir = get_destdir_path(d, t[1])
+            outdir = get_destdir_path(destdir, fullprefix, t.install_path)
             outfilename = os.path.join(outdir, fname)
-            install_mode = t[2]
-            d.dirmaker.makedirs(outdir, exist_ok=True)
-            self.do_copyfile(fullfilename, outfilename)
-            set_mode(outfilename, install_mode, d.install_umask)
+            if self.do_copyfile(fullfilename, outfilename, makedirs=(dm, outdir)):
+                self.did_install_something = True
+            self.set_mode(outfilename, t.install_mode, d.install_umask)
 
-    def run_install_script(self, d):
+    def run_install_script(self, d: InstallData, destdir: str, fullprefix: str) -> None:
         env = {'MESON_SOURCE_ROOT': d.source_dir,
                'MESON_BUILD_ROOT': d.build_dir,
                'MESON_INSTALL_PREFIX': d.prefix,
-               'MESON_INSTALL_DESTDIR_PREFIX': d.fullprefix,
+               'MESON_INSTALL_DESTDIR_PREFIX': fullprefix,
                'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in d.mesonintrospect]),
                }
-
-        child_env = os.environ.copy()
-        child_env.update(env)
+        if self.options.quiet:
+            env['MESON_INSTALL_QUIET'] = '1'
 
         for i in d.install_scripts:
+            if not self.should_install(i):
+                continue
+            name = ' '.join(i.cmd_args)
+            if i.skip_if_destdir and destdir:
+                self.log(f'Skipping custom install script because DESTDIR is set {name!r}')
+                continue
             self.did_install_something = True  # Custom script must report itself if it does nothing.
-            script = i['exe']
-            args = i['args']
-            name = ' '.join(script + args)
-            print('Running custom install script {!r}'.format(name))
+            self.log(f'Running custom install script {name!r}')
             try:
-                rc = subprocess.call(script + args, env=child_env)
-                if rc != 0:
-                    sys.exit(rc)
+                rc = self.run_exe(i, env)
             except OSError:
-                print('Failed to run install script {!r}'.format(name))
-                sys.exit(1)
+                print(f'FAILED: install script \'{name}\' could not be run, stopped')
+                # POSIX shells return 127 when a command could not be found
+                sys.exit(127)
+            if rc != 0:
+                print(f'FAILED: install script \'{name}\' exit code {rc}, stopped')
+                sys.exit(rc)
 
-    def install_targets(self, d):
+    def install_targets(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
         for t in d.targets:
-            self.did_install_something = True
+            if not self.should_install(t):
+                continue
             if not os.path.exists(t.fname):
                 # For example, import libraries of shared modules are optional
                 if t.optional:
-                    print('File {!r} not found, skipping'.format(t.fname))
+                    self.log(f'File {t.fname!r} not found, skipping')
                     continue
                 else:
-                    raise RuntimeError('File {!r} could not be found'.format(t.fname))
+                    raise MesonException(f'File {t.fname!r} could not be found')
+            file_copied = False # not set when a directory is copied
             fname = check_for_stampfile(t.fname)
-            outdir = get_destdir_path(d, t.outdir)
+            outdir = get_destdir_path(destdir, fullprefix, t.outdir)
             outname = os.path.join(outdir, os.path.basename(fname))
             final_path = os.path.join(d.prefix, t.outdir, os.path.basename(fname))
             aliases = t.aliases
@@ -442,22 +724,21 @@
             install_rpath = t.install_rpath
             install_name_mappings = t.install_name_mappings
             install_mode = t.install_mode
-            d.dirmaker.makedirs(outdir, exist_ok=True)
             if not os.path.exists(fname):
-                raise RuntimeError('File {!r} could not be found'.format(fname))
+                raise MesonException(f'File {fname!r} could not be found')
             elif os.path.isfile(fname):
-                self.do_copyfile(fname, outname)
-                set_mode(outname, install_mode, d.install_umask)
+                file_copied = self.do_copyfile(fname, outname, makedirs=(dm, outdir))
+                self.set_mode(outname, install_mode, d.install_umask)
                 if should_strip and d.strip_bin is not None:
                     if fname.endswith('.jar'):
-                        print('Not stripping jar target:', os.path.basename(fname))
+                        self.log('Not stripping jar target: {}'.format(os.path.basename(fname)))
                         continue
-                    print('Stripping target {!r} using {}.'.format(fname, d.strip_bin[0]))
-                    ps, stdo, stde = Popen_safe(d.strip_bin + [outname])
-                    if ps.returncode != 0:
+                    self.log('Stripping target {!r} using {}.'.format(fname, d.strip_bin[0]))
+                    returncode, stdo, stde = self.Popen_safe(d.strip_bin + [outname])
+                    if returncode != 0:
                         print('Could not strip file.\n')
-                        print('Stdout:\n%s\n' % stdo)
-                        print('Stderr:\n%s\n' % stde)
+                        print(f'Stdout:\n{stdo}\n')
+                        print(f'Stderr:\n{stde}\n')
                         sys.exit(1)
                 if fname.endswith('.js'):
                     # Emscripten outputs js files and optionally a wasm file.
@@ -465,51 +746,67 @@
                     wasm_source = os.path.splitext(fname)[0] + '.wasm'
                     if os.path.exists(wasm_source):
                         wasm_output = os.path.splitext(outname)[0] + '.wasm'
-                        self.do_copyfile(wasm_source, wasm_output)
+                        file_copied = self.do_copyfile(wasm_source, wasm_output)
             elif os.path.isdir(fname):
                 fname = os.path.join(d.build_dir, fname.rstrip('/'))
                 outname = os.path.join(outdir, os.path.basename(fname))
-                self.do_copydir(d, fname, outname, None, install_mode)
+                dm.makedirs(outdir, exist_ok=True)
+                self.do_copydir(d, fname, outname, None, install_mode, dm)
             else:
-                raise RuntimeError('Unknown file type for {!r}'.format(fname))
-            printed_symlink_error = False
-            for alias, to in aliases.items():
+                raise RuntimeError(f'Unknown file type for {fname!r}')
+            for alias, target in aliases.items():
+                symlinkfilename = os.path.join(outdir, alias)
+                self.do_symlink(target, symlinkfilename, outdir)
+            if file_copied:
+                self.did_install_something = True
                 try:
-                    symlinkfilename = os.path.join(outdir, alias)
-                    try:
-                        os.remove(symlinkfilename)
-                    except FileNotFoundError:
-                        pass
-                    os.symlink(to, symlinkfilename)
-                    append_to_log(self.lf, symlinkfilename)
-                except (NotImplementedError, OSError):
-                    if not printed_symlink_error:
-                        print("Symlink creation does not work on this platform. "
-                              "Skipping all symlinking.")
-                        printed_symlink_error = True
-            if os.path.isfile(outname):
-                try:
-                    depfixer.fix_rpath(outname, install_rpath, final_path,
-                                       install_name_mappings, verbose=False)
+                    self.fix_rpath(outname, t.rpath_dirs_to_remove, install_rpath, final_path,
+                                   install_name_mappings, verbose=False)
                 except SystemExit as e:
                     if isinstance(e.code, int) and e.code == 0:
                         pass
                     else:
                         raise
 
-def run(opts):
+
+def rebuild_all(wd: str) -> bool:
+    if not (Path(wd) / 'build.ninja').is_file():
+        print('Only ninja backend is supported to rebuild the project before installation.')
+        return True
+
+    ninja = environment.detect_ninja()
+    if not ninja:
+        print("Can't find ninja, can't rebuild test.")
+        return False
+
+    ret = subprocess.run(ninja + ['-C', wd]).returncode
+    if ret != 0:
+        print(f'Could not rebuild {wd}')
+        return False
+
+    return True
+
+
+def run(opts: 'ArgumentType') -> int:
     datafilename = 'meson-private/install.dat'
     private_dir = os.path.dirname(datafilename)
     log_dir = os.path.join(private_dir, '../meson-logs')
     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)
-    with open(os.path.join(log_dir, 'install-log.txt'), 'w') as lf:
+    with open(os.path.join(log_dir, 'install-log.txt'), 'w', encoding='utf-8') as lf:
         installer = Installer(opts, lf)
         append_to_log(lf, '# List of files installed by Meson')
         append_to_log(lf, '# Does not contain files installed by custom scripts.')
-        installer.do_install(datafilename)
+        if opts.profile:
+            import cProfile as profile
+            fname = os.path.join(private_dir, 'profile-installer.log')
+            profile.runctx('installer.do_install(datafilename)', globals(), locals(), filename=fname)
+        else:
+            installer.do_install(datafilename)
     return 0
diff -Nru meson-0.53.2/mesonbuild/mintro.py meson-0.61.2/mesonbuild/mintro.py
--- meson-0.53.2/mesonbuild/mintro.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/mintro.py	2021-11-02 19:58:07.000000000 +0000
@@ -19,16 +19,21 @@
 Currently only works for the Ninja backend. Others use generated
 project files and don't need this info."""
 
+import collections
 import json
 from . import build, coredata as cdata
 from . import mesonlib
-from .ast import IntrospectionInterpreter, build_target_functions, AstConditionLevel, AstIDGenerator, AstIndentationGenerator
+from .ast import IntrospectionInterpreter, build_target_functions, AstConditionLevel, AstIDGenerator, AstIndentationGenerator, AstJSONPrinter
 from . import mlog
 from .backend import backends
-from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode
+from .mparser import BaseNode, FunctionNode, ArrayNode, ArgumentNode, StringNode
+from .interpreter import Interpreter
+from pathlib import Path, PurePath
 import typing as T
 import os
-import pathlib
+import argparse
+
+from .mesonlib import OptionKey
 
 def get_meson_info_file(info_dir: str) -> str:
     return os.path.join(info_dir, 'meson-info.json')
@@ -51,33 +56,37 @@
 def get_meson_introspection_types(coredata: T.Optional[cdata.CoreData] = None,
                                   builddata: T.Optional[build.Build] = None,
                                   backend: T.Optional[backends.Backend] = None,
-                                  sourcedir: T.Optional[str] = None) -> T.Dict[str, IntroCommand]:
+                                  sourcedir: T.Optional[str] = None) -> 'T.Mapping[str, IntroCommand]':
     if backend and builddata:
         benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks())
         testdata = backend.create_test_serialisation(builddata.get_tests())
         installdata = backend.create_install_data()
+        interpreter = backend.interpreter
     else:
         benchmarkdata = testdata = installdata = None
 
-    return {
-        'benchmarks': IntroCommand('T.List all benchmarks', func=lambda: list_benchmarks(benchmarkdata)),
-        'buildoptions': IntroCommand('T.List all build options', func=lambda: list_buildoptions(coredata), no_bd=list_buildoptions_from_source),
-        'buildsystem_files': IntroCommand('T.List files that make up the build system', func=lambda: list_buildsystem_files(builddata)),
-        'dependencies': IntroCommand('T.List external dependencies', func=lambda: list_deps(coredata), no_bd=list_deps_from_source),
-        'scan_dependencies': IntroCommand('Scan for dependencies used in the meson.build file', no_bd=list_deps_from_source),
-        'installed': IntroCommand('T.List all installed files and directories', func=lambda: list_installed(installdata)),
-        'projectinfo': IntroCommand('Information about projects', func=lambda: list_projinfo(builddata), no_bd=list_projinfo_from_source),
-        'targets': IntroCommand('T.List top level targets', func=lambda: list_targets(builddata, installdata, backend), no_bd=list_targets_from_source),
-        'tests': IntroCommand('T.List all unit tests', func=lambda: list_tests(testdata)),
-    }
+    # Enforce key order for argparse
+    return collections.OrderedDict([
+        ('ast', IntroCommand('Dump the AST of the meson file', no_bd=dump_ast)),
+        ('benchmarks', IntroCommand('List all benchmarks', func=lambda: list_benchmarks(benchmarkdata))),
+        ('buildoptions', IntroCommand('List all build options', func=lambda: list_buildoptions(coredata), no_bd=list_buildoptions_from_source)),
+        ('buildsystem_files', IntroCommand('List files that make up the build system', func=lambda: list_buildsystem_files(builddata, interpreter))),
+        ('dependencies', IntroCommand('List external dependencies', func=lambda: list_deps(coredata), no_bd=list_deps_from_source)),
+        ('scan_dependencies', IntroCommand('Scan for dependencies used in the meson.build file', no_bd=list_deps_from_source)),
+        ('installed', IntroCommand('List all installed files and directories', func=lambda: list_installed(installdata))),
+        ('install_plan', IntroCommand('List all installed files and directories with their details', func=lambda: list_install_plan(installdata))),
+        ('projectinfo', IntroCommand('Information about projects', func=lambda: list_projinfo(builddata), no_bd=list_projinfo_from_source)),
+        ('targets', IntroCommand('List top level targets', func=lambda: list_targets(builddata, installdata, backend), no_bd=list_targets_from_source)),
+        ('tests', IntroCommand('List all unit tests', func=lambda: list_tests(testdata))),
+    ])
 
-def add_arguments(parser):
+def add_arguments(parser: argparse.ArgumentParser) -> None:
     intro_types = get_meson_introspection_types()
     for key, val in intro_types.items():
         flag = '--' + key.replace('_', '-')
         parser.add_argument(flag, action='store_true', dest=key, default=False, help=val.desc)
 
-    parser.add_argument('--backend', choices=cdata.backendlist, dest='backend', default='ninja',
+    parser.add_argument('--backend', choices=sorted(cdata.backendlist), dest='backend', default='ninja',
                         help='The backend to use for the --buildoptions introspection.')
     parser.add_argument('-a', '--all', action='store_true', dest='all', default=False,
                         help='Print all available information.')
@@ -87,28 +96,74 @@
                         help='Always use the new JSON format for multiple entries (even for 0 and 1 introspection commands)')
     parser.add_argument('builddir', nargs='?', default='.', help='The build directory')
 
-def list_installed(installdata):
+def dump_ast(intr: IntrospectionInterpreter) -> T.Dict[str, T.Any]:
+    printer = AstJSONPrinter()
+    intr.ast.accept(printer)
+    return printer.result
+
+def list_installed(installdata: backends.InstallData) -> T.Dict[str, str]:
     res = {}
     if installdata is not None:
         for t in installdata.targets:
             res[os.path.join(installdata.build_dir, t.fname)] = \
                 os.path.join(installdata.prefix, t.outdir, os.path.basename(t.fname))
-        for path, installpath, _ in installdata.data:
-            res[path] = os.path.join(installdata.prefix, installpath)
-        for path, installdir, _ in installdata.headers:
-            res[path] = os.path.join(installdata.prefix, installdir, os.path.basename(path))
-        for path, installpath, _ in installdata.man:
-            res[path] = os.path.join(installdata.prefix, installpath)
-        for path, installpath, _, _ in installdata.install_subdirs:
-            res[path] = os.path.join(installdata.prefix, installpath)
+            for alias in t.aliases.keys():
+                res[os.path.join(installdata.build_dir, alias)] = \
+                    os.path.join(installdata.prefix, t.outdir, os.path.basename(alias))
+        for i in installdata.data:
+            res[i.path] = os.path.join(installdata.prefix, i.install_path)
+        for i in installdata.headers:
+            res[i.path] = os.path.join(installdata.prefix, i.install_path, os.path.basename(i.path))
+        for i in installdata.man:
+            res[i.path] = os.path.join(installdata.prefix, i.install_path)
+        for i in installdata.install_subdirs:
+            res[i.path] = os.path.join(installdata.prefix, i.install_path)
     return res
 
+def list_install_plan(installdata: backends.InstallData) -> T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]]:
+    plan = {
+        'targets': {
+            os.path.join(installdata.build_dir, target.fname): {
+                'destination': target.out_name,
+                'tag': target.tag or None,
+            }
+            for target in installdata.targets
+        },
+    }  # type: T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]]
+    for key, data_list in {
+        'data': installdata.data,
+        'man': installdata.man,
+        'headers': installdata.headers,
+    }.items():
+        for data in data_list:
+            data_type = data.data_type or key
+            install_path_name = data.install_path_name
+            if key == 'headers':  # in the headers, install_path_name is the directory
+                install_path_name = os.path.join(install_path_name, os.path.basename(data.path))
+            elif data_type == 'configure':
+                install_path_name = os.path.join('{prefix}', install_path_name)
+
+            plan[data_type] = plan.get(data_type, {})
+            plan[data_type][data.path] = {
+                'destination': install_path_name,
+                'tag': data.tag or None,
+            }
+    return plan
+
+def get_target_dir(coredata: cdata.CoreData, subdir: str) -> str:
+    if coredata.get_option(OptionKey('layout')) == 'flat':
+        return 'meson-out'
+    else:
+        return subdir
+
 def list_targets_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]:
     tlist = []  # type: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]
-    for i in intr.targets:
-        sources = []  # type: T.List[str]
-        for n in i['sources']:
-            args = []  # type: T.List[T.Union[str, StringNode]]
+    root_dir = Path(intr.source_root)
+
+    def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]:
+        res = []  # type: T.List[Path]
+        for n in node_list:
+            args = []  # type: T.List[BaseNode]
             if isinstance(n, FunctionNode):
                 args = list(n.args.arguments)
                 if n.func_name in build_target_functions:
@@ -119,95 +174,108 @@
                 args = n.arguments
             for j in args:
                 if isinstance(j, StringNode):
-                    sources += [j.value]
+                    assert isinstance(j.value, str)
+                    res += [Path(j.value)]
                 elif isinstance(j, str):
-                    sources += [j]
+                    res += [Path(j)]
+        res = [root_dir / i['subdir'] / x for x in res]
+        res = [x.resolve() for x in res]
+        return res
+
+    for i in intr.targets:
+        sources = nodes_to_paths(i['sources'])
+        extra_f = nodes_to_paths(i['extra_files'])
+        outdir = get_target_dir(intr.coredata, i['subdir'])
 
         tlist += [{
             'name': i['name'],
             'id': i['id'],
             'type': i['type'],
             'defined_in': i['defined_in'],
-            'filename': [os.path.join(i['subdir'], x) for x in i['outputs']],
+            'filename': [os.path.join(outdir, x) for x in i['outputs']],
             'build_by_default': i['build_by_default'],
             'target_sources': [{
                 'language': 'unknown',
                 'compiler': [],
                 'parameters': [],
-                'sources': [os.path.normpath(os.path.join(os.path.abspath(intr.source_root), i['subdir'], x)) for x in sources],
+                'sources': [str(x) for x in sources],
                 'generated_sources': []
             }],
+            'extra_files': [str(x) for x in extra_f],
             'subproject': None, # Subprojects are not supported
             'installed': i['installed']
         }]
 
     return tlist
 
-def list_targets(builddata: build.Build, installdata, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]:
-    tlist = []  # type: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]
+def list_targets(builddata: build.Build, installdata: backends.InstallData, backend: backends.Backend) -> T.List[T.Any]:
+    tlist = []  # type: T.List[T.Any]
     build_dir = builddata.environment.get_build_dir()
     src_dir = builddata.environment.get_source_dir()
 
     # Fast lookup table for installation files
     install_lookuptable = {}
     for i in installdata.targets:
-        outname = os.path.join(installdata.prefix, i.outdir, os.path.basename(i.fname))
-        install_lookuptable[os.path.basename(i.fname)] = str(pathlib.PurePath(outname))
+        out = [os.path.join(installdata.prefix, i.outdir, os.path.basename(i.fname))]
+        out += [os.path.join(installdata.prefix, i.outdir, os.path.basename(x)) for x in i.aliases]
+        install_lookuptable[os.path.basename(i.fname)] = [str(PurePath(x)) for x in out]
 
     for (idname, target) in builddata.get_targets().items():
         if not isinstance(target, build.Target):
             raise RuntimeError('The target object in `builddata.get_targets()` is not of type `build.Target`. Please file a bug with this error message.')
 
+        outdir = get_target_dir(builddata.environment.coredata, target.subdir)
         t = {
             'name': target.get_basename(),
             'id': idname,
             'type': target.get_typename(),
             'defined_in': os.path.normpath(os.path.join(src_dir, target.subdir, 'meson.build')),
-            'filename': [os.path.join(build_dir, target.subdir, x) for x in target.get_outputs()],
+            'filename': [os.path.join(build_dir, outdir, x) for x in target.get_outputs()],
             'build_by_default': target.build_by_default,
             'target_sources': backend.get_introspection_data(idname, target),
+            'extra_files': [os.path.normpath(os.path.join(src_dir, x.subdir, x.fname)) for x in target.extra_files],
             'subproject': target.subproject or None
         }
 
         if installdata and target.should_install():
             t['installed'] = True
-            t['install_filename'] = [install_lookuptable.get(x, None) for x in target.get_outputs()]
+            ifn = [install_lookuptable.get(x, [None]) for x in target.get_outputs()]
+            t['install_filename'] = [x for sublist in ifn for x in sublist]  # flatten the list
         else:
             t['installed'] = False
         tlist.append(t)
     return tlist
 
 def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
-    return list_buildoptions(intr.coredata)
+    subprojects = [i['name'] for i in intr.project_data['subprojects']]
+    return list_buildoptions(intr.coredata, subprojects)
 
-def list_buildoptions(coredata: cdata.CoreData) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
+def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[str]] = None) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
     optlist = []  # type: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]
+    subprojects = subprojects or []
 
-    dir_option_names = ['bindir',
-                        'datadir',
-                        'includedir',
-                        'infodir',
-                        'libdir',
-                        'libexecdir',
-                        'localedir',
-                        'localstatedir',
-                        'mandir',
-                        'prefix',
-                        'sbindir',
-                        'sharedstatedir',
-                        'sysconfdir']
-    test_option_names = ['errorlogs',
-                         'stdsplit']
-    core_option_names = [k for k in coredata.builtins if k not in dir_option_names + test_option_names]
-
-    dir_options = {k: o for k, o in coredata.builtins.items() if k in dir_option_names}
-    test_options = {k: o for k, o in coredata.builtins.items() if k in test_option_names}
-    core_options = {k: o for k, o in coredata.builtins.items() if k in core_option_names}
-
-    def add_keys(options: T.Dict[str, cdata.UserOption], section: str, machine: str = 'any') -> None:
-        for key in sorted(options.keys()):
-            opt = options[key]
-            optdict = {'name': key, 'value': opt.value, 'section': section, 'machine': machine}
+    dir_option_names = set(cdata.BUILTIN_DIR_OPTIONS)
+    test_option_names = {OptionKey('errorlogs'),
+                         OptionKey('stdsplit')}
+
+    dir_options: 'cdata.KeyedOptionDictType' = {}
+    test_options: 'cdata.KeyedOptionDictType' = {}
+    core_options: 'cdata.KeyedOptionDictType' = {}
+    for k, v in coredata.options.items():
+        if k in dir_option_names:
+            dir_options[k] = v
+        elif k in test_option_names:
+            test_options[k] = v
+        elif k.is_builtin():
+            core_options[k] = v
+            if not v.yielding:
+                for s in subprojects:
+                    core_options[k.evolve(subproject=s)] = v
+
+    def add_keys(options: 'cdata.KeyedOptionDictType', section: str) -> None:
+        for key, opt in sorted(options.items()):
+            optdict = {'name': str(key), 'value': opt.value, 'section': section,
+                       'machine': key.machine.get_lower_case_name() if coredata.is_per_machine_option(key) else 'any'}
             if isinstance(opt, cdata.UserStringOption):
                 typestr = 'string'
             elif isinstance(opt, cdata.UserBooleanOption):
@@ -219,6 +287,8 @@
                 typestr = 'integer'
             elif isinstance(opt, cdata.UserArrayOption):
                 typestr = 'array'
+                if opt.choices:
+                    optdict['choices'] = opt.choices
             else:
                 raise RuntimeError("Unknown option type")
             optdict['type'] = typestr
@@ -226,26 +296,18 @@
             optlist.append(optdict)
 
     add_keys(core_options, 'core')
-    add_keys(coredata.builtins_per_machine.host, 'core', machine='host')
-    add_keys(
-        {'build.' + k: o for k, o in coredata.builtins_per_machine.build.items()},
-        'core',
-        machine='build',
-    )
-    add_keys(coredata.backend_options, 'backend')
-    add_keys(coredata.base_options, 'base')
-    add_keys(coredata.compiler_options.host, 'compiler', machine='host')
+    add_keys({k: v for k, v in coredata.options.items() if k.is_backend()}, 'backend')
+    add_keys({k: v for k, v in coredata.options.items() if k.is_base()}, 'base')
     add_keys(
-        {'build.' + k: o for k, o in coredata.compiler_options.build.items()},
+        {k: v for k, v in sorted(coredata.options.items(), key=lambda i: i[0].machine) if k.is_compiler()},
         'compiler',
-        machine='build',
     )
     add_keys(dir_options, 'directory')
-    add_keys(coredata.user_options, 'user')
+    add_keys({k: v for k, v in coredata.options.items() if k.is_project()}, 'user')
     add_keys(test_options, 'test')
     return optlist
 
-def find_buildsystem_files_list(src_dir) -> T.List[str]:
+def find_buildsystem_files_list(src_dir: str) -> T.List[str]:
     # I feel dirty about this. But only slightly.
     filelist = []  # type: T.List[str]
     for root, _, files in os.walk(src_dir):
@@ -254,10 +316,10 @@
                 filelist.append(os.path.relpath(os.path.join(root, f), src_dir))
     return filelist
 
-def list_buildsystem_files(builddata: build.Build) -> T.List[str]:
+def list_buildsystem_files(builddata: build.Build, interpreter: Interpreter) -> T.List[str]:
     src_dir = builddata.environment.get_source_dir()
-    filelist = find_buildsystem_files_list(src_dir)
-    filelist = [os.path.join(src_dir, x) for x in filelist]
+    filelist = interpreter.get_build_def_files()  # type: T.List[str]
+    filelist = [PurePath(src_dir, x).as_posix() for x in filelist]
     return filelist
 
 def list_deps_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool]]]:
@@ -283,10 +345,10 @@
                         'link_args': d.get_link_args()}]
     return result
 
-def get_test_list(testdata) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
+def get_test_list(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
     result = []  # type: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]
     for t in testdata:
-        to = {}
+        to = {}  # type: T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]
         if isinstance(t.fname, str):
             fname = [t.fname]
         else:
@@ -302,25 +364,26 @@
         to['suite'] = t.suite
         to['is_parallel'] = t.is_parallel
         to['priority'] = t.priority
-        to['protocol'] = t.protocol
+        to['protocol'] = str(t.protocol)
+        to['depends'] = t.depends
         result.append(to)
     return result
 
-def list_tests(testdata) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
+def list_tests(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
     return get_test_list(testdata)
 
-def list_benchmarks(benchdata) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
+def list_benchmarks(benchdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
     return get_test_list(benchdata)
 
 def list_projinfo(builddata: build.Build) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]:
     result = {'version': builddata.project_version,
               'descriptive_name': builddata.project_name,
-              'subproject_dir': builddata.subproject_dir}
+              'subproject_dir': builddata.subproject_dir}    # type: T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]
     subprojects = []
     for k, v in builddata.subprojects.items():
         c = {'name': k,
              'version': v,
-             'descriptive_name': builddata.projects.get(k)}
+             'descriptive_name': builddata.projects.get(k)}  # type: T.Dict[str, str]
         subprojects.append(c)
     result['subprojects'] = subprojects
     return result
@@ -339,7 +402,7 @@
     intr.project_data['subproject_dir'] = intr.subproject_dir
     return intr.project_data
 
-def print_results(options, results: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], indent: int) -> int:
+def print_results(options: argparse.Namespace, results: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], indent: int) -> int:
     if not results and not options.force_dict:
         print('No command specified')
         return 1
@@ -353,12 +416,25 @@
         print(json.dumps(out, indent=indent))
     return 0
 
-def run(options) -> int:
-    datadir = 'meson-private'
+def get_infodir(builddir: T.Optional[str] = None) -> str:
     infodir = 'meson-info'
+    if builddir is not None:
+        infodir = os.path.join(builddir, infodir)
+    return infodir
+
+def get_info_file(infodir: str, kind: T.Optional[str] = None) -> str:
+    return os.path.join(infodir,
+                        'meson-info.json' if not kind else f'intro-{kind}.json')
+
+def load_info_file(infodir: str, kind: T.Optional[str] = None) -> T.Any:
+    with open(get_info_file(infodir, kind), encoding='utf-8') as fp:
+        return json.load(fp)
+
+def run(options: argparse.Namespace) -> int:
+    datadir = 'meson-private'
+    infodir = get_infodir(options.builddir)
     if options.builddir is not None:
         datadir = os.path.join(options.builddir, datadir)
-        infodir = os.path.join(options.builddir, infodir)
     indent = 4 if options.indent else None
     results = []  # type: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]]
     sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11]
@@ -367,7 +443,8 @@
     if 'meson.build' in [os.path.basename(options.builddir), options.builddir]:
         # Make sure that log entries in other parts of meson don't interfere with the JSON output
         mlog.disable()
-        backend = backends.get_backend_from_name(options.backend, None)
+        backend = backends.get_backend_from_name(options.backend)
+        assert backend is not None
         intr = IntrospectionInterpreter(sourcedir, '', backend.name, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()])
         intr.analyze()
         # Re-enable logging just in case
@@ -378,17 +455,18 @@
             results += [(key, val.no_bd(intr))]
         return print_results(options, results, indent)
 
-    infofile = get_meson_info_file(infodir)
-    if not os.path.isdir(datadir) or not os.path.isdir(infodir) or not os.path.isfile(infofile):
-        print('Current directory is not a meson build directory.\n'
-              'Please specify a valid build dir or change the working directory to it.\n'
-              'It is also possible that the build directory was generated with an old\n'
-              'meson version. Please regenerate it in this case.')
-        return 1
-
-    with open(infofile, 'r') as fp:
-        raw = json.load(fp)
+    try:
+        raw = load_info_file(infodir)
         intro_vers = raw.get('introspection', {}).get('version', {}).get('full', '0.0.0')
+    except FileNotFoundError:
+        if not os.path.isdir(datadir) or not os.path.isdir(infodir):
+            print('Current directory is not a meson build directory.\n'
+                  'Please specify a valid build dir or change the working directory to it.')
+        else:
+            print('Introspection file {} does not exist.\n'
+                  'It is also possible that the build directory was generated with an old\n'
+                  'meson version. Please regenerate it in this case.'.format(get_info_file(infodir)))
+        return 1
 
     vers_to_check = get_meson_introspection_required_version()
     for i in vers_to_check:
@@ -404,12 +482,11 @@
             continue
         if not options.all and not getattr(options, i, False):
             continue
-        curr = os.path.join(infodir, 'intro-{}.json'.format(i))
-        if not os.path.isfile(curr):
-            print('Introspection file {} does not exist.'.format(curr))
+        try:
+            results += [(i, load_info_file(infodir, i))]
+        except FileNotFoundError:
+            print('Introspection file {} does not exist.'.format(get_info_file(infodir, i)))
             return 1
-        with open(curr, 'r') as fp:
-            results += [(i, json.load(fp))]
 
     return print_results(options, results, indent)
 
@@ -417,14 +494,14 @@
 
 def write_intro_info(intro_info: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], info_dir: str) -> None:
     global updated_introspection_files
-    for i in intro_info:
-        out_file = os.path.join(info_dir, 'intro-{}.json'.format(i[0]))
+    for kind, data in intro_info:
+        out_file = os.path.join(info_dir, f'intro-{kind}.json')
         tmp_file = os.path.join(info_dir, 'tmp_dump.json')
-        with open(tmp_file, 'w') as fp:
-            json.dump(i[1], fp)
+        with open(tmp_file, 'w', encoding='utf-8') as fp:
+            json.dump(data, fp)
             fp.flush() # Not sure if this is needed
         os.replace(tmp_file, out_file)
-        updated_introspection_files += [i[0]]
+        updated_introspection_files += [kind]
 
 def generate_introspection_file(builddata: build.Build, backend: backends.Backend) -> None:
     coredata = builddata.environment.get_coredata()
@@ -438,7 +515,7 @@
 
     write_intro_info(intro_info, builddata.environment.info_dir)
 
-def update_build_options(coredata: cdata.CoreData, info_dir) -> None:
+def update_build_options(coredata: cdata.CoreData, info_dir: str) -> None:
     intro_info = [
         ('buildoptions', list_buildoptions(coredata))
     ]
@@ -465,7 +542,7 @@
         if not intro_types[i].func:
             continue
         intro_info[i] = {
-            'file': 'intro-{}.json'.format(i),
+            'file': f'intro-{i}.json',
             'updated': i in updated_introspection_files
         }
 
@@ -491,7 +568,7 @@
 
     # Write the data to disc
     tmp_file = os.path.join(info_dir, 'tmp_dump.json')
-    with open(tmp_file, 'w') as fp:
+    with open(tmp_file, 'w', encoding='utf-8') as fp:
         json.dump(info_data, fp)
         fp.flush()
     os.replace(tmp_file, info_file)
diff -Nru meson-0.53.2/mesonbuild/mlog.py meson-0.61.2/mesonbuild/mlog.py
--- meson-0.53.2/mesonbuild/mlog.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/mlog.py	2022-01-02 20:12:32.000000000 +0000
@@ -21,6 +21,9 @@
 from contextlib import contextmanager
 from pathlib import Path
 
+if T.TYPE_CHECKING:
+    from ._typing import StringProtocol, SizedStringProtocol
+
 """This is (mostly) a standalone module used to write logging
 information about Meson runs. Some output goes to screen,
 some to logging dir and some goes to both."""
@@ -40,25 +43,43 @@
     # original behavior
     return bool(kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON'))
 
-def setup_console() -> bool:
+def colorize_console() -> bool:
+    _colorize_console = getattr(sys.stdout, 'colorize_console', None)  # type: bool
+    if _colorize_console is not None:
+        return _colorize_console
+
     try:
         if platform.system().lower() == 'windows':
-            return os.isatty(sys.stdout.fileno()) and _windows_ansi()
-        return os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
+            _colorize_console = os.isatty(sys.stdout.fileno()) and _windows_ansi()
+        else:
+            _colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM', 'dumb') != 'dumb'
     except Exception:
-        return False
+        _colorize_console = False
+
+    sys.stdout.colorize_console = _colorize_console  # type: ignore[attr-defined]
+    return _colorize_console
+
+def setup_console() -> None:
+    # on Windows, a subprocess might call SetConsoleMode() on the console
+    # connected to stdout and turn off ANSI escape processing. Call this after
+    # running a subprocess to ensure we turn it on again.
+    if platform.system().lower() == 'windows':
+        try:
+            delattr(sys.stdout, 'colorize_console')
+        except AttributeError:
+            pass
 
-colorize_console = setup_console()
 log_dir = None               # type: T.Optional[str]
 log_file = None              # type: T.Optional[T.TextIO]
 log_fname = 'meson-log.txt'  # type: str
-log_depth = 0                # type: int
+log_depth = []               # type: T.List[str]
 log_timestamp_start = None   # type: T.Optional[float]
 log_fatal_warnings = False   # type: bool
 log_disable_stdout = False   # type: bool
 log_errors_only = False      # type: bool
 _in_ci = 'CI' in os.environ  # type: bool
 _logged_once = set()         # type: T.Set[T.Tuple[str, ...]]
+log_warnings_counter = 0     # type: int
 
 def disable() -> None:
     global log_disable_stdout
@@ -79,7 +100,7 @@
 def initialize(logdir: str, fatal_warnings: bool = False) -> None:
     global log_dir, log_file, log_fatal_warnings
     log_dir = logdir
-    log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf8')
+    log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf-8')
     log_fatal_warnings = fatal_warnings
 
 def set_timestamp_start(start: float) -> None:
@@ -106,15 +127,38 @@
 
     def get_text(self, with_codes: bool) -> str:
         text = self.text
-        if with_codes:
+        if with_codes and self.code:
             text = self.code + self.text + AnsiDecorator.plain_code
         if self.quoted:
-            text = '"{}"'.format(text)
+            text = f'"{text}"'
         return text
 
+    def __len__(self) -> int:
+        return len(self.text)
+
+    def __str__(self) -> str:
+        return self.get_text(colorize_console())
+
+TV_Loggable = T.Union[str, AnsiDecorator, 'StringProtocol']
+TV_LoggableList = T.List[TV_Loggable]
+
+class AnsiText:
+    def __init__(self, *args: 'SizedStringProtocol'):
+        self.args = args
+
+    def __len__(self) -> int:
+        return sum(len(x) for x in self.args)
+
+    def __str__(self) -> str:
+        return ''.join(str(x) for x in self.args)
+
+
 def bold(text: str, quoted: bool = False) -> AnsiDecorator:
     return AnsiDecorator(text, "\033[1m", quoted=quoted)
 
+def plain(text: str) -> AnsiDecorator:
+    return AnsiDecorator(text, "")
+
 def red(text: str) -> AnsiDecorator:
     return AnsiDecorator(text, "\033[1;31m")
 
@@ -147,7 +191,7 @@
 
 # This really should be AnsiDecorator or anything that implements
 # __str__(), but that requires protocols from typing_extensions
-def process_markup(args: T.Sequence[T.Union[AnsiDecorator, str]], keep: bool) -> T.List[str]:
+def process_markup(args: T.Sequence[TV_Loggable], keep: bool) -> T.List[str]:
     arr = []  # type: T.List[str]
     if log_timestamp_start is not None:
         arr = ['[{:.3f}]'.format(time.monotonic() - log_timestamp_start)]
@@ -162,7 +206,7 @@
             arr.append(str(arg))
     return arr
 
-def force_print(*args: str, **kwargs: T.Any) -> None:
+def force_print(*args: str, nested: bool, **kwargs: T.Any) -> None:
     if log_disable_stdout:
         return
     iostr = io.StringIO()
@@ -170,9 +214,13 @@
     print(*args, **kwargs)
 
     raw = iostr.getvalue()
-    if log_depth > 0:
-        prepend = '|' * log_depth
-        raw = prepend + raw.replace('\n', '\n' + prepend, raw.count('\n') - 1)
+    if log_depth:
+        prepend = log_depth[-1] + '| ' if nested else ''
+        lines = []
+        for l in raw.split('\n'):
+            l = l.strip()
+            lines.append(prepend + l if l else '')
+        raw = '\n'.join(lines)
 
     # _Something_ is going to get printed.
     try:
@@ -182,7 +230,7 @@
         print(cleaned, end='')
 
 # We really want a heterogeneous dict for this, but that's in typing_extensions
-def debug(*args: T.Union[str, AnsiDecorator], **kwargs: T.Any) -> None:
+def debug(*args: TV_Loggable, **kwargs: T.Any) -> None:
     arr = process_markup(args, False)
     if log_file is not None:
         print(*arr, file=log_file, **kwargs)
@@ -191,46 +239,72 @@
 def _debug_log_cmd(cmd: str, args: T.List[str]) -> None:
     if not _in_ci:
         return
-    args = ['"{}"'.format(x) for x in args]  # Quote all args, just in case
+    args = [f'"{x}"' for x in args]  # Quote all args, just in case
     debug('!meson_ci!/{} {}'.format(cmd, ' '.join(args)))
 
 def cmd_ci_include(file: str) -> None:
     _debug_log_cmd('ci_include', [file])
 
-def log(*args: T.Union[str, AnsiDecorator], is_error: bool = False,
-        **kwargs: T.Any) -> None:
+
+def log(*args: TV_Loggable, is_error: bool = False,
+        once: bool = False, **kwargs: T.Any) -> None:
+    if once:
+        log_once(*args, is_error=is_error, **kwargs)
+    else:
+        _log(*args, is_error=is_error, **kwargs)
+
+
+def _log(*args: TV_Loggable, is_error: bool = False,
+         **kwargs: T.Any) -> None:
+    nested = kwargs.pop('nested', True)
     arr = process_markup(args, False)
     if log_file is not None:
         print(*arr, file=log_file, **kwargs)
         log_file.flush()
-    if colorize_console:
+    if colorize_console():
         arr = process_markup(args, True)
     if not log_errors_only or is_error:
-        force_print(*arr, **kwargs)
+        force_print(*arr, nested=nested, **kwargs)
 
-def log_once(*args: T.Union[str, AnsiDecorator], is_error: bool = False,
+def log_once(*args: TV_Loggable, is_error: bool = False,
              **kwargs: T.Any) -> None:
     """Log variant that only prints a given message one time per meson invocation.
 
-    This considers nasi decorated values by the values they wrap without
+    This considers ansi decorated values by the values they wrap without
     regard for the AnsiDecorator itself.
     """
-    t = tuple(a.text if isinstance(a, AnsiDecorator) else a for a in args)
+    def to_str(x: TV_Loggable) -> str:
+        if isinstance(x, str):
+            return x
+        if isinstance(x, AnsiDecorator):
+            return x.text
+        return str(x)
+    t = tuple(to_str(a) for a in args)
     if t in _logged_once:
         return
     _logged_once.add(t)
-    log(*args, is_error=is_error, **kwargs)
+    _log(*args, is_error=is_error, **kwargs)
 
-def _log_error(severity: str, *rargs: T.Union[str, AnsiDecorator],
-               once: bool = False, **kwargs: T.Any) -> None:
-    from .mesonlib import get_error_location_string
-    from .environment import build_filename
-    from .mesonlib import MesonException
+# This isn't strictly correct. What we really want here is something like:
+# class StringProtocol(typing_extensions.Protocol):
+#
+#      def __str__(self) -> str: ...
+#
+# This would more accurately embody what this function can handle, but we
+# don't have that yet, so instead we'll do some casting to work around it
+def get_error_location_string(fname: str, lineno: int) -> str:
+    return f'{fname}:{lineno}:'
+
+def _log_error(severity: str, *rargs: TV_Loggable,
+               once: bool = False, fatal: bool = True, **kwargs: T.Any) -> None:
+    from .mesonlib import MesonException, relpath
 
-    # The tping requirements here are non-obvious. Lists are invariant,
+    # The typing requirements here are non-obvious. Lists are invariant,
     # therefore T.List[A] and T.List[T.Union[A, B]] are not able to be joined
-    if severity == 'warning':
-        label = [yellow('WARNING:')]  # type: T.List[T.Union[str, AnsiDecorator]]
+    if severity == 'notice':
+        label = [bold('NOTICE:')]  # type: TV_LoggableList
+    elif severity == 'warning':
+        label = [yellow('WARNING:')]
     elif severity == 'error':
         label = [red('ERROR:')]
     elif severity == 'deprecation':
@@ -242,29 +316,32 @@
 
     location = kwargs.pop('location', None)
     if location is not None:
-        location_file = os.path.join(location.subdir, build_filename)
+        location_file = relpath(location.filename, os.getcwd())
         location_str = get_error_location_string(location_file, location.lineno)
         # Unions are frankly awful, and we have to T.cast here to get mypy
         # to understand that the list concatenation is safe
-        location_list = T.cast(T.List[T.Union[str, AnsiDecorator]], [location_str])
+        location_list = T.cast(TV_LoggableList, [location_str])
         args = location_list + args
 
-    if once:
-        log_once(*args, **kwargs)
-    else:
-        log(*args, **kwargs)
+    log(*args, once=once, **kwargs)
+
+    global log_warnings_counter
+    log_warnings_counter += 1
 
-    if log_fatal_warnings:
+    if log_fatal_warnings and fatal:
         raise MesonException("Fatal warnings enabled, aborting")
 
-def error(*args: T.Union[str, AnsiDecorator], once: bool = False, **kwargs: T.Any) -> None:
-    return _log_error('error', *args, **kwargs, is_error=True, once=once)
+def error(*args: TV_Loggable, **kwargs: T.Any) -> None:
+    return _log_error('error', *args, **kwargs, is_error=True)
+
+def warning(*args: TV_Loggable, **kwargs: T.Any) -> None:
+    return _log_error('warning', *args, **kwargs, is_error=True)
 
-def warning(*args: T.Union[str, AnsiDecorator], once: bool = False, **kwargs: T.Any) -> None:
-    return _log_error('warning', *args, **kwargs, is_error=True, once=once)
+def deprecation(*args: TV_Loggable, **kwargs: T.Any) -> None:
+    return _log_error('deprecation', *args, **kwargs, is_error=True)
 
-def deprecation(*args: T.Union[str, AnsiDecorator], once: bool = False, **kwargs: T.Any) -> None:
-    return _log_error('deprecation', *args, **kwargs, is_error=True, once=once)
+def notice(*args: TV_Loggable, **kwargs: T.Any) -> None:
+    return _log_error('notice', *args, **kwargs, is_error=False)
 
 def get_relative_path(target: Path, current: Path) -> Path:
     """Get the path to target from current"""
@@ -286,11 +363,11 @@
         prefix = red('ERROR:')
     log()
     args = []  # type: T.List[T.Union[AnsiDecorator, str]]
-    if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'):
-        # Mypy can't figure this out, and it's pretty easy to vidual inspect
+    if all(getattr(e, a, None) is not None for a in ['file', 'lineno', 'colno']):
+        # Mypy doesn't follow hasattr, and it's pretty easy to visually inspect
         # that this is correct, so we'll just ignore it.
-        path = get_relative_path(Path(e.file), Path(os.getcwd()))
-        args.append('%s:%d:%d:' % (path, e.lineno, e.colno))  # type: ignore
+        path = get_relative_path(Path(e.file), Path(os.getcwd()))  # type: ignore
+        args.append(f'{path}:{e.lineno}:{e.colno}:')  # type: ignore
     if prefix:
         args.append(prefix)
     args.append(str(e))
@@ -310,10 +387,10 @@
         return ''
 
 @contextmanager
-def nested() -> T.Generator[None, None, None]:
+def nested(name: str = '') -> T.Generator[None, None, None]:
     global log_depth
-    log_depth += 1
+    log_depth.append(name)
     try:
         yield
     finally:
-        log_depth -= 1
+        log_depth.pop()
diff -Nru meson-0.53.2/mesonbuild/modules/cmake.py meson-0.61.2/mesonbuild/modules/cmake.py
--- meson-0.53.2/mesonbuild/modules/cmake.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/cmake.py	2022-01-02 20:12:32.000000000 +0000
@@ -14,12 +14,26 @@
 import re
 import os, os.path, pathlib
 import shutil
+import typing as T
 
-from . import ExtensionModule, ModuleReturnValue
+from . import ExtensionModule, ModuleReturnValue, ModuleObject
 
-from .. import build, dependencies, mesonlib, mlog
-from ..interpreterbase import permittedKwargs, FeatureNew, stringArgs, InterpreterObject, ObjectHolder, noPosargs
-from ..interpreter import ConfigurationDataHolder, InterpreterException, SubprojectHolder
+from .. import build, mesonlib, mlog, dependencies
+from ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args
+from ..interpreter import ConfigurationDataObject, SubprojectHolder
+from ..interpreterbase import (
+    FeatureNew,
+    FeatureNewKwargs,
+    FeatureDeprecatedKwargs,
+
+    stringArgs,
+    permittedKwargs,
+    noPosargs,
+    noKwargs,
+
+    InvalidArguments,
+    InterpreterException,
+)
 
 
 COMPATIBILITIES = ['AnyNewerVersion', 'SameMajorVersion', 'SameMinorVersion', 'ExactVersion']
@@ -54,12 +68,12 @@
 ####################################################################################
 '''
 
-class CMakeSubprojectHolder(InterpreterObject, ObjectHolder):
+class CMakeSubproject(ModuleObject):
     def __init__(self, subp, pv):
-        assert(isinstance(subp, SubprojectHolder))
-        assert(hasattr(subp, 'cm_interpreter'))
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, subp, pv)
+        assert isinstance(subp, SubprojectHolder)
+        assert hasattr(subp, 'cm_interpreter')
+        super().__init__()
+        self.subp = subp
         self.methods.update({'get_variable': self.get_variable,
                              'dependency': self.dependency,
                              'include_directories': self.include_directories,
@@ -74,58 +88,139 @@
             raise InterpreterException('Exactly one argument is required.')
 
         tgt = args[0]
-        res = self.held_object.cm_interpreter.target_info(tgt)
+        res = self.subp.cm_interpreter.target_info(tgt)
         if res is None:
-            raise InterpreterException('The CMake target {} does not exist'.format(tgt))
+            raise InterpreterException(f'The CMake target {tgt} does not exist\n' +
+                                       '  Use the following command in your meson.build to list all available targets:\n\n' +
+                                       '    message(\'CMaket targets:\\n - \' + \'\\n - \'.join(.target_list()))')
 
         # Make sure that all keys are present (if not this is a bug)
-        assert(all([x in res for x in ['inc', 'src', 'dep', 'tgt', 'func']]))
+        assert all([x in res for x in ['inc', 'src', 'dep', 'tgt', 'func']])
         return res
 
-    @permittedKwargs({})
-    def get_variable(self, args, kwargs):
-        return self.held_object.get_variable_method(args, kwargs)
+    @noKwargs
+    @stringArgs
+    def get_variable(self, state, args, kwargs):
+        return self.subp.get_variable_method(args, kwargs)
 
-    @permittedKwargs({})
-    def dependency(self, args, kwargs):
+    @FeatureNewKwargs('dependency', '0.56.0', ['include_type'])
+    @permittedKwargs({'include_type'})
+    @stringArgs
+    def dependency(self, state, args, kwargs):
         info = self._args_to_info(args)
-        return self.get_variable([info['dep']], kwargs)
+        if info['func'] == 'executable':
+            raise InvalidArguments(f'{args[0]} is an executable and does not support the dependency() method. Use target() instead.')
+        orig = self.get_variable(state, [info['dep']], {})
+        assert isinstance(orig, dependencies.Dependency)
+        actual = orig.include_type
+        if 'include_type' in kwargs and kwargs['include_type'] != actual:
+            mlog.debug('Current include type is {}. Converting to requested {}'.format(actual, kwargs['include_type']))
+            return orig.generate_system_dependency(kwargs['include_type'])
+        return orig
 
-    @permittedKwargs({})
-    def include_directories(self, args, kwargs):
+    @noKwargs
+    @stringArgs
+    def include_directories(self, state, args, kwargs):
         info = self._args_to_info(args)
-        return self.get_variable([info['inc']], kwargs)
+        return self.get_variable(state, [info['inc']], kwargs)
 
-    @permittedKwargs({})
-    def target(self, args, kwargs):
+    @noKwargs
+    @stringArgs
+    def target(self, state, args, kwargs):
         info = self._args_to_info(args)
-        return self.get_variable([info['tgt']], kwargs)
+        return self.get_variable(state, [info['tgt']], kwargs)
 
-    @permittedKwargs({})
-    def target_type(self, args, kwargs):
+    @noKwargs
+    @stringArgs
+    def target_type(self, state, args, kwargs):
         info = self._args_to_info(args)
         return info['func']
 
     @noPosargs
-    @permittedKwargs({})
-    def target_list(self, args, kwargs):
-        return self.held_object.cm_interpreter.target_list()
+    @noKwargs
+    def target_list(self, state, args, kwargs):
+        return self.subp.cm_interpreter.target_list()
 
     @noPosargs
-    @permittedKwargs({})
+    @noKwargs
     @FeatureNew('CMakeSubproject.found()', '0.53.2')
-    def found_method(self, args, kwargs):
-        return self.held_object is not None
+    def found_method(self, state, args, kwargs):
+        return self.subp is not None
+
+
+class CMakeSubprojectOptions(ModuleObject):
+    def __init__(self) -> None:
+        super().__init__()
+        self.cmake_options = []  # type: T.List[str]
+        self.target_options = TargetOptions()
+
+        self.methods.update(
+            {
+                'add_cmake_defines': self.add_cmake_defines,
+                'set_override_option': self.set_override_option,
+                'set_install': self.set_install,
+                'append_compile_args': self.append_compile_args,
+                'append_link_args': self.append_link_args,
+                'clear': self.clear,
+            }
+        )
+
+    def _get_opts(self, kwargs: dict) -> SingleTargetOptions:
+        if 'target' in kwargs:
+            return self.target_options[kwargs['target']]
+        return self.target_options.global_options
+
+    @noKwargs
+    def add_cmake_defines(self, state, args, kwargs) -> None:
+        self.cmake_options += cmake_defines_to_args(args)
+
+    @stringArgs
+    @permittedKwargs({'target'})
+    def set_override_option(self, state, args, kwargs) -> None:
+        if len(args) != 2:
+            raise InvalidArguments('set_override_option takes exactly 2 positional arguments')
+        self._get_opts(kwargs).set_opt(args[0], args[1])
+
+    @permittedKwargs({'target'})
+    def set_install(self, state, args, kwargs) -> None:
+        if len(args) != 1 or not isinstance(args[0], bool):
+            raise InvalidArguments('set_install takes exactly 1 boolean argument')
+        self._get_opts(kwargs).set_install(args[0])
+
+    @stringArgs
+    @permittedKwargs({'target'})
+    def append_compile_args(self, state, args, kwargs) -> None:
+        if len(args) < 2:
+            raise InvalidArguments('append_compile_args takes at least 2 positional arguments')
+        self._get_opts(kwargs).append_args(args[0], args[1:])
+
+    @stringArgs
+    @permittedKwargs({'target'})
+    def append_link_args(self, state, args, kwargs) -> None:
+        if not args:
+            raise InvalidArguments('append_link_args takes at least 1 positional argument')
+        self._get_opts(kwargs).append_link_args(args)
+
+    @noPosargs
+    @noKwargs
+    def clear(self, state, args, kwargs) -> None:
+        self.cmake_options.clear()
+        self.target_options = TargetOptions()
 
 
 class CmakeModule(ExtensionModule):
     cmake_detected = False
     cmake_root = None
 
+    @FeatureNew('CMake Module', '0.50.0')
     def __init__(self, interpreter):
         super().__init__(interpreter)
-        self.snippets.add('configure_package_config_file')
-        self.snippets.add('subproject')
+        self.methods.update({
+            'write_basic_package_version_file': self.write_basic_package_version_file,
+            'configure_package_config_file': self.configure_package_config_file,
+            'subproject': self.subproject,
+            'subproject_options': self.subproject_options,
+        })
 
     def detect_voidp_size(self, env):
         compilers = env.coredata.compilers.host
@@ -138,14 +233,17 @@
 
         return compiler.sizeof('void *', '', env)
 
-    def detect_cmake(self):
+    def detect_cmake(self, state):
         if self.cmake_detected:
             return True
 
-        cmakebin = dependencies.ExternalProgram('cmake', silent=False)
+        cmakebin = state.find_program('cmake', silent=False)
+        if not cmakebin.found():
+            return False
+
         p, stdout, stderr = mesonlib.Popen_safe(cmakebin.get_command() + ['--system-information', '-G', 'Ninja'])[0:3]
         if p.returncode != 0:
-            mlog.log('error retrieving cmake information: returnCode={0} stdout={1} stderr={2}'.format(p.returncode, stdout, stderr))
+            mlog.log(f'error retrieving cmake information: returnCode={p.returncode} stdout={stdout} stderr={stderr}')
             return False
 
         match = re.search('\nCMAKE_ROOT \\"([^"]+)"\n', stdout.strip())
@@ -174,20 +272,21 @@
         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 = kwargs.get('install_dir', None)
+        pkgroot = pkgroot_name = kwargs.get('install_dir', None)
         if pkgroot is None:
-            pkgroot = os.path.join(state.environment.coredata.get_builtin_option('libdir'), 'cmake', name)
+            pkgroot = os.path.join(state.environment.coredata.get_option(mesonlib.OptionKey('libdir')), 'cmake', name)
+            pkgroot_name = os.path.join('{libdir}', 'cmake', name)
         if not isinstance(pkgroot, str):
             raise mesonlib.MesonException('Install_dir must be a string.')
 
-        template_file = os.path.join(self.cmake_root, 'Modules', 'BasicConfigVersion-{}.cmake.in'.format(compatibility))
+        template_file = os.path.join(self.cmake_root, 'Modules', f'BasicConfigVersion-{compatibility}.cmake.in')
         if not os.path.exists(template_file):
-            raise mesonlib.MesonException('your cmake installation doesn\'t support the {} compatibility'.format(compatibility))
+            raise mesonlib.MesonException(f'your cmake installation doesn\'t support the {compatibility} compatibility')
 
-        version_file = os.path.join(state.environment.scratch_dir, '{}ConfigVersion.cmake'.format(name))
+        version_file = os.path.join(state.environment.scratch_dir, f'{name}ConfigVersion.cmake')
 
         conf = {
             'CVF_VERSION': (version, ''),
@@ -195,26 +294,26 @@
         }
         mesonlib.do_conf_file(template_file, version_file, conf, 'meson')
 
-        res = build.Data(mesonlib.File(True, state.environment.get_scratch_dir(), version_file), pkgroot)
+        res = build.Data([mesonlib.File(True, state.environment.get_scratch_dir(), version_file)], pkgroot, pkgroot_name, None, state.subproject)
         return ModuleReturnValue(res, [res])
 
     def create_package_file(self, infile, outfile, PACKAGE_RELATIVE_PATH, extra, confdata):
         package_init = PACKAGE_INIT_BASE.replace('@PACKAGE_RELATIVE_PATH@', PACKAGE_RELATIVE_PATH)
-        package_init = package_init.replace('@inputFileName@', infile)
+        package_init = package_init.replace('@inputFileName@', os.path.basename(infile))
         package_init += extra
         package_init += PACKAGE_INIT_SET_AND_CHECK
 
         try:
-            with open(infile, "r") as fin:
+            with open(infile, encoding='utf-8') as fin:
                 data = fin.readlines()
         except Exception as e:
-            raise mesonlib.MesonException('Could not read input file %s: %s' % (infile, str(e)))
+            raise mesonlib.MesonException(f'Could not read input file {infile}: {e!s}')
 
         result = []
-        regex = re.compile(r'(?:\\\\)+(?=\\?@)|\\@|@([-a-zA-Z0-9_]+)@')
+        regex = mesonlib.get_variable_regex('cmake@')
         for line in data:
             line = line.replace('@PACKAGE_INIT@', package_init)
-            line, _missing = mesonlib.do_replacement(regex, line, 'meson', confdata)
+            line, _missing = mesonlib.do_replacement(regex, line, 'cmake@', confdata)
 
             result.append(line)
 
@@ -226,7 +325,7 @@
         mesonlib.replace_if_different(outfile, outfile_tmp)
 
     @permittedKwargs({'input', 'name', 'install_dir', 'configuration'})
-    def configure_package_config_file(self, interpreter, state, args, kwargs):
+    def configure_package_config_file(self, state, args, kwargs):
         if args:
             raise mesonlib.MesonException('configure_package_config_file takes only keyword arguments.')
 
@@ -249,21 +348,20 @@
             raise mesonlib.MesonException('"name" not specified.')
         name = kwargs['name']
 
-        (ofile_path, ofile_fname) = os.path.split(os.path.join(state.subdir, '{}Config.cmake'.format(name)))
+        (ofile_path, ofile_fname) = os.path.split(os.path.join(state.subdir, f'{name}Config.cmake'))
         ofile_abs = os.path.join(state.environment.build_dir, ofile_path, ofile_fname)
 
-        if 'install_dir' not in kwargs:
-            install_dir = os.path.join(state.environment.coredata.get_builtin_option('libdir'), 'cmake', name)
+        install_dir = kwargs.get('install_dir', os.path.join(state.environment.coredata.get_option(mesonlib.OptionKey('libdir')), 'cmake', name))
         if not isinstance(install_dir, str):
             raise mesonlib.MesonException('"install_dir" must be a string.')
 
         if 'configuration' not in kwargs:
             raise mesonlib.MesonException('"configuration" not specified.')
         conf = kwargs['configuration']
-        if not isinstance(conf, ConfigurationDataHolder):
+        if not isinstance(conf, ConfigurationDataObject):
             raise mesonlib.MesonException('Argument "configuration" is not of type configuration_data')
 
-        prefix = state.environment.coredata.get_builtin_option('prefix')
+        prefix = state.environment.coredata.get_option(mesonlib.OptionKey('prefix'))
         abs_install_dir = install_dir
         if not os.path.isabs(abs_install_dir):
             abs_install_dir = os.path.join(prefix, install_dir)
@@ -274,29 +372,39 @@
             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.held_object)
+        self.create_package_file(ifile_abs, ofile_abs, PACKAGE_RELATIVE_PATH, extra, conf.conf_data)
         conf.mark_used()
 
         conffile = os.path.normpath(inputfile.relative_name())
-        if conffile not in interpreter.build_def_files:
-            interpreter.build_def_files.append(conffile)
+        if conffile not in self.interpreter.build_def_files:
+            self.interpreter.build_def_files.append(conffile)
 
-        res = build.Data(mesonlib.File(True, ofile_path, ofile_fname), install_dir)
-        interpreter.build.data.append(res)
+        res = build.Data([mesonlib.File(True, ofile_path, ofile_fname)], install_dir, install_dir, None, state.subproject)
+        self.interpreter.build.data.append(res)
 
         return res
 
     @FeatureNew('subproject', '0.51.0')
-    @permittedKwargs({'cmake_options', 'required'})
+    @FeatureNewKwargs('subproject', '0.55.0', ['options'])
+    @FeatureDeprecatedKwargs('subproject', '0.55.0', ['cmake_options'])
+    @permittedKwargs({'cmake_options', 'required', 'options'})
     @stringArgs
-    def subproject(self, interpreter, state, args, kwargs):
+    def subproject(self, state, args, kwargs):
         if len(args) != 1:
             raise InterpreterException('Subproject takes exactly one argument')
+        if 'cmake_options' in kwargs and 'options' in kwargs:
+            raise InterpreterException('"options" cannot be used together with "cmake_options"')
         dirname = args[0]
-        subp = interpreter.do_subproject(dirname, 'cmake', kwargs)
-        if not subp.held_object:
+        subp = self.interpreter.do_subproject(dirname, 'cmake', kwargs)
+        if not subp.found():
             return subp
-        return CMakeSubprojectHolder(subp, dirname)
+        return CMakeSubproject(subp, dirname)
+
+    @FeatureNew('subproject_options', '0.55.0')
+    @noKwargs
+    @noPosargs
+    def subproject_options(self, state, args, kwargs) -> CMakeSubprojectOptions:
+        return CMakeSubprojectOptions()
 
 def initialize(*args, **kwargs):
     return CmakeModule(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/dlang.py meson-0.61.2/mesonbuild/modules/dlang.py
--- meson-0.53.2/mesonbuild/modules/dlang.py	2018-10-31 09:31:20.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/dlang.py	2022-01-02 20:12:32.000000000 +0000
@@ -19,36 +19,31 @@
 import os
 
 from . import ExtensionModule
-
+from .. import dependencies
 from .. import mlog
-
-from ..mesonlib import (
-    Popen_safe, MesonException
-)
-
-from ..dependencies.base import (
-    ExternalProgram, DubDependency
-)
-
-from ..interpreter import DependencyHolder
+from ..interpreterbase import FeatureNew
+from ..mesonlib import Popen_safe, MesonException
 
 class DlangModule(ExtensionModule):
     class_dubbin = None
     init_dub = False
 
+    @FeatureNew('Dlang Module', '0.48.0')
     def __init__(self, interpreter):
         super().__init__(interpreter)
-        self.snippets.add('generate_dub_file')
+        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 = DubDependency.class_dubbin
+            self.dubbin = dependencies.DubDependency.class_dubbin
             DlangModule.class_dubbin = self.dubbin
         else:
             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
@@ -57,9 +52,9 @@
             if not self.dubbin:
                 raise MesonException('DUB not found.')
 
-    def generate_dub_file(self, interpreter, state, args, kwargs):
+    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')
@@ -70,7 +65,7 @@
 
         config_path = os.path.join(args[1], 'dub.json')
         if os.path.exists(config_path):
-            with open(config_path, 'r', encoding='utf8') as ofile:
+            with open(config_path, encoding='utf-8') as ofile:
                 try:
                     config = json.load(ofile)
                 except ValueError:
@@ -87,20 +82,20 @@
                 config[key] = {}
                 if isinstance(value, list):
                     for dep in value:
-                        if isinstance(dep, DependencyHolder):
-                            name = dep.method_call('name', [], [])
+                        if isinstance(dep, dependencies.Dependency):
+                            name = dep.get_name()
                             ret, res = self._call_dubbin(['describe', name])
                             if ret == 0:
-                                version = dep.method_call('version', [], [])
+                                version = dep.get_version()
                                 if version is None:
                                     config[key][name] = ''
                                 else:
                                     config[key][name] = version
-                elif isinstance(value, DependencyHolder):
-                    name = value.method_call('name', [], [])
+                elif isinstance(value, dependencies.Dependency):
+                    name = value.get_name()
                     ret, res = self._call_dubbin(['describe', name])
                     if ret == 0:
-                        version = value.method_call('version', [], [])
+                        version = value.get_version()
                         if version is None:
                             config[key][name] = ''
                         else:
@@ -108,15 +103,15 @@
             else:
                 config[key] = value
 
-        with open(config_path, 'w', encoding='utf8') as ofile:
+        with open(config_path, 'w', encoding='utf-8') as ofile:
             ofile.write(json.dumps(config, indent=4, ensure_ascii=False))
 
     def _call_dubbin(self, args, env=None):
         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 -Nru meson-0.53.2/mesonbuild/modules/fs.py meson-0.61.2/mesonbuild/modules/fs.py
--- meson-0.53.2/mesonbuild/modules/fs.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/fs.py	2022-01-02 20:12:32.000000000 +0000
@@ -14,127 +14,246 @@
 
 import typing as T
 import hashlib
-from pathlib import Path, PurePath
+import os
+from pathlib import Path, PurePath, PureWindowsPath
 
 from .. import mlog
 from . import ExtensionModule
-from . import ModuleReturnValue
-from ..mesonlib import MesonException
+from ..mesonlib import (
+    File,
+    FileOrString,
+    MesonException,
+    path_is_in_root,
+)
+from ..interpreterbase import FeatureNew, KwargInfo, typed_kwargs, typed_pos_args, noKwargs
 
-from ..interpreterbase import stringArgs, noKwargs
 if T.TYPE_CHECKING:
-    from ..interpreter import ModuleState
+    from . import ModuleState
+    from ..interpreter import Interpreter
+
+    from typing_extensions import TypedDict
+
+    class ReadKwArgs(TypedDict):
+        """Keyword Arguments for fs.read."""
+
+        encoding: str
+
 
 class FSModule(ExtensionModule):
 
-    def __init__(self, interpreter):
+    @FeatureNew('Fs Module', '0.53.0')
+    def __init__(self, interpreter: 'Interpreter') -> None:
         super().__init__(interpreter)
-        self.snippets.add('generate_dub_file')
+        self.methods.update({
+            'expanduser': self.expanduser,
+            'is_absolute': self.is_absolute,
+            'as_posix': self.as_posix,
+            'exists': self.exists,
+            'is_symlink': self.is_symlink,
+            'is_file': self.is_file,
+            'is_dir': self.is_dir,
+            'hash': self.hash,
+            'size': self.size,
+            'is_samepath': self.is_samepath,
+            'replace_suffix': self.replace_suffix,
+            'parent': self.parent,
+            'name': self.name,
+            'stem': self.stem,
+            'read': self.read,
+        })
 
-    def _resolve_dir(self, state: 'ModuleState', arg: str) -> Path:
+    def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path:
         """
-        resolves (makes absolute) a directory relative to calling meson.build,
-        if not already absolute
+        make an absolute path from a relative path, WITHOUT resolving symlinks
         """
-        return Path(state.source_root) / state.subdir / Path(arg).expanduser()
+        if isinstance(arg, File):
+            return Path(arg.absolute_path(state.source_root, self.interpreter.environment.get_build_dir()))
+        return Path(state.source_root) / Path(state.subdir) / Path(arg).expanduser()
 
-    def _check(self, check: str, state: 'ModuleState', args: T.Sequence[str]) -> ModuleReturnValue:
-        if len(args) != 1:
-            raise MesonException('fs.{} takes exactly one argument.'.format(check))
-        test_file = self._resolve_dir(state, args[0])
-        return ModuleReturnValue(getattr(test_file, check)(), [])
+    def _resolve_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path:
+        """
+        resolves symlinks and makes absolute a directory relative to calling meson.build,
+        if not already absolute
+        """
+        path = self._absolute_dir(state, arg)
+        try:
+            # accommodate unresolvable paths e.g. symlink loops
+            path = path.resolve()
+        except Exception:
+            # return the best we could do
+            pass
+        return path
+
+    @noKwargs
+    @FeatureNew('fs.expanduser', '0.54.0')
+    @typed_pos_args('fs.expanduser', str)
+    def expanduser(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str:
+        return str(Path(args[0]).expanduser())
+
+    @noKwargs
+    @FeatureNew('fs.is_absolute', '0.54.0')
+    @typed_pos_args('fs.is_absolute', (str, File))
+    def is_absolute(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool:
+        if isinstance(args[0], File):
+            FeatureNew('fs.is_absolute_file', '0.59.0').use(state.subproject)
+        return PurePath(str(args[0])).is_absolute()
+
+    @noKwargs
+    @FeatureNew('fs.as_posix', '0.54.0')
+    @typed_pos_args('fs.as_posix', str)
+    def as_posix(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str:
+        """
+        this function assumes you are passing a Windows path, even if on a Unix-like system
+        and so ALL '\' are turned to '/', even if you meant to escape a character
+        """
+        return PureWindowsPath(args[0]).as_posix()
 
-    @stringArgs
     @noKwargs
-    def exists(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        return self._check('exists', state, args)
+    @typed_pos_args('fs.exists', str)
+    def exists(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool:
+        return self._resolve_dir(state, args[0]).exists()
 
-    @stringArgs
     @noKwargs
-    def is_symlink(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        return self._check('is_symlink', state, args)
+    @typed_pos_args('fs.is_symlink', (str, File))
+    def is_symlink(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool:
+        if isinstance(args[0], File):
+            FeatureNew('fs.is_symlink_file', '0.59.0').use(state.subproject)
+        return self._absolute_dir(state, args[0]).is_symlink()
 
-    @stringArgs
     @noKwargs
-    def is_file(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        return self._check('is_file', state, args)
+    @typed_pos_args('fs.is_file', str)
+    def is_file(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool:
+        return self._resolve_dir(state, args[0]).is_file()
 
-    @stringArgs
     @noKwargs
-    def is_dir(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        return self._check('is_dir', state, args)
+    @typed_pos_args('fs.is_dir', str)
+    def is_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool:
+        return self._resolve_dir(state, args[0]).is_dir()
 
-    @stringArgs
     @noKwargs
-    def hash(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        if len(args) != 2:
-            raise MesonException('method takes exactly two arguments.')
+    @typed_pos_args('fs.hash', (str, File), str)
+    def hash(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str:
+        if isinstance(args[0], File):
+            FeatureNew('fs.hash_file', '0.59.0').use(state.subproject)
         file = self._resolve_dir(state, args[0])
         if not file.is_file():
-            raise MesonException('{} is not a file and therefore cannot be hashed'.format(file))
+            raise MesonException(f'{file} is not a file and therefore cannot be hashed')
         try:
             h = hashlib.new(args[1])
         except ValueError:
             raise MesonException('hash algorithm {} is not available'.format(args[1]))
         mlog.debug('computing {} sum of {} size {} bytes'.format(args[1], file, file.stat().st_size))
         h.update(file.read_bytes())
-        return ModuleReturnValue(h.hexdigest(), [])
+        return h.hexdigest()
 
-    @stringArgs
     @noKwargs
-    def size(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        if len(args) != 1:
-            raise MesonException('method takes exactly one argument.')
+    @typed_pos_args('fs.size', (str, File))
+    def size(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> int:
+        if isinstance(args[0], File):
+            FeatureNew('fs.size_file', '0.59.0').use(state.subproject)
         file = self._resolve_dir(state, args[0])
         if not file.is_file():
-            raise MesonException('{} is not a file and therefore cannot be sized'.format(file))
+            raise MesonException(f'{file} is not a file and therefore cannot be sized')
         try:
-            return ModuleReturnValue(file.stat().st_size, [])
+            return file.stat().st_size
         except ValueError:
             raise MesonException('{} size could not be determined'.format(args[0]))
 
-    @stringArgs
     @noKwargs
-    def is_samepath(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        if len(args) != 2:
-            raise MesonException('fs.is_samepath takes exactly two arguments.')
+    @typed_pos_args('fs.is_samepath', (str, File), (str, File))
+    def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool:
+        if isinstance(args[0], File) or isinstance(args[1], File):
+            FeatureNew('fs.is_samepath_file', '0.59.0').use(state.subproject)
         file1 = self._resolve_dir(state, args[0])
         file2 = self._resolve_dir(state, args[1])
         if not file1.exists():
-            return ModuleReturnValue(False, [])
+            return False
         if not file2.exists():
-            return ModuleReturnValue(False, [])
+            return False
         try:
-            return ModuleReturnValue(file1.samefile(file2), [])
+            return file1.samefile(file2)
         except OSError:
-            return ModuleReturnValue(False, [])
+            return False
 
-    @stringArgs
     @noKwargs
-    def replace_suffix(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        if len(args) != 2:
-            raise MesonException('method takes exactly two arguments.')
-        original = PurePath(args[0])
+    @typed_pos_args('fs.replace_suffix', (str, File), str)
+    def replace_suffix(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str:
+        if isinstance(args[0], File):
+            FeatureNew('fs.replace_suffix_file', '0.59.0').use(state.subproject)
+        original = PurePath(str(args[0]))
         new = original.with_suffix(args[1])
-        return ModuleReturnValue(str(new), [])
+        return str(new)
 
-    @stringArgs
     @noKwargs
-    def parent(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        if len(args) != 1:
-            raise MesonException('method takes exactly one argument.')
-        original = PurePath(args[0])
+    @typed_pos_args('fs.parent', (str, File))
+    def parent(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str:
+        if isinstance(args[0], File):
+            FeatureNew('fs.parent_file', '0.59.0').use(state.subproject)
+        original = PurePath(str(args[0]))
         new = original.parent
-        return ModuleReturnValue(str(new), [])
+        return str(new)
 
-    @stringArgs
     @noKwargs
-    def name(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
-        if len(args) != 1:
-            raise MesonException('method takes exactly one argument.')
-        original = PurePath(args[0])
+    @typed_pos_args('fs.name', (str, File))
+    def name(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str:
+        if isinstance(args[0], File):
+            FeatureNew('fs.name_file', '0.59.0').use(state.subproject)
+        original = PurePath(str(args[0]))
         new = original.name
-        return ModuleReturnValue(str(new), [])
+        return str(new)
+
+    @noKwargs
+    @typed_pos_args('fs.stem', (str, File))
+    @FeatureNew('fs.stem', '0.54.0')
+    def stem(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str:
+        if isinstance(args[0], File):
+            FeatureNew('fs.stem_file', '0.59.0').use(state.subproject)
+        original = PurePath(str(args[0]))
+        new = original.stem
+        return str(new)
+
+    @FeatureNew('fs.read', '0.57.0')
+    @typed_pos_args('fs.read', (str, File))
+    @typed_kwargs('fs.read', KwargInfo('encoding', str, default='utf-8'))
+    def read(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: 'ReadKwArgs') -> str:
+        """Read a file from the source tree and return its value as a decoded
+        string.
+
+        If the encoding is not specified, the file is assumed to be utf-8
+        encoded. Paths must be relative by default (to prevent accidents) and
+        are forbidden to be read from the build directory (to prevent build
+        loops)
+        """
+        path = args[0]
+        encoding = kwargs['encoding']
+        src_dir = self.interpreter.environment.source_dir
+        sub_dir = self.interpreter.subdir
+        build_dir = self.interpreter.environment.get_build_dir()
+
+        if isinstance(path, File):
+            if path.is_built:
+                raise MesonException(
+                    'fs.read_file does not accept built files() objects')
+            path = os.path.join(src_dir, path.relative_name())
+        else:
+            if sub_dir:
+                src_dir = os.path.join(src_dir, sub_dir)
+            path = os.path.join(src_dir, path)
+
+        path = os.path.abspath(path)
+        if path_is_in_root(Path(path), Path(build_dir), resolve=True):
+            raise MesonException('path must not be in the build tree')
+        try:
+            with open(path, encoding=encoding) as f:
+                data = f.read()
+        except UnicodeDecodeError:
+            raise MesonException(f'decoding failed for {path}')
+        # Reconfigure when this file changes as it can contain data used by any
+        # part of the build configuration (e.g. `project(..., version:
+        # fs.read_file('VERSION')` or `configure_file(...)`
+        self.interpreter.add_build_def_file(path)
+        return data
+
 
-def initialize(*args, **kwargs) -> FSModule:
+def initialize(*args: T.Any, **kwargs: T.Any) -> FSModule:
     return FSModule(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/gnome.py meson-0.61.2/mesonbuild/modules/gnome.py
--- meson-0.53.2/mesonbuild/modules/gnome.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/gnome.py	2022-02-14 19:03:13.000000000 +0000
@@ -15,24 +15,234 @@
 '''This module provides helper functions for Gnome/GLib related
 functionality such as gobject-introspection, gresources and gtk-doc'''
 
-import os
 import copy
-import subprocess
 import functools
+import os
+import subprocess
+import textwrap
+import typing as T
 
-from .. import build
-from .. import mlog
-from .. import mesonlib
-from .. import interpreter
-from . import GResourceTarget, GResourceHeaderTarget, GirTarget, TypelibTarget, VapiTarget
-from . import get_include_args
 from . import ExtensionModule
+from . import GResourceTarget, GResourceHeaderTarget, GirTarget, TypelibTarget, VapiTarget
 from . import ModuleReturnValue
+from .. import build
+from .. import interpreter
+from .. import mesonlib
+from .. import mlog
+from ..build import BuildTarget, CustomTarget, CustomTargetIndex, 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, FeatureNew, FeatureDeprecated
+from ..interpreterbase import typed_kwargs, KwargInfo, ContainerTypeInfo
+from ..interpreterbase.decorators import typed_pos_args
 from ..mesonlib import (
-    MachineChoice, MesonException, OrderedSet, Popen_safe, extract_as_list, join_args
+    MachineChoice, MesonException, OrderedSet, Popen_safe, join_args,
 )
-from ..dependencies import Dependency, PkgConfigDependency, InternalDependency
-from ..interpreterbase import noKwargs, permittedKwargs, FeatureNew, FeatureNewKwargs
+from ..programs import ExternalProgram, OverrideProgram, EmptyExternalProgram
+from ..scripts.gettext import read_linguas
+
+if T.TYPE_CHECKING:
+    from typing_extensions import Literal, TypedDict
+
+    from . import ModuleState
+    from ..compilers import Compiler
+    from ..interpreter import Interpreter
+    from ..interpreterbase import TYPE_var, TYPE_kwargs
+    from ..mesonlib import FileOrString
+
+    class PostInstall(TypedDict):
+        glib_compile_schemas: bool
+        gio_querymodules: T.List[str]
+        gtk_update_icon_cache: bool
+        update_desktop_database: bool
+
+    class CompileSchemas(TypedDict):
+
+        build_by_default: bool
+        depend_files: T.List[FileOrString]
+
+    class Yelp(TypedDict):
+
+        languages: T.List[str]
+        media: T.List[str]
+        sources: T.List[str]
+        symlink_media: bool
+
+    class CompileResources(TypedDict):
+
+        build_by_default: bool
+        c_name: T.Optional[str]
+        dependencies: T.List[T.Union[mesonlib.File, build.CustomTarget, build.CustomTargetIndex]]
+        export: bool
+        extra_args: T.List[str]
+        gresource_bundle: bool
+        install: bool
+        install_dir: T.Optional[str]
+        install_header: bool
+        source_dir: T.List[str]
+
+    class GenerateGir(TypedDict):
+
+        build_by_default: bool
+        dependencies: T.List[Dependency]
+        export_packages: T.List[str]
+        extra_args: T.List[str]
+        fatal_warnings: bool
+        header: T.List[str]
+        identifier_prefix: T.List[str]
+        include_directories: T.List[T.Union[build.IncludeDirs, str]]
+        includes: T.List[T.Union[str, GirTarget]]
+        install: bool
+        install_dir_gir: T.Optional[str]
+        install_dir_typelib: T.Optional[str]
+        link_with: T.List[T.Union[build.SharedLibrary, build.StaticLibrary]]
+        namespace: str
+        nsversion: str
+        sources: T.List[T.Union[FileOrString, build.GeneratedTypes]]
+        symbol_prefix: T.List[str]
+
+    class GtkDoc(TypedDict):
+
+        src_dir: T.List[T.Union[str, build.IncludeDirs]]
+        main_sgml: str
+        main_xml: str
+        module_version: str
+        namespace: str
+        mode: Literal['xml', 'smgl', 'auto', 'none']
+        html_args: T.List[str]
+        scan_args: T.List[str]
+        scanobjs_args: T.List[str]
+        fixxref_args: T.List[str]
+        mkdb_args: T.List[str]
+        content_files: T.List[T.Union[build.GeneratedTypes, FileOrString]]
+        ignore_headers: T.List[str]
+        install_dir: T.List[str]
+        check: bool
+        install: bool
+        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]]
+
+    class GdbusCodegen(TypedDict):
+
+        sources: T.List[FileOrString]
+        extra_args: T.List[str]
+        interface_prefix: T.Optional[str]
+        namespace: T.Optional[str]
+        object_manager: bool
+        build_by_default: bool
+        annotations: T.List[T.List[str]]
+        install_header: bool
+        install_dir: T.Optional[str]
+        docbook: T.Optional[str]
+        autocleanup: Literal['all', 'none', 'objects', 'default']
+
+    class GenMarshal(TypedDict):
+
+        build_always: T.Optional[str]
+        build_always_stale: T.Optional[bool]
+        build_by_default: T.Optional[bool]
+        depend_files: T.List[mesonlib.File]
+        extra_args: T.List[str]
+        install_dir: T.List[T.Union[str, bool]]
+        install_header: bool
+        internal: bool
+        nostdinc: bool
+        prefix: T.Optional[str]
+        skip_source: bool
+        sources: T.List[FileOrString]
+        stdinc: bool
+        valist_marshallers: bool
+
+    class GenerateVapi(TypedDict):
+
+        sources: T.List[T.Union[str, GirTarget]]
+        install_dir: T.Optional[str]
+        install: bool
+        vapi_dirs: T.List[str]
+        metadata_dirs: T.List[str]
+        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,
+)
+
+_EXTRA_ARGS_KW: KwargInfo[T.List[str]] = KwargInfo(
+    'extra_args',
+    ContainerTypeInfo(list, str),
+    default=[],
+    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 not annotations:
+        return None
+    elif 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
@@ -43,25 +253,32 @@
 
 native_glib_version = None
 
-@functools.lru_cache(maxsize=None)
-def gir_has_option(intr_obj, option):
-    try:
-        g_ir_scanner = intr_obj.find_program_impl('g-ir-scanner')
-        # Handle overridden g-ir-scanner
-        if isinstance(getattr(g_ir_scanner, "held_object", g_ir_scanner), interpreter.OverrideProgram):
-            assert option in ['--extra-library', '--sources-top-dirs']
-            return True
-
-        opts = Popen_safe(g_ir_scanner.get_command() + ['--help'], stderr=subprocess.STDOUT)[1]
-        return option in opts
-    except (MesonException, FileNotFoundError, subprocess.CalledProcessError):
-        return False
-
 class GnomeModule(ExtensionModule):
-    gir_dep = None
+    def __init__(self, interpreter: 'Interpreter') -> None:
+        super().__init__(interpreter)
+        self.gir_dep = None
+        self.install_glib_compile_schemas = False
+        self.install_gio_querymodules = []
+        self.install_gtk_update_icon_cache = False
+        self.install_update_desktop_database = False
+        self.devenv = None
+        self.methods.update({
+            'post_install': self.post_install,
+            'compile_resources': self.compile_resources,
+            'generate_gir': self.generate_gir,
+            'compile_schemas': self.compile_schemas,
+            'yelp': self.yelp,
+            'gtkdoc': self.gtkdoc,
+            'gtkdoc_html_dir': self.gtkdoc_html_dir,
+            'gdbus_codegen': self.gdbus_codegen,
+            'mkenums': self.mkenums,
+            'mkenums_simple': self.mkenums_simple,
+            'genmarshal': self.genmarshal,
+            'generate_vapi': self.generate_vapi,
+        })
 
     @staticmethod
-    def _get_native_glib_version(state):
+    def _get_native_glib_version(state: 'ModuleState') -> str:
         global native_glib_version
         if native_glib_version is None:
             glib_dep = PkgConfigDependency('glib-2.0', state.environment,
@@ -75,7 +292,7 @@
         return native_glib_version
 
     @mesonlib.run_once
-    def __print_gresources_warning(self, state):
+    def __print_gresources_warning(self, state: 'ModuleState') -> None:
         if not mesonlib.version_compare(self._get_native_glib_version(state),
                                         gresource_dep_needed_version):
             mlog.warning('GLib compiled dependencies do not work reliably with \n'
@@ -83,67 +300,144 @@
                          mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=774368'))
 
     @staticmethod
-    @mesonlib.run_once
-    def _print_gdbus_warning():
+    def _print_gdbus_warning() -> None:
         mlog.warning('Code generated with gdbus_codegen() requires the root directory be added to\n'
                      '  include_directories of targets with GLib < 2.51.3:',
-                     mlog.bold('https://github.com/mesonbuild/meson/issues/1387'))
+                     mlog.bold('https://github.com/mesonbuild/meson/issues/1387'),
+                     once=True)
+
+    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)
+
+    def _get_native_binary(self, state: 'ModuleState', name: str, depname: str,
+                           varname: str, required: bool = True) -> T.Union[ExternalProgram, OverrideProgram, 'build.Executable']:
+        # Look in overrides in case glib/gtk/etc are built as subproject
+        prog = self.interpreter.program_from_overrides([name], [])
+        if prog is not None:
+            return prog
+
+        # Look in machine file
+        prog_list = state.environment.lookup_binary_entry(MachineChoice.HOST, name)
+        if prog_list is not None:
+            return ExternalProgram.from_entry(name, prog_list)
+
+        # 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, {})
+            if value:
+                return ExternalProgram(name, [value])
+
+        # Normal program lookup
+        return state.find_program(name, required=required)
+
+    @typed_kwargs('gnome.post_install',
+        KwargInfo('glib_compile_schemas', bool, default=False),
+        KwargInfo('gio_querymodules', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('gtk_update_icon_cache', bool, default=False),
+        KwargInfo('update_desktop_database', bool, default=False, since='0.59.0'),
+    )
+    @noPosargs
+    @FeatureNew('gnome.post_install', '0.57.0')
+    def post_install(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'PostInstall') -> ModuleReturnValue:
+        rv: T.List['build.ExecutableSerialisation'] = []
+        datadir_abs = os.path.join(state.environment.get_prefix(), state.environment.get_datadir())
+        if kwargs['glib_compile_schemas'] and not self.install_glib_compile_schemas:
+            self.install_glib_compile_schemas = True
+            prog = self._get_native_binary(state, 'glib-compile-schemas', 'gio-2.0', 'glib_compile_schemas')
+            schemasdir = os.path.join(datadir_abs, 'glib-2.0', 'schemas')
+            script = state.backend.get_executable_serialisation([prog, schemasdir])
+            script.skip_if_destdir = True
+            rv.append(script)
+        for d in kwargs['gio_querymodules']:
+            if d not in self.install_gio_querymodules:
+                self.install_gio_querymodules.append(d)
+                prog = self._get_native_binary(state, 'gio-querymodules', 'gio-2.0', 'gio_querymodules')
+                moduledir = os.path.join(state.environment.get_prefix(), d)
+                script = state.backend.get_executable_serialisation([prog, moduledir])
+                script.skip_if_destdir = True
+                rv.append(script)
+        if kwargs['gtk_update_icon_cache'] and not self.install_gtk_update_icon_cache:
+            self.install_gtk_update_icon_cache = True
+            prog = self._get_native_binary(state, 'gtk4-update-icon-cache', 'gtk4', 'gtk4_update_icon_cache', required=False)
+            found = isinstance(prog, build.Executable) or prog.found()
+            if not found:
+                prog = self._get_native_binary(state, 'gtk-update-icon-cache', 'gtk+-3.0', 'gtk_update_icon_cache')
+            icondir = os.path.join(datadir_abs, 'icons', 'hicolor')
+            script = state.backend.get_executable_serialisation([prog, '-q', '-t', '-f', icondir])
+            script.skip_if_destdir = True
+            rv.append(script)
+        if kwargs['update_desktop_database'] and not self.install_update_desktop_database:
+            self.install_update_desktop_database = True
+            prog = self._get_native_binary(state, 'update-desktop-database', 'desktop-file-utils', 'update_desktop_database')
+            appdir = os.path.join(datadir_abs, 'applications')
+            script = state.backend.get_executable_serialisation([prog, '-q', appdir])
+            script.skip_if_destdir = True
+            rv.append(script)
+        return ModuleReturnValue(None, rv)
 
-    @FeatureNewKwargs('gnome.compile_resources', '0.37.0', ['gresource_bundle', 'export', 'install_header'])
-    @permittedKwargs({'source_dir', 'c_name', 'dependencies', 'export', 'gresource_bundle', 'install_header',
-                      'install', 'install_dir', 'extra_args', 'build_by_default'})
-    def compile_resources(self, state, args, kwargs):
+    @typed_pos_args('gnome.compile_resources', str, (str, mesonlib.File))
+    @typed_kwargs(
+        'gnome.compile_resources',
+        _BUILD_BY_DEFAULT,
+        _EXTRA_ARGS_KW,
+        INSTALL_KW,
+        INSTALL_KW.evolve(name='install_header', since='0.37.0'),
+        KwargInfo('c_name', (str, NoneType)),
+        KwargInfo('dependencies', ContainerTypeInfo(list, (mesonlib.File, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True),
+        KwargInfo('export', bool, default=False, since='0.37.0'),
+        KwargInfo('gresource_bundle', bool, default=False, since='0.37.0'),
+        KwargInfo('install_dir', (str, NoneType)),
+        KwargInfo('source_dir', ContainerTypeInfo(list, str), default=[], listify=True),
+    )
+    def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrString'],
+                          kwargs: 'CompileResources') -> 'ModuleReturnValue':
         self.__print_gresources_warning(state)
         glib_version = self._get_native_glib_version(state)
 
-        cmd = ['glib-compile-resources', '@INPUT@']
+        glib_compile_resources = state.find_program('glib-compile-resources')
+        cmd = [glib_compile_resources, '@INPUT@']
 
-        source_dirs, dependencies = mesonlib.extract_as_list(kwargs, 'source_dir', 'dependencies', pop=True)
+        source_dirs = kwargs['source_dir']
+        dependencies = kwargs['dependencies']
 
-        if len(args) < 2:
-            raise MesonException('Not enough arguments; the name of the resource '
-                                 'and the path to the XML file are required')
+        target_name, input_file = args
 
         # Validate dependencies
-        for (ii, dep) in enumerate(dependencies):
-            if hasattr(dep, 'held_object'):
-                dependencies[ii] = dep = dep.held_object
-            if not isinstance(dep, (mesonlib.File, build.CustomTarget, build.CustomTargetIndex)):
-                m = 'Unexpected dependency type {!r} for gnome.compile_resources() ' \
-                    '"dependencies" argument.\nPlease pass the return value of ' \
-                    'custom_target() or configure_file()'
-                raise MesonException(m.format(dep))
-            if isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)):
+        subdirs: T.List[str] = []
+        depends: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]] = []
+        for dep in dependencies:
+            if isinstance(dep, mesonlib.File):
+                subdirs.append(dep.subdir)
+            else:
+                depends.append(dep)
+                subdirs.append(dep.get_subdir())
                 if not mesonlib.version_compare(glib_version, gresource_dep_needed_version):
                     m = 'The "dependencies" argument of gnome.compile_resources() can not\n' \
                         'be used with the current version of glib-compile-resources due to\n' \
                         ''
                     raise MesonException(m)
 
-        ifile = args[1]
-        if isinstance(ifile, mesonlib.File):
-            # glib-compile-resources will be run inside the source dir,
-            # so we need either 'src_to_build' or the absolute path.
-            # Absolute path is the easiest choice.
-            if ifile.is_built:
-                ifile = os.path.join(state.environment.get_build_dir(), ifile.subdir, ifile.fname)
+        if not mesonlib.version_compare(glib_version, gresource_dep_needed_version):
+            # Resource xml files generated at build-time cannot be used with
+            # gnome.compile_resources() because we need to scan the xml for
+            # dependencies. Use configure_file() instead to generate it at
+            # configure-time
+            if isinstance(input_file, mesonlib.File):
+                # glib-compile-resources will be run inside the source dir,
+                # so we need either 'src_to_build' or the absolute path.
+                # Absolute path is the easiest choice.
+                if input_file.is_built:
+                    ifile = os.path.join(state.environment.get_build_dir(), input_file.subdir, input_file.fname)
+                else:
+                    ifile = os.path.join(input_file.subdir, input_file.fname)
             else:
-                ifile = os.path.join(ifile.subdir, ifile.fname)
-        elif isinstance(ifile, str):
-            ifile = os.path.join(state.subdir, ifile)
-        elif isinstance(ifile, (interpreter.CustomTargetHolder,
-                                interpreter.CustomTargetIndexHolder,
-                                interpreter.GeneratedObjectsHolder)):
-            m = 'Resource xml files generated at build-time cannot be used ' \
-                'with gnome.compile_resources() because we need to scan ' \
-                'the xml for dependencies. Use configure_file() instead ' \
-                'to generate it at configure-time.'
-            raise MesonException(m)
-        else:
-            raise MesonException('Invalid file argument: {!r}'.format(ifile))
+                ifile = os.path.join(state.subdir, input_file)
 
-        depend_files, depends, subdirs = self._get_gresource_dependencies(
-            state, ifile, source_dirs, dependencies)
+            depend_files, depends, subdirs = self._get_gresource_dependencies(
+                state, ifile, source_dirs, dependencies)
 
         # Make source dirs relative to build dir now
         source_dirs = [os.path.join(state.build_to_src, state.subdir, d) for d in source_dirs]
@@ -155,67 +449,77 @@
         for source_dir in OrderedSet(source_dirs):
             cmd += ['--sourcedir', source_dir]
 
-        if 'c_name' in kwargs:
-            cmd += ['--c-name', kwargs.pop('c_name')]
-        export = kwargs.pop('export', False)
-        if not export:
+        if kwargs['c_name']:
+            cmd += ['--c-name', kwargs['c_name']]
+        if not kwargs['export']:
             cmd += ['--internal']
 
         cmd += ['--generate', '--target', '@OUTPUT@']
+        cmd += kwargs['extra_args']
 
-        cmd += mesonlib.stringlistify(kwargs.pop('extra_args', []))
-
-        gresource = kwargs.pop('gresource_bundle', False)
+        gresource = kwargs['gresource_bundle']
         if gresource:
-            output = args[0] + '.gresource'
-            name = args[0] + '_gresource'
+            output = f'{target_name}.gresource'
+            name = f'{target_name}_gresource'
         else:
-            output = args[0] + '.c'
-            name = args[0] + '_c'
+            if 'c' in state.environment.coredata.compilers.host:
+                output = f'{target_name}.c'
+                name = f'{target_name}_c'
+            elif 'cpp' in state.environment.coredata.compilers.host:
+                output = f'{target_name}.cpp'
+                name = f'{target_name}_cpp'
+            else:
+                raise MesonException('Compiling GResources into code is only supported in C and C++ projects')
 
-        if kwargs.get('install', False) and not gresource:
+        if kwargs['install'] and not gresource:
             raise MesonException('The install kwarg only applies to gresource bundles, see install_header')
 
-        install_header = kwargs.pop('install_header', False)
+        install_header = kwargs['install_header']
         if install_header and gresource:
             raise MesonException('The install_header kwarg does not apply to gresource bundles')
-        if install_header and not export:
+        if install_header and not kwargs['export']:
             raise MesonException('GResource header is installed yet export is not enabled')
 
-        kwargs['input'] = args[1]
-        kwargs['output'] = output
-        kwargs['depends'] = depends
+        c_kwargs: T.Dict[str, T.Any] = {
+            'build_by_default': kwargs['build_by_default'],
+            'depends': depends,
+            'input': input_file,
+            'install': kwargs['install'],
+            'install_dir': kwargs['install_dir'] or [],
+            'output': output,
+        }
         if not mesonlib.version_compare(glib_version, gresource_dep_needed_version):
             # This will eventually go out of sync if dependencies are added
-            kwargs['depend_files'] = depend_files
-            kwargs['command'] = cmd
+            c_kwargs['depend_files'] = depend_files
+            c_kwargs['command'] = cmd
         else:
-            depfile = kwargs['output'] + '.d'
-            kwargs['depfile'] = depfile
-            kwargs['command'] = copy.copy(cmd) + ['--dependency-file', '@DEPFILE@']
-        target_c = GResourceTarget(name, state.subdir, state.subproject, kwargs)
+            depfile = f'{output}.d'
+            c_kwargs['depfile'] = depfile
+            c_kwargs['command'] = copy.copy(cmd) + ['--dependency-file', '@DEPFILE@']
+        target_c = GResourceTarget(name, state.subdir, state.subproject, c_kwargs)
 
         if gresource: # Only one target for .gresource files
             return ModuleReturnValue(target_c, [target_c])
 
-        h_kwargs = {
+        h_kwargs: T.Dict[str, T.Any] = {
             'command': cmd,
-            'input': args[1],
-            'output': args[0] + '.h',
+            'input': input_file,
+            'output': f'{target_name}.h',
             # The header doesn't actually care about the files yet it errors if missing
-            'depends': depends
+            'depends': depends,
+            'build_by_default': kwargs['build_by_default'],
+            'install_dir': kwargs['install_dir'] or [state.environment.coredata.get_option(mesonlib.OptionKey('includedir'))],
         }
-        if 'build_by_default' in kwargs:
-            h_kwargs['build_by_default'] = kwargs['build_by_default']
         if install_header:
             h_kwargs['install'] = install_header
-            h_kwargs['install_dir'] = kwargs.get('install_dir',
-                                                 state.environment.coredata.get_builtin_option('includedir'))
-        target_h = GResourceHeaderTarget(args[0] + '_h', state.subdir, state.subproject, h_kwargs)
+        target_h = GResourceHeaderTarget(f'{target_name}_h', state.subdir, state.subproject, h_kwargs)
         rv = [target_c, target_h]
         return ModuleReturnValue(rv, rv)
 
-    def _get_gresource_dependencies(self, state, input_file, source_dirs, dependencies):
+    def _get_gresource_dependencies(
+            self, 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]]:
 
         cmd = ['glib-compile-resources',
                input_file,
@@ -226,25 +530,27 @@
         for source_dir in source_dirs:
             cmd += ['--sourcedir', os.path.join(state.subdir, source_dir)]
 
-        pc, stdout, stderr = Popen_safe(cmd, cwd=state.environment.get_source_dir())
+        try:
+            pc, stdout, stderr = Popen_safe(cmd, cwd=state.environment.get_source_dir())
+        except (FileNotFoundError, PermissionError):
+            raise MesonException('Could not execute glib-compile-resources.')
         if pc.returncode != 0:
-            m = 'glib-compile-resources failed to get dependencies for {}:\n{}'
-            mlog.warning(m.format(cmd[1], stderr))
+            m = f'glib-compile-resources failed to get dependencies for {cmd[1]}:\n{stderr}'
+            mlog.warning(m)
             raise subprocess.CalledProcessError(pc.returncode, cmd)
 
-        dep_files = stdout.split('\n')[:-1]
+        raw_dep_files: T.List[str] = stdout.split('\n')[:-1]
 
-        depends = []
-        subdirs = []
-        for resfile in dep_files[:]:
+        depends: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]] = []
+        subdirs: T.List[str] = []
+        dep_files: T.List[mesonlib.FileOrString] = []
+        for resfile in raw_dep_files.copy():
             resbasename = os.path.basename(resfile)
             for dep in dependencies:
-                if hasattr(dep, 'held_object'):
-                    dep = dep.held_object
                 if isinstance(dep, mesonlib.File):
                     if dep.fname != resbasename:
                         continue
-                    dep_files.remove(resfile)
+                    raw_dep_files.remove(resfile)
                     dep_files.append(dep)
                     subdirs.append(dep.subdir)
                     break
@@ -256,7 +562,7 @@
                             fname = o
                             break
                     if fname is not None:
-                        dep_files.remove(resfile)
+                        raw_dep_files.remove(resfile)
                         depends.append(dep)
                         subdirs.append(dep.get_subdir())
                         break
@@ -274,17 +580,21 @@
                                                        ".", resfile)
                 except MesonException:
                     raise MesonException(
-                        'Resource "%s" listed in "%s" was not found. If this is a '
-                        'generated file, pass the target that generates it to '
-                        'gnome.compile_resources() using the "dependencies" '
-                        'keyword argument.' % (resfile, input_file))
-                dep_files.remove(resfile)
+                        f'Resource "{resfile}" listed in "{input_file}" was not found. '
+                        'If this is a generated file, pass the target that generates '
+                        'it to gnome.compile_resources() using the "dependencies" '
+                        'keyword argument.')
+                raw_dep_files.remove(resfile)
                 dep_files.append(f)
+        dep_files.extend(raw_dep_files)
         return dep_files, depends, subdirs
 
-    def _get_link_args(self, state, lib, depends, include_rpath=False,
-                       use_gir_args=False):
-        link_command = []
+    def _get_link_args(self, state: 'ModuleState',
+                       lib: T.Union[build.SharedLibrary, build.StaticLibrary],
+                       depends: T.List[build.BuildTarget],
+                       include_rpath: bool = False,
+                       use_gir_args: bool = False) -> T.List[str]:
+        link_command: T.List[str] = []
         # Construct link args
         if isinstance(lib, build.SharedLibrary):
             libdir = os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(lib))
@@ -301,30 +611,36 @@
                 link_command.append('-L' + d)
                 if include_rpath:
                     link_command.append('-Wl,-rpath,' + d)
-        if gir_has_option(self.interpreter, '--extra-library') and use_gir_args:
+        if use_gir_args and self._gir_has_option('--extra-library'):
             link_command.append('--extra-library=' + lib.name)
         else:
             link_command.append('-l' + lib.name)
         return link_command
 
-    def _get_dependencies_flags(self, deps, state, depends, include_rpath=False,
-                                use_gir_args=False, separate_nodedup=False):
-        cflags = OrderedSet()
-        internal_ldflags = OrderedSet()
-        external_ldflags = OrderedSet()
+    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]]:
+        cflags: OrderedSet[str] = OrderedSet()
+        internal_ldflags: OrderedSet[str] = OrderedSet()
+        external_ldflags: OrderedSet[str] = OrderedSet()
         # External linker flags that can't be de-duped reliably because they
         # require two args in order, such as -framework AVFoundation
-        external_ldflags_nodedup = []
-        gi_includes = OrderedSet()
-        deps = mesonlib.listify(deps, unholder=True)
+        external_ldflags_nodedup: T.List[str] = []
+        gi_includes: OrderedSet[str] = OrderedSet()
+        deps = mesonlib.listify(deps)
 
         for dep in deps:
+            if isinstance(dep, Dependency):
+                girdir = dep.get_variable(pkgconfig='girdir', internal='girdir', default_value='')
+                if girdir:
+                    assert isinstance(girdir, str), 'for mypy'
+                    gi_includes.update([girdir])
             if isinstance(dep, InternalDependency):
                 cflags.update(dep.get_compile_args())
-                cflags.update(get_include_args(dep.include_directories))
+                cflags.update(state.get_include_args(dep.include_directories))
                 for lib in dep.libraries:
-                    if hasattr(lib, 'held_object'):
-                        lib = lib.held_object
                     if isinstance(lib, build.SharedLibrary):
                         internal_ldflags.update(self._get_link_args(state, lib, depends, include_rpath))
                         libdepflags = self._get_dependencies_flags(lib.get_external_deps(), state, depends, include_rpath,
@@ -342,8 +658,6 @@
                 external_ldflags_nodedup += extdepflags[3]
                 gi_includes.update(extdepflags[4])
                 for source in dep.sources:
-                    if hasattr(source, 'held_object'):
-                        source = source.held_object
                     if isinstance(source, GirTarget):
                         gi_includes.update([os.path.join(state.environment.get_build_dir(),
                                             source.get_subdir())])
@@ -351,43 +665,38 @@
             elif isinstance(dep, Dependency):
                 cflags.update(dep.get_compile_args())
                 ldflags = iter(dep.get_link_args(raw=True))
-                for lib in ldflags:
-                    if (os.path.isabs(lib) and
+                for flag in ldflags:
+                    if (os.path.isabs(flag) and
                             # For PkgConfigDependency only:
                             getattr(dep, 'is_libtool', False)):
-                        lib_dir = os.path.dirname(lib)
-                        external_ldflags.update(["-L%s" % lib_dir])
+                        lib_dir = os.path.dirname(flag)
+                        external_ldflags.update([f'-L{lib_dir}'])
                         if include_rpath:
-                            external_ldflags.update(['-Wl,-rpath {}'.format(lib_dir)])
-                        libname = os.path.basename(lib)
+                            external_ldflags.update([f'-Wl,-rpath {lib_dir}'])
+                        libname = os.path.basename(flag)
                         if libname.startswith("lib"):
                             libname = libname[3:]
                         libname = libname.split(".so")[0]
-                        lib = "-l%s" % libname
+                        flag = f"-l{libname}"
                     # FIXME: Hack to avoid passing some compiler options in
-                    if lib.startswith("-W"):
+                    if flag.startswith("-W"):
                         continue
                     # If it's a framework arg, slurp the framework name too
                     # to preserve the order of arguments
-                    if lib == '-framework':
-                        external_ldflags_nodedup += [lib, next(ldflags)]
+                    if flag == '-framework':
+                        external_ldflags_nodedup += [flag, next(ldflags)]
                     else:
-                        external_ldflags.update([lib])
-
-                if isinstance(dep, PkgConfigDependency):
-                    girdir = dep.get_pkgconfig_variable("girdir", {'default': ''})
-                    if girdir:
-                        gi_includes.update([girdir])
+                        external_ldflags.update([flag])
             elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
-                cflags.update(get_include_args(dep.get_include_dirs()))
+                cflags.update(state.get_include_args(dep.get_include_dirs()))
                 depends.append(dep)
             else:
-                mlog.log('dependency {!r} not handled to build gir files'.format(dep))
+                mlog.log(f'dependency {dep!r} not handled to build gir files')
                 continue
 
-        if gir_has_option(self.interpreter, '--extra-library') and use_gir_args:
-            def fix_ldflags(ldflags):
-                fixed_ldflags = OrderedSet()
+        if use_gir_args and self._gir_has_option('--extra-library'):
+            def fix_ldflags(ldflags: T.Iterable[str]) -> OrderedSet[str]:
+                fixed_ldflags: OrderedSet[str] = OrderedSet()
                 for ldflag in ldflags:
                     if ldflag.startswith("-l"):
                         ldflag = ldflag.replace('-l', '--extra-library=', 1)
@@ -397,17 +706,15 @@
             external_ldflags = fix_ldflags(external_ldflags)
         if not separate_nodedup:
             external_ldflags.update(external_ldflags_nodedup)
-            return cflags, internal_ldflags, external_ldflags, gi_includes
+            return cflags, internal_ldflags, external_ldflags, None, gi_includes
         else:
             return cflags, internal_ldflags, external_ldflags, external_ldflags_nodedup, gi_includes
 
-    def _unwrap_gir_target(self, girtarget, state):
-        while hasattr(girtarget, 'held_object'):
-            girtarget = girtarget.held_object
-
+    def _unwrap_gir_target(self, girtarget: T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary], state: 'ModuleState'
+                           ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary]:
         if not isinstance(girtarget, (build.Executable, build.SharedLibrary,
                                       build.StaticLibrary)):
-            raise MesonException('Gir target must be an executable or library')
+            raise MesonException(f'Gir target must be an executable or library but is "{girtarget}" of type {type(girtarget).__name__}')
 
         STATIC_BUILD_REQUIRED_VERSION = ">=1.58.1"
         if isinstance(girtarget, (build.StaticLibrary)) and \
@@ -418,109 +725,49 @@
 
         return girtarget
 
-    def _get_gir_dep(self, state):
-        try:
-            gir_dep = self.gir_dep or PkgConfigDependency('gobject-introspection-1.0',
-                                                          state.environment,
-                                                          {'native': True})
-            pkgargs = gir_dep.get_compile_args()
-        except Exception:
-            raise MesonException('gobject-introspection dependency was not found, gir cannot be generated.')
-
-        return gir_dep, pkgargs
-
-    def _scan_header(self, kwargs):
-        ret = []
-        header = kwargs.pop('header', None)
-        if header:
-            if not isinstance(header, str):
-                raise MesonException('header must be a string')
-            ret = ['--c-include=' + header]
-        return ret
-
-    def _scan_extra_args(self, kwargs):
-        return mesonlib.stringlistify(kwargs.pop('extra_args', []))
-
-    def _scan_link_withs(self, state, depends, kwargs):
-        ret = []
-        if 'link_with' in kwargs:
-            link_with = mesonlib.extract_as_list(kwargs, 'link_with', pop = True)
-
-            for link in link_with:
-                ret += self._get_link_args(state, link.held_object, depends,
-                                           use_gir_args=True)
-        return ret
+    def _devenv_prepend(self, varname: str, value: str) -> None:
+        if self.devenv is None:
+            self.devenv = build.EnvironmentVariables()
+            self.interpreter.build.devenv.append(self.devenv)
+        self.devenv.prepend(varname, [value])
+
+    def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, T.Union[build.Executable, 'ExternalProgram', 'OverrideProgram'],
+                                                            T.Union[build.Executable, 'ExternalProgram', 'OverrideProgram']]:
+        if not self.gir_dep:
+            self.gir_dep = self._get_dep(state, 'gobject-introspection-1.0')
+            self.giscanner = self._get_native_binary(state, 'g-ir-scanner', 'gobject-introspection-1.0', 'g_ir_scanner')
+            self.gicompiler = self._get_native_binary(state, 'g-ir-compiler', 'gobject-introspection-1.0', 'g_ir_compiler')
+        return self.gir_dep, self.giscanner, self.gicompiler
+
+    @functools.lru_cache(maxsize=None)
+    def _gir_has_option(self, option: str) -> bool:
+        exe = self.giscanner
+        if isinstance(exe, OverrideProgram):
+            # Handle overridden g-ir-scanner
+            assert option in {'--extra-library', '--sources-top-dirs'}
+            return True
+        p, o, _ = Popen_safe(exe.get_command() + ['--help'], stderr=subprocess.STDOUT)
+        return p.returncode == 0 and option in o
 
     # May mutate depends and gir_inc_dirs
-    def _scan_include(self, state, depends, gir_inc_dirs, kwargs):
-        ret = []
+    def _scan_include(self, 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] = []
+        depends: T.List[GirTarget] = []
+
+        for inc in includes:
+            if isinstance(inc, str):
+                ret += [f'--include={inc}']
+            elif isinstance(inc, GirTarget):
+                gir_inc_dirs .append(os.path.join(state.environment.get_build_dir(), inc.get_subdir()))
+                ret.append(f"--include-uninstalled={os.path.join(inc.get_subdir(), inc.get_basename())}")
+                depends.append(inc)
 
-        if 'includes' in kwargs:
-            includes = mesonlib.extract_as_list(kwargs, 'includes', pop = True)
-            for inc in includes:
-                if hasattr(inc, 'held_object'):
-                    inc = inc.held_object
-                if isinstance(inc, str):
-                    ret += ['--include=%s' % (inc, )]
-                elif isinstance(inc, GirTarget):
-                    gir_inc_dirs += [
-                        os.path.join(state.environment.get_build_dir(),
-                                     inc.get_subdir()),
-                    ]
-                    ret += [
-                        "--include-uninstalled=%s" % (os.path.join(inc.get_subdir(), inc.get_basename()), )
-                    ]
-                    depends += [inc]
-                else:
-                    raise MesonException(
-                        'Gir includes must be str, GirTarget, or list of them')
-
-        return ret
+        return ret, gir_inc_dirs, depends
 
-    def _scan_symbol_prefix(self, kwargs):
-        ret = []
-
-        if 'symbol_prefix' in kwargs:
-            sym_prefixes = mesonlib.stringlistify(kwargs.pop('symbol_prefix', []))
-            ret += ['--symbol-prefix=%s' % sym_prefix for sym_prefix in sym_prefixes]
-
-        return ret
-
-    def _scan_identifier_prefix(self, kwargs):
-        ret = []
-
-        if 'identifier_prefix' in kwargs:
-            identifier_prefix = kwargs.pop('identifier_prefix')
-            if not isinstance(identifier_prefix, str):
-                raise MesonException('Gir identifier prefix must be str')
-            ret += ['--identifier-prefix=%s' % identifier_prefix]
-
-        return ret
-
-    def _scan_export_packages(self, kwargs):
-        ret = []
-
-        if 'export_packages' in kwargs:
-            pkgs = kwargs.pop('export_packages')
-            if isinstance(pkgs, str):
-                ret += ['--pkg-export=%s' % pkgs]
-            elif isinstance(pkgs, list):
-                ret += ['--pkg-export=%s' % pkg for pkg in pkgs]
-            else:
-                raise MesonException('Gir export packages must be str or list')
-
-        return ret
-
-    def _scan_inc_dirs(self, kwargs):
-        ret = mesonlib.extract_as_list(kwargs, 'include_directories', pop = True)
-        for incd in ret:
-            if not isinstance(incd.held_object, (str, build.IncludeDirs)):
-                raise MesonException(
-                    'Gir include dirs should be include_directories().')
-        return ret
-
-    def _scan_langs(self, state, langs):
-        ret = []
+    def _scan_langs(self, state: 'ModuleState', langs: T.Iterable[str]) -> T.List[str]:
+        ret: T.List[str] = []
 
         for lang in langs:
             link_args = state.environment.coredata.get_external_link_args(MachineChoice.HOST, lang)
@@ -530,8 +777,8 @@
 
         return ret
 
-    def _scan_gir_targets(self, state, girtargets):
-        ret = []
+    def _scan_gir_targets(self, 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:
             if isinstance(girtarget, build.Executable):
@@ -539,15 +786,20 @@
             else:
                 # Because of https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/72
                 # we can't use the full path until this is merged.
+                libpath = os.path.join(girtarget.get_subdir(), girtarget.get_filename())
+                # Must use absolute paths here because g-ir-scanner will not
+                # add them to the runtime path list if they're relative. This
+                # means we cannot use @BUILD_ROOT@
+                build_root = state.environment.get_build_dir()
                 if isinstance(girtarget, build.SharedLibrary):
+                    # need to put our output directory first as we need to use the
+                    # generated libraries instead of any possibly installed system/prefix
+                    # ones.
+                    ret += ["-L{}/{}".format(build_root, os.path.dirname(libpath))]
                     libname = girtarget.get_basename()
                 else:
-                    libname = os.path.join("@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id(), girtarget.get_filename())
+                    libname = os.path.join(f"{build_root}/{libpath}")
                 ret += ['--library', libname]
-                # need to put our output directory first as we need to use the
-                # generated libraries instead of any possibly installed system/prefix
-                # ones.
-                ret += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()]
                 # Needed for the following binutils bug:
                 # https://github.com/mesonbuild/meson/issues/1911
                 # However, g-ir-scanner does not understand -Wl,-rpath
@@ -558,8 +810,8 @@
 
         return ret
 
-    def _get_girtargets_langs_compilers(self, girtargets):
-        ret = []
+    def _get_girtargets_langs_compilers(self, 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():
                 # XXX: Can you use g-i with any other language?
@@ -569,31 +821,33 @@
 
         return ret
 
-    def _get_gir_targets_deps(self, girtargets):
-        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]] = []
         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):
-        ret = []
+    def _get_gir_targets_inc_dirs(self, 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, langs_compilers):
-        cflags = []
-        internal_ldflags = []
-        external_ldflags = []
+    def _get_langs_compilers_flags(self, 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] = []
+        external_ldflags: T.List[str] = []
 
         for lang, compiler in langs_compilers:
             if state.global_args.get(lang):
                 cflags += state.global_args[lang]
             if state.project_args.get(lang):
                 cflags += state.project_args[lang]
-            if 'b_sanitize' in compiler.base_options:
-                sanitize = state.environment.coredata.base_options['b_sanitize'].value
+            if mesonlib.OptionKey('b_sanitize') in compiler.base_options:
+                sanitize = state.environment.coredata.options[mesonlib.OptionKey('b_sanitize')].value
                 cflags += compiler.sanitizer_compile_args(sanitize)
                 sanitize = sanitize.split(',')
                 # These must be first in ldflags
@@ -609,16 +863,19 @@
 
         return cflags, internal_ldflags, external_ldflags
 
-    def _make_gir_filelist(self, state, srcdir, ns, nsversion, girtargets, libsources):
+    def _make_gir_filelist(self, 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]]
+                            ) -> str:
         gir_filelist_dir = state.backend.get_target_private_dir_abs(girtargets[0])
         if not os.path.isdir(gir_filelist_dir):
             os.mkdir(gir_filelist_dir)
-        gir_filelist_filename = os.path.join(gir_filelist_dir, '%s_%s_gir_filelist' % (ns, nsversion))
+        gir_filelist_filename = os.path.join(gir_filelist_dir, f'{ns}_{nsversion}_gir_filelist')
 
         with open(gir_filelist_filename, 'w', encoding='utf-8') as gir_filelist:
             for s in libsources:
-                if hasattr(s, 'held_object'):
-                    s = s.held_object
                 if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)):
                     for custom_output in s.get_outputs():
                         gir_filelist.write(os.path.join(state.environment.get_build_dir(),
@@ -634,52 +891,68 @@
 
         return gir_filelist_filename
 
-    def _make_gir_target(self, state, girfile, scan_command, depends, kwargs):
-        scankwargs = {'output': girfile,
-                      'command': scan_command,
-                      'depends': depends}
-
-        if 'install' in kwargs:
-            scankwargs['install'] = kwargs['install']
-            scankwargs['install_dir'] = kwargs.get('install_dir_gir',
-                                                   os.path.join(state.environment.get_datadir(), 'gir-1.0'))
-
-        if 'build_by_default' in kwargs:
-            scankwargs['build_by_default'] = kwargs['build_by_default']
+    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:
+        install = kwargs['install_gir']
+        if install is None:
+            install = kwargs['install']
+
+        install_dir = kwargs['install_dir_gir']
+        if install_dir is None:
+            install_dir = os.path.join(state.environment.get_datadir(), 'gir-1.0')
+        elif install_dir is False:
+            install = False
+
+        scankwargs = {
+            'input': generated_files,
+            'output': girfile,
+            'command': scan_command,
+            'depends': depends,
+            'install': install,
+            'install_dir': install_dir,
+            'install_tag': 'devel',
+            'build_by_default': kwargs['build_by_default'],
+        }
 
         return GirTarget(girfile, state.subdir, state.subproject, scankwargs)
 
-    def _make_typelib_target(self, state, typelib_output, typelib_cmd, kwargs):
+    def _make_typelib_target(self, state: 'ModuleState', typelib_output: str, typelib_cmd: T.List[str],
+                             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']
+        if install is None:
+            install = kwargs['install']
+
+        install_dir = kwargs['install_dir_typelib']
+        if install_dir is None:
+            install_dir = os.path.join(state.environment.get_libdir(), 'girepository-1.0')
+        elif install_dir is False:
+            install = False
+
         typelib_kwargs = {
-            'output': typelib_output,
+            'input': generated_files,
+            'output': [typelib_output],
             'command': typelib_cmd,
+            'install': install,
+            'install_dir': install_dir,
+            'install_tag': 'typelib',
+            'build_by_default': kwargs['build_by_default'],
         }
 
-        if 'install' in kwargs:
-            typelib_kwargs['install'] = kwargs['install']
-            typelib_kwargs['install_dir'] = kwargs.get('install_dir_typelib',
-                                                       os.path.join(state.environment.get_libdir(), 'girepository-1.0'))
-
-        if 'build_by_default' in kwargs:
-            typelib_kwargs['build_by_default'] = kwargs['build_by_default']
-
         return TypelibTarget(typelib_output, state.subdir, state.subproject, typelib_kwargs)
 
     # May mutate depends
-    def _gather_typelib_includes_and_update_depends(self, state, deps, depends):
+    def _gather_typelib_includes_and_update_depends(self, state: 'ModuleState', deps: T.List[Dependency], depends: T.List[build.Target]) -> T.List[str]:
         # 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 = []
+        typelib_includes: T.List[str] = []
         for dep in deps:
-            if hasattr(dep, 'held_object'):
-                dep = dep.held_object
             # 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 hasattr(source, 'held_object'):
-                        source = source.held_object
                     if isinstance(source, GirTarget) and source not in depends:
                         depends.append(source)
                         subdir = os.path.join(state.environment.get_build_dir(),
@@ -698,295 +971,399 @@
                                               source.get_subdir())
                         if subdir not in typelib_includes:
                             typelib_includes.append(subdir)
-            elif isinstance(dep, PkgConfigDependency):
-                girdir = dep.get_pkgconfig_variable("girdir", {'default': ''})
+            if isinstance(dep, Dependency):
+                girdir = dep.get_variable(pkgconfig='girdir', internal='girdir', default_value='')
+                assert isinstance(girdir, str), 'for mypy'
                 if girdir and girdir not in typelib_includes:
                     typelib_includes.append(girdir)
-
         return typelib_includes
 
-    def _get_external_args_for_langs(self, state, langs):
-        ret = []
+    def _get_external_args_for_langs(self, state: 'ModuleState', langs: T.Sequence[str]) -> T.List[str]:
+        ret: T.List[str] = []
         for lang in langs:
-            ret += state.environment.coredata.get_external_args(MachineChoice.HOST, lang)
+            ret += mesonlib.listify(state.environment.coredata.get_external_args(MachineChoice.HOST, lang))
         return ret
 
     @staticmethod
-    def _get_scanner_cflags(cflags):
+    def _get_scanner_cflags(cflags: T.Iterable[str]) -> T.Iterable[str]:
         'g-ir-scanner only accepts -I/-D/-U; must ignore all other flags'
         for f in cflags:
-            if f.startswith(('-D', '-U', '-I')):
+            # _FORTIFY_SOURCE depends on / works together with -O, on the other hand this
+            # just invokes the preprocessor anyway
+            if f.startswith(('-D', '-U', '-I')) and not f.startswith('-D_FORTIFY_SOURCE'):
                 yield f
 
     @staticmethod
-    def _get_scanner_ldflags(ldflags):
+    def _get_scanner_ldflags(ldflags: T.Iterable[str]) -> T.Iterable[str]:
         'g-ir-scanner only accepts -L/-l; must ignore -F and other linker flags'
         for f in ldflags:
             if f.startswith(('-L', '-l', '--extra-library')):
                 yield f
 
-    @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
-    @permittedKwargs({'sources', 'nsversion', 'namespace', 'symbol_prefix', 'identifier_prefix',
-                      'export_packages', 'includes', 'dependencies', 'link_with', 'include_directories',
-                      'install', 'install_dir_gir', 'install_dir_typelib', 'extra_args',
-                      'packages', 'header', 'build_by_default'})
-    def generate_gir(self, state, args, kwargs):
-        if not args:
-            raise MesonException('generate_gir takes at least one argument')
-        if kwargs.get('install_dir'):
-            raise MesonException('install_dir is not supported with generate_gir(), see "install_dir_gir" and "install_dir_typelib"')
-
-        giscanner = self.interpreter.find_program_impl('g-ir-scanner')
-        gicompiler = self.interpreter.find_program_impl('g-ir-compiler')
-
-        girtargets = [self._unwrap_gir_target(arg, state) for arg in args]
-
+    @typed_pos_args('gnome.generate_gir', varargs=(build.Executable, build.SharedLibrary, build.StaticLibrary), min_varargs=1)
+    @typed_kwargs(
+        'gnome.generate_gir',
+        INSTALL_KW,
+        _BUILD_BY_DEFAULT.evolve(since='0.40.0'),
+        _EXTRA_ARGS_KW,
+        KwargInfo('dependencies', ContainerTypeInfo(list, Dependency), default=[], listify=True),
+        KwargInfo('export_packages', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('fatal_warnings', bool, default=False, since='0.55.0'),
+        KwargInfo('header', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('identifier_prefix', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('include_directories', ContainerTypeInfo(list, (str, build.IncludeDirs)), default=[], listify=True),
+        KwargInfo('includes', ContainerTypeInfo(list, (str, GirTarget)), default=[], listify=True),
+        KwargInfo('install_gir', (bool, NoneType), since='0.61.0'),
+        KwargInfo('install_dir_gir', (str, bool, NoneType),
+            deprecated_values={False: ('0.61.0', 'Use install_gir to disable installation')},
+            validator=lambda x: 'as boolean can only be false' if x is True else None),
+        KwargInfo('install_typelib', (bool, NoneType), since='0.61.0'),
+        KwargInfo('install_dir_typelib', (str, bool, NoneType),
+            deprecated_values={False: ('0.61.0', 'Use install_typelib to disable installation')},
+            validator=lambda x: 'as boolean can only be false' if x is True else None),
+        KwargInfo('link_with', ContainerTypeInfo(list, (build.SharedLibrary, build.StaticLibrary)), default=[], listify=True),
+        KwargInfo('namespace', str, required=True),
+        KwargInfo('nsversion', str, required=True),
+        KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True),
+        KwargInfo('symbol_prefix', ContainerTypeInfo(list, str), default=[], listify=True),
+    )
+    def generate_gir(self, state: 'ModuleState', args: T.Tuple[T.List[T.Union[build.Executable, build.SharedLibrary, build.StaticLibrary]]],
+                     kwargs: 'GenerateGir') -> ModuleReturnValue:
+        girtargets = [self._unwrap_gir_target(arg, state) for arg in args[0]]
         if len(girtargets) > 1 and any([isinstance(el, build.Executable) for el in girtargets]):
             raise MesonException('generate_gir only accepts a single argument when one of the arguments is an executable')
 
-        self.gir_dep, pkgargs = self._get_gir_dep(state)
+        gir_dep, giscanner, gicompiler = self._get_gir_dep(state)
+
+        ns = kwargs['namespace']
+        nsversion = kwargs['nsversion']
+        libsources = kwargs['sources']
 
-        ns = kwargs.pop('namespace')
-        nsversion = kwargs.pop('nsversion')
-        libsources = mesonlib.extract_as_list(kwargs, 'sources', pop=True)
-        girfile = '%s-%s.gir' % (ns, nsversion)
+        girfile = f'{ns}-{nsversion}.gir'
         srcdir = os.path.join(state.environment.get_source_dir(), state.subdir)
         builddir = os.path.join(state.environment.get_build_dir(), state.subdir)
-        depends = [] + girtargets
-        gir_inc_dirs = []
+
+        depends: T.List[T.Union['FileOrString', build.GeneratedTypes, build.Executable, build.SharedLibrary, build.StaticLibrary]] = []
+        depends.extend(gir_dep.sources)
+        depends.extend(girtargets)
+
         langs_compilers = self._get_girtargets_langs_compilers(girtargets)
         cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers)
         deps = self._get_gir_targets_deps(girtargets)
-        deps += extract_as_list(kwargs, 'dependencies', pop=True, unholder=True)
+        deps += kwargs['dependencies']
+        deps += [gir_dep]
         typelib_includes = 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 = \
             self._get_dependencies_flags(deps, state, depends, use_gir_args=True)
-        cflags += list(self._get_scanner_cflags(dep_cflags))
-        cflags += list(self._get_scanner_cflags(self._get_external_args_for_langs(state, [lc[0] for lc in langs_compilers])))
-        internal_ldflags += list(self._get_scanner_ldflags(dep_internal_ldflags))
-        external_ldflags += list(self._get_scanner_ldflags(dep_external_ldflags))
+        scan_cflags = []
+        scan_cflags += list(self._get_scanner_cflags(cflags))
+        scan_cflags += list(self._get_scanner_cflags(dep_cflags))
+        scan_cflags += list(self._get_scanner_cflags(self._get_external_args_for_langs(state, [lc[0] for lc in langs_compilers])))
+        scan_internal_ldflags = []
+        scan_internal_ldflags += list(self._get_scanner_ldflags(internal_ldflags))
+        scan_internal_ldflags += list(self._get_scanner_ldflags(dep_internal_ldflags))
+        scan_external_ldflags = []
+        scan_external_ldflags += list(self._get_scanner_ldflags(external_ldflags))
+        scan_external_ldflags += list(self._get_scanner_ldflags(dep_external_ldflags))
         girtargets_inc_dirs = self._get_gir_targets_inc_dirs(girtargets)
-        inc_dirs = self._scan_inc_dirs(kwargs)
+        inc_dirs = kwargs['include_directories']
 
-        scan_command = [giscanner]
-        scan_command += pkgargs
+        gir_inc_dirs: T.List[str] = []
+
+        scan_command: T.List[T.Union[str, build.Executable, 'ExternalProgram', 'OverrideProgram']] = [giscanner]
         scan_command += ['--no-libtool']
         scan_command += ['--namespace=' + ns, '--nsversion=' + nsversion]
         scan_command += ['--warn-all']
         scan_command += ['--output', '@OUTPUT@']
-        scan_command += self._scan_header(kwargs)
-        scan_command += self._scan_extra_args(kwargs)
+        scan_command += [f'--c-include={h}' for h in kwargs['header']]
+        scan_command += kwargs['extra_args']
         scan_command += ['-I' + srcdir, '-I' + builddir]
-        scan_command += get_include_args(girtargets_inc_dirs)
+        scan_command += state.get_include_args(girtargets_inc_dirs)
         scan_command += ['--filelist=' + self._make_gir_filelist(state, srcdir, ns, nsversion, girtargets, libsources)]
-        scan_command += self._scan_link_withs(state, depends, kwargs)
-        scan_command += self._scan_include(state, depends, gir_inc_dirs, kwargs)
-        scan_command += self._scan_symbol_prefix(kwargs)
-        scan_command += self._scan_identifier_prefix(kwargs)
-        scan_command += self._scan_export_packages(kwargs)
+        scan_command += mesonlib.listify([self._get_link_args(state, l, depends, use_gir_args=True)
+                                          for l in kwargs['link_with']])
+
+        _cmd, _ginc, _deps = self._scan_include(state, kwargs['includes'])
+        scan_command.extend(_cmd)
+        gir_inc_dirs.extend(_ginc)
+        depends.extend(_deps)
+
+        scan_command += [f'--symbol-prefix={p}' for p in kwargs['symbol_prefix']]
+        scan_command += [f'--identifier-prefix={p}' for p in kwargs['identifier_prefix']]
+        scan_command += [f'--pkg-export={p}' for p in kwargs['export_packages']]
         scan_command += ['--cflags-begin']
-        scan_command += cflags
+        scan_command += scan_cflags
         scan_command += ['--cflags-end']
-        scan_command += get_include_args(inc_dirs)
-        scan_command += get_include_args(list(gi_includes) + gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
-        scan_command += list(internal_ldflags)
+        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 += 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])
-        scan_command += list(external_ldflags)
+        scan_command += list(scan_external_ldflags)
 
-        if gir_has_option(self.interpreter, '--sources-top-dirs'):
+        if self._gir_has_option('--sources-top-dirs'):
             scan_command += ['--sources-top-dirs', os.path.join(state.environment.get_source_dir(), self.interpreter.subproject_dir, state.subproject)]
             scan_command += ['--sources-top-dirs', os.path.join(state.environment.get_build_dir(), self.interpreter.subproject_dir, state.subproject)]
 
-        scan_target = self._make_gir_target(state, girfile, scan_command, depends, kwargs)
+        if '--warn-error' in scan_command:
+            FeatureDeprecated.single_use('gnome.generate_gir argument --warn-error', '0.55.0',
+                                         state.subproject, 'Use "fatal_warnings" keyword argument', state.current_node)
+        if kwargs['fatal_warnings']:
+            scan_command.append('--warn-error')
 
-        typelib_output = '%s-%s.typelib' % (ns, nsversion)
+        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)
+
+        typelib_output = f'{ns}-{nsversion}.typelib'
         typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@']
-        typelib_cmd += get_include_args(gir_inc_dirs, prefix='--includedir=')
+        typelib_cmd += state.get_include_args(gir_inc_dirs, prefix='--includedir=')
 
         for incdir in typelib_includes:
             typelib_cmd += ["--includedir=" + incdir]
 
-        typelib_target = self._make_typelib_target(state, typelib_output, typelib_cmd, kwargs)
+        typelib_target = self._make_typelib_target(state, typelib_output, typelib_cmd, generated_files, kwargs)
+
+        self._devenv_prepend('GI_TYPELIB_PATH', os.path.join(state.environment.get_build_dir(), state.subdir))
 
         rv = [scan_target, typelib_target]
 
         return ModuleReturnValue(rv, rv)
 
-    @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
-    @permittedKwargs({'build_by_default', 'depend_files'})
-    def compile_schemas(self, state, args, kwargs):
-        if args:
-            raise MesonException('Compile_schemas does not take positional arguments.')
+    @noPosargs
+    @typed_kwargs('gnome.compile_schemas', _BUILD_BY_DEFAULT.evolve(since='0.40.0'), DEPEND_FILES_KW)
+    def compile_schemas(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'CompileSchemas') -> ModuleReturnValue:
         srcdir = os.path.join(state.build_to_src, state.subdir)
         outdir = state.subdir
 
-        cmd = [self.interpreter.find_program_impl('glib-compile-schemas')]
-        cmd += ['--targetdir', outdir, srcdir]
-        kwargs['command'] = cmd
-        kwargs['input'] = []
-        kwargs['output'] = 'gschemas.compiled'
+        cmd = [state.find_program('glib-compile-schemas'), '--targetdir', outdir, srcdir]
+        ct_kwargs = T.cast(T.Dict[str, T.Any], kwargs.copy())
+        ct_kwargs['command'] = cmd
+        ct_kwargs['input'] = []
+        ct_kwargs['output'] = 'gschemas.compiled'
         if state.subdir == '':
             targetname = 'gsettings-compile'
         else:
             targetname = 'gsettings-compile-' + state.subdir.replace('/', '_')
-        target_g = build.CustomTarget(targetname, state.subdir, state.subproject, kwargs)
+        target_g = build.CustomTarget(targetname, state.subdir, state.subproject, ct_kwargs)
+        self._devenv_prepend('GSETTINGS_SCHEMA_DIR', os.path.join(state.environment.get_build_dir(), state.subdir))
         return ModuleReturnValue(target_g, [target_g])
 
-    @permittedKwargs({'sources', 'media', 'symlink_media', 'languages'})
-    def yelp(self, state, args, kwargs):
-        if len(args) < 1:
-            raise MesonException('Yelp requires a project id')
-
+    @typed_pos_args('gnome.yelp', str, varargs=str)
+    @typed_kwargs(
+        'gnome.yelp',
+        KwargInfo(
+            'languages', ContainerTypeInfo(list, str),
+            listify=True, default=[],
+            deprecated='0.43.0',
+            deprecated_message='Use a LINGUAS file in the source directory instead',
+        ),
+        KwargInfo('media', ContainerTypeInfo(list, str), listify=True, default=[]),
+        KwargInfo('sources', ContainerTypeInfo(list, str), listify=True, default=[]),
+        KwargInfo('symlink_media', bool, default=True),
+    )
+    def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Yelp') -> ModuleReturnValue:
         project_id = args[0]
-        sources = mesonlib.stringlistify(kwargs.pop('sources', []))
+        sources = kwargs['sources']
+        if args[1]:
+            FeatureDeprecated.single_use('gnome.yelp more than one positional argument', '0.60.0',
+                                         state.subproject, 'use the "sources" keyword argument instead.', state.current_node)
         if not sources:
-            if len(args) > 1:
-                sources = mesonlib.stringlistify(args[1:])
+            sources = args[1]
             if not sources:
                 raise MesonException('Yelp requires a list of sources')
-        source_str = '@@'.join(sources)
-
-        langs = mesonlib.stringlistify(kwargs.pop('languages', []))
-        if langs:
-            mlog.deprecation('''The "languages" argument of gnome.yelp() is deprecated.
-Use a LINGUAS file in the sources directory instead.
-This will become a hard error in the future.''')
-
-        media = mesonlib.stringlistify(kwargs.pop('media', []))
-        symlinks = kwargs.pop('symlink_media', True)
-
-        if not isinstance(symlinks, bool):
-            raise MesonException('symlink_media must be a boolean')
-
-        if kwargs:
-            raise MesonException('Unknown arguments passed: {}'.format(', '.join(kwargs.keys())))
-
-        script = state.environment.get_build_command()
-        args = ['--internal',
-                'yelphelper',
-                'install',
-                '--subdir=' + state.subdir,
-                '--id=' + project_id,
-                '--installdir=' + os.path.join(state.environment.get_datadir(), 'help'),
-                '--sources=' + source_str]
-        if symlinks:
-            args.append('--symlinks=true')
-        if media:
-            args.append('--media=' + '@@'.join(media))
-        if langs:
-            args.append('--langs=' + '@@'.join(langs))
-        inscript = build.RunScript(script, 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[0],
-                                    potargs[1:], [], 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[0],
-                                   poargs[1:], [], state.subdir, state.subproject)
-
-        rv = [inscript, pottarget, potarget]
-        return ModuleReturnValue(None, rv)
-
-    @FeatureNewKwargs('gnome.gtkdoc', '0.52.0', ['check'])
-    @FeatureNewKwargs('gnome.gtkdoc', '0.48.0', ['c_args'])
-    @FeatureNewKwargs('gnome.gtkdoc', '0.48.0', ['module_version'])
-    @FeatureNewKwargs('gnome.gtkdoc', '0.37.0', ['namespace', 'mode'])
-    @permittedKwargs({'main_xml', 'main_sgml', 'src_dir', 'dependencies', 'install',
-                      'install_dir', 'scan_args', 'scanobjs_args', 'gobject_typesfile',
-                      'fixxref_args', 'html_args', 'html_assets', 'content_files',
-                      'mkdb_args', 'ignore_headers', 'include_directories',
-                      'namespace', 'mode', 'expand_content_files', 'module_version',
-                      'c_args'})
-    def gtkdoc(self, state, args, kwargs):
-        if len(args) != 1:
-            raise MesonException('Gtkdoc must have one positional argument.')
+        elif args[1]:
+            mlog.warning('"gnome.yelp" ignores positional sources arguments when the "sources" keyword argument is set')
+        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['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 = [itstool, '-o', pot_file] + 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)
+                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 = [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)
+
+        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(
+        'gnome.gtkdoc',
+        KwargInfo('c_args', ContainerTypeInfo(list, str), since='0.48.0', default=[], listify=True),
+        KwargInfo('check', bool, default=False, since='0.52.0'),
+        KwargInfo('content_files', ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True),
+        KwargInfo(
+            'dependencies',
+            ContainerTypeInfo(list, (Dependency, build.SharedLibrary, build.StaticLibrary)),
+            listify=True, default=[]),
+        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, mesonlib.File)), default=[], listify=True),
+        KwargInfo('html_args', 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',
+            ContainerTypeInfo(list, (str, build.IncludeDirs)),
+            listify=True, default=[]),
+        KwargInfo('install', bool, default=True),
+        KwargInfo('install_dir', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('main_sgml', (str, NoneType)),
+        KwargInfo('main_xml', (str, NoneType)),
+        KwargInfo('mkdb_args', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo(
+            'mode', str, default='auto', since='0.37.0',
+             validator=in_set_validator({'xml', 'sgml', 'none', 'auto'})),
+        KwargInfo('module_version', str, default='', since='0.48.0'),
+        KwargInfo('namespace', str, default='', since='0.37.0'),
+        KwargInfo('scan_args', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('scanobjs_args', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('src_dir', ContainerTypeInfo(list, (str, build.IncludeDirs)), listify=True, required=True),
+    )
+    def gtkdoc(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GtkDoc') -> ModuleReturnValue:
         modulename = args[0]
-        if not isinstance(modulename, str):
-            raise MesonException('Gtkdoc arg must be string.')
-        if 'src_dir' not in kwargs:
-            raise MesonException('Keyword argument src_dir missing.')
-        main_file = kwargs.get('main_sgml', '')
-        if not isinstance(main_file, str):
-            raise MesonException('Main sgml keyword argument must be a string.')
-        main_xml = kwargs.get('main_xml', '')
-        if not isinstance(main_xml, str):
-            raise MesonException('Main xml keyword argument must be a string.')
-        moduleversion = kwargs.get('module_version', '')
-        if not isinstance(moduleversion, str):
-            raise MesonException('Module version keyword argument must be a string.')
-        if main_xml != '':
-            if main_file != '':
-                raise MesonException('You can only specify main_xml or main_sgml, not both.')
+        main_file = kwargs['main_sgml']
+        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_sgml are exclusive arguments')
             main_file = main_xml
+        moduleversion = kwargs['module_version']
         targetname = modulename + ('-' + moduleversion if moduleversion else '') + '-doc'
         command = state.environment.get_build_command()
 
-        namespace = kwargs.get('namespace', '')
-        mode = kwargs.get('mode', 'auto')
-        VALID_MODES = ('xml', 'sgml', 'none', 'auto')
-        if mode not in VALID_MODES:
-            raise MesonException('gtkdoc: Mode {} is not a valid mode: {}'.format(mode, VALID_MODES))
+        namespace = kwargs['namespace']
+
+        def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]:
+            for f in files:
+                if isinstance(f, mesonlib.File):
+                    yield f.absolute_path(state.environment.get_source_dir(), state.environment.get_build_dir())
+                else:
+                    yield os.path.join(state.environment.get_source_dir(), state.subdir, f)
 
-        src_dirs = mesonlib.extract_as_list(kwargs, 'src_dir')
-        header_dirs = []
+        src_dirs = kwargs['src_dir']
+        header_dirs: T.List[str] = []
         for src_dir in src_dirs:
-            if hasattr(src_dir, 'held_object'):
-                src_dir = src_dir.held_object
-                if not isinstance(src_dir, build.IncludeDirs):
-                    raise MesonException('Invalid keyword argument for src_dir.')
-                for inc_dir in src_dir.get_incdirs():
-                    header_dirs.append(os.path.join(state.environment.get_source_dir(),
-                                                    src_dir.get_curdir(), inc_dir))
-                    header_dirs.append(os.path.join(state.environment.get_build_dir(),
-                                                    src_dir.get_curdir(), inc_dir))
+            if isinstance(src_dir, build.IncludeDirs):
+                header_dirs.extend(src_dir.to_string_list(state.environment.get_source_dir(),
+                                                          state.environment.get_build_dir()))
             else:
                 header_dirs.append(src_dir)
 
-        args = ['--internal', 'gtkdoc',
-                '--sourcedir=' + state.environment.get_source_dir(),
-                '--builddir=' + state.environment.get_build_dir(),
-                '--subdir=' + state.subdir,
-                '--headerdirs=' + '@@'.join(header_dirs),
-                '--mainfile=' + main_file,
-                '--modulename=' + modulename,
-                '--moduleversion=' + moduleversion,
-                '--mode=' + mode]
+        t_args = ['--internal', 'gtkdoc',
+                  '--sourcedir=' + state.environment.get_source_dir(),
+                  '--builddir=' + state.environment.get_build_dir(),
+                  '--subdir=' + state.subdir,
+                  '--headerdirs=' + '@@'.join(header_dirs),
+                  '--mainfile=' + main_file,
+                  '--modulename=' + modulename,
+                  '--moduleversion=' + moduleversion,
+                  '--mode=' + kwargs['mode']]
         for tool in ['scan', 'scangobj', 'mkdb', 'mkhtml', 'fixxref']:
             program_name = 'gtkdoc-' + tool
-            program = self.interpreter.find_program_impl(program_name)
-            path = program.held_object.get_path()
-            args.append('--{}={}'.format(program_name, path))
+            program = state.find_program(program_name)
+            path = program.get_path()
+            t_args.append(f'--{program_name}={path}')
         if namespace:
-            args.append('--namespace=' + namespace)
-        args += self._unpack_args('--htmlargs=', 'html_args', kwargs)
-        args += self._unpack_args('--scanargs=', 'scan_args', kwargs)
-        args += self._unpack_args('--scanobjsargs=', 'scanobjs_args', kwargs)
-        args += self._unpack_args('--gobjects-types-file=', 'gobject_typesfile', kwargs, state)
-        args += self._unpack_args('--fixxrefargs=', 'fixxref_args', kwargs)
-        args += self._unpack_args('--mkdbargs=', 'mkdb_args', kwargs)
-        args += self._unpack_args('--html-assets=', 'html_assets', kwargs, state)
+            t_args.append('--namespace=' + namespace)
+        if state.environment.need_exe_wrapper() and not isinstance(state.environment.get_exe_wrapper(), EmptyExternalProgram):
+            t_args.append('--run=' + ' '.join(state.environment.get_exe_wrapper().get_command()))
+        t_args.append(f'--htmlargs={"@@".join(kwargs["html_args"])}')
+        t_args.append(f'--scanargs={"@@".join(kwargs["scan_args"])}')
+        t_args.append(f'--scanobjsargs={"@@".join(kwargs["scanobjs_args"])}')
+        t_args.append(f'--gobjects-types-file={"@@".join(abs_filenames(kwargs["gobject_typesfile"]))}')
+        t_args.append(f'--fixxrefargs={"@@".join(kwargs["fixxref_args"])}')
+        t_args.append(f'--mkdbargs={"@@".join(kwargs["mkdb_args"])}')
+        t_args.append(f'--html-assets={"@@".join(abs_filenames(kwargs["html_assets"]))}')
 
-        depends = []
+        depends: T.List['build.GeneratedTypes'] = []
         content_files = []
-        for s in mesonlib.extract_as_list(kwargs, 'content_files'):
-            if hasattr(s, 'held_object'):
-                s = s.held_object
+        for s in kwargs['content_files']:
             if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)):
                 depends.append(s)
                 for o in s.get_outputs():
@@ -1002,56 +1379,47 @@
                     content_files.append(os.path.join(state.environment.get_source_dir(),
                                                       state.subdir,
                                                       gen_src))
-            elif isinstance(s, str):
+            else:
                 content_files.append(os.path.join(state.environment.get_source_dir(),
                                                   state.subdir,
                                                   s))
-            else:
-                raise MesonException(
-                    'Invalid object type: {!r}'.format(s.__class__.__name__))
-        args += ['--content-files=' + '@@'.join(content_files)]
-
-        args += self._unpack_args('--expand-content-files=', 'expand_content_files', kwargs, state)
-        args += self._unpack_args('--ignore-headers=', 'ignore_headers', kwargs)
-        args += self._unpack_args('--installdir=', 'install_dir', kwargs)
-        args += self._get_build_args(kwargs, state, depends)
+        t_args += ['--content-files=' + '@@'.join(content_files)]
+
+        t_args.append(f'--expand-content-files={"@@".join(abs_filenames(kwargs["expand_content_files"]))}')
+        t_args.append(f'--ignore-headers={"@@".join(kwargs["ignore_headers"])}')
+        t_args.append(f'--installdir={"@@".join(kwargs["install_dir"])}')
+        t_args += self._get_build_args(kwargs['c_args'], kwargs['include_directories'],
+                                       kwargs['dependencies'], state, depends)
         custom_kwargs = {'output': modulename + '-decl.txt',
-                         'command': command + args,
+                         'command': command + t_args,
                          'depends': depends,
                          'build_always_stale': True,
                          }
         custom_target = build.CustomTarget(targetname, state.subdir, state.subproject, custom_kwargs)
         alias_target = build.AliasTarget(targetname, [custom_target], state.subdir, state.subproject)
-        if kwargs.get('check', False):
-            check_cmd = self.interpreter.find_program_impl('gtkdoc-check')
+        if kwargs['check']:
+            check_cmd = state.find_program('gtkdoc-check')
             check_env = ['DOC_MODULE=' + modulename,
                          'DOC_MAIN_SGML_FILE=' + main_file]
-            check_args = [targetname + '-check', check_cmd]
-            check_kwargs = {'env': check_env,
-                            'workdir': os.path.join(state.environment.get_build_dir(), state.subdir),
-                            'depends': custom_target}
-            self.interpreter.add_test(state.current_node, check_args, check_kwargs, True)
-        res = [custom_target, alias_target]
-        if kwargs.get('install', True):
-            res.append(build.RunScript(command, args))
+            check_args = (targetname + '-check', check_cmd)
+            check_workdir = os.path.join(state.environment.get_build_dir(), state.subdir)
+            state.test(check_args, env=check_env, workdir=check_workdir, depends=[custom_target])
+        res: T.List[T.Union[build.Target, build.ExecutableSerialisation]] = [custom_target, alias_target]
+        if kwargs['install']:
+            res.append(state.backend.get_executable_serialisation(command + t_args, tag='doc'))
         return ModuleReturnValue(custom_target, res)
 
-    def _get_build_args(self, kwargs, state, depends):
-        args = []
-        deps = extract_as_list(kwargs, 'dependencies', unholder=True)
-        cflags = []
-        cflags.extend(mesonlib.stringlistify(kwargs.pop('c_args', [])))
-        deps_cflags, internal_ldflags, external_ldflags, gi_includes = \
+    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]:
+        args: T.List[str] = []
+        cflags = c_args.copy()
+        deps_cflags, internal_ldflags, external_ldflags, *_ = \
             self._get_dependencies_flags(deps, state, depends, include_rpath=True)
-        inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories')
-        for incd in inc_dirs:
-            if not isinstance(incd.held_object, (str, build.IncludeDirs)):
-                raise MesonException(
-                    'Gir include dirs should be include_directories().')
 
         cflags.extend(deps_cflags)
-        cflags.extend(get_include_args(inc_dirs))
-        ldflags = []
+        cflags.extend(state.get_include_args(inc_dirs))
+        ldflags: T.List[str] = []
         ldflags.extend(internal_ldflags)
         ldflags.extend(external_ldflags)
 
@@ -1074,90 +1442,71 @@
         return args
 
     @noKwargs
-    def gtkdoc_html_dir(self, state, args, kwargs):
-        if len(args) != 1:
-            raise MesonException('Must have exactly one argument.')
-        modulename = args[0]
-        if not isinstance(modulename, str):
-            raise MesonException('Argument must be a string')
-        return ModuleReturnValue(os.path.join('share/gtk-doc/html', modulename), [])
-
-    @staticmethod
-    def _unpack_args(arg, kwarg_name, kwargs, expend_file_state=None):
-        if kwarg_name not in kwargs:
-            return []
-
-        new_args = mesonlib.extract_as_list(kwargs, kwarg_name)
-        args = []
-        for i in new_args:
-            if expend_file_state and isinstance(i, mesonlib.File):
-                i = i.absolute_path(expend_file_state.environment.get_source_dir(), expend_file_state.environment.get_build_dir())
-            elif expend_file_state and isinstance(i, str):
-                i = os.path.join(expend_file_state.environment.get_source_dir(), expend_file_state.subdir, i)
-            elif not isinstance(i, str):
-                raise MesonException(kwarg_name + ' values must be strings.')
-            args.append(i)
-
-        if args:
-            return [arg + '@@'.join(args)]
-
-        return []
-
-    def _get_autocleanup_args(self, kwargs, glib_version):
-        if not mesonlib.version_compare(glib_version, '>= 2.49.1'):
-            # Warn if requested, silently disable if not
-            if 'autocleanup' in kwargs:
-                mlog.warning('Glib version ({}) is too old to support the \'autocleanup\' '
-                             'kwarg, need 2.49.1 or newer'.format(glib_version))
-            return []
-        autocleanup = kwargs.pop('autocleanup', 'all')
-        values = ('none', 'objects', 'all')
-        if autocleanup not in values:
-            raise MesonException('gdbus_codegen does not support {!r} as an autocleanup value, '
-                                 'must be one of: {!r}'.format(autocleanup, ', '.join(values)))
-        return ['--c-generate-autocleanup', autocleanup]
-
-    @FeatureNewKwargs('build target', '0.46.0', ['install_header', 'install_dir', 'sources'])
-    @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
-    @FeatureNewKwargs('build target', '0.47.0', ['extra_args', 'autocleanup'])
-    @permittedKwargs({'interface_prefix', 'namespace', 'extra_args', 'autocleanup', 'object_manager', 'build_by_default',
-                      'annotations', 'docbook', 'install_header', 'install_dir', 'sources'})
-    def gdbus_codegen(self, state, args, kwargs):
-        if len(args) not in (1, 2):
-            raise MesonException('gdbus_codegen takes at most two arguments, name and xml file.')
+    @typed_pos_args('gnome.gtkdoc_html_dir', str)
+    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, mesonlib.File)])
+    @typed_kwargs(
+        'gnome.gdbus_codegen',
+        _BUILD_BY_DEFAULT.evolve(since='0.40.0'),
+        KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File)), since='0.46.0', default=[], listify=True),
+        KwargInfo('extra_args', ContainerTypeInfo(list, str), since='0.47.0', default=[], listify=True),
+        KwargInfo('interface_prefix', (str, NoneType)),
+        KwargInfo('namespace', (str, NoneType)),
+        KwargInfo('object_manager', bool, default=False),
+        KwargInfo(
+            'annotations', ContainerTypeInfo(list, (list, str)),
+            default=[],
+            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'),
+        KwargInfo('docbook', (str, NoneType)),
+        KwargInfo(
+            '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['FileOrString']],
+                      kwargs: 'GdbusCodegen') -> ModuleReturnValue:
         namebase = args[0]
-        xml_files = args[1:]
-        cmd = [self.interpreter.find_program_impl('gdbus-codegen')]
-        extra_args = mesonlib.stringlistify(kwargs.pop('extra_args', []))
-        cmd += extra_args
+        xml_files: T.List['FileOrString'] = [args[1]] if args[1] else []
+        cmd: T.List[T.Union['ExternalProgram', str]] = [state.find_program('gdbus-codegen')]
+        cmd.extend(kwargs['extra_args'])
+
         # Autocleanup supported?
         glib_version = self._get_native_glib_version(state)
-        cmd += self._get_autocleanup_args(kwargs, glib_version)
-        if 'interface_prefix' in kwargs:
-            cmd += ['--interface-prefix', kwargs.pop('interface_prefix')]
-        if 'namespace' in kwargs:
-            cmd += ['--c-namespace', kwargs.pop('namespace')]
-        if kwargs.get('object_manager', False):
-            cmd += ['--c-generate-object-manager']
-        if 'sources' in kwargs:
-            xml_files += mesonlib.listify(kwargs.pop('sources'))
-        build_by_default = kwargs.get('build_by_default', False)
+        if not mesonlib.version_compare(glib_version, '>= 2.49.1'):
+            # Warn if requested, silently disable if not
+            if kwargs['autocleanup'] != 'default':
+                mlog.warning(f'Glib version ({glib_version}) is too old to support the \'autocleanup\' '
+                             'kwarg, need 2.49.1 or newer')
+        else:
+            # Handle legacy glib versions that don't have autocleanup
+            ac = kwargs['autocleanup']
+            if ac == 'default':
+                ac = 'all'
+            cmd.extend(['--c-generate-autocleanup', ac])
+
+        if kwargs['interface_prefix'] is not None:
+            cmd.extend(['--interface-prefix', kwargs['interface_prefix']])
+        if kwargs['namespace'] is not None:
+            cmd.extend(['--c-namespace', kwargs['namespace']])
+        if kwargs['object_manager']:
+            cmd.extend(['--c-generate-object-manager'])
+        xml_files.extend(kwargs['sources'])
+        build_by_default = kwargs['build_by_default']
 
         # Annotations are a bit ugly in that they are a list of lists of strings...
-        annotations = kwargs.pop('annotations', [])
-        if not isinstance(annotations, list):
-            raise MesonException('annotations takes a list')
-        if annotations and isinstance(annotations, list) and not isinstance(annotations[0], list):
-            annotations = [annotations]
-
-        for annotation in annotations:
-            if len(annotation) != 3 or not all(isinstance(i, str) for i in annotation):
-                raise MesonException('Annotations must be made up of 3 strings for ELEMENT, KEY, and VALUE')
-            cmd += ['--annotate'] + annotation
+        for annot in kwargs['annotations']:
+            cmd.append('--annotate')
+            cmd.extend(annot)
 
         targets = []
-        install_header = kwargs.get('install_header', False)
-        install_dir = kwargs.get('install_dir', state.environment.coredata.get_builtin_option('includedir'))
+        install_header = kwargs['install_header']
+        install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('includedir'))
+        assert isinstance(install_dir, str), 'for mypy'
 
         output = namebase + '.c'
         # Added in https://gitlab.gnome.org/GNOME/glib/commit/e4d68c7b3e8b01ab1a4231bf6da21d045cb5a816 (2.55.2)
@@ -1169,10 +1518,8 @@
                              'build_by_default': build_by_default
                              }
         else:
-            if 'docbook' in kwargs:
+            if kwargs['docbook'] is not None:
                 docbook = kwargs['docbook']
-                if not isinstance(docbook, str):
-                    raise MesonException('docbook value must be a string.')
 
                 cmd += ['--generate-docbook', docbook]
 
@@ -1214,7 +1561,7 @@
         hfile_custom_target = build.CustomTarget(output, state.subdir, state.subproject, custom_kwargs)
         targets.append(hfile_custom_target)
 
-        if 'docbook' in kwargs:
+        if kwargs['docbook'] is not None:
             docbook = kwargs['docbook']
             if not isinstance(docbook, str):
                 raise MesonException('docbook value must be a string.')
@@ -1246,78 +1593,53 @@
 
         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'})
-    def mkenums(self, state, args, kwargs):
-        if len(args) != 1:
-            raise MesonException('Mkenums requires one positional argument.')
+    @typed_pos_args('gnome.mkenums', str)
+    @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(
-                    'Mkenums does not take a %s keyword argument.' % (arg, ))
-        cmd = [self.interpreter.find_program_impl(['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
-            custom_kwargs['install'] = install_header
-            if 'install_dir' not in custom_kwargs:
-                custom_kwargs['install_dir'] = \
-                    state.environment.coredata.get_builtin_option('includedir')
-            h_target = self._make_mkenum_custom_target(state, h_sources,
-                                                       h_output, h_cmd,
-                                                       custom_kwargs)
+            h_sources = [h_template] + 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:
@@ -1325,203 +1647,206 @@
             # 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
-            # Never install the C file. Complain on bug tracker if you need it.
-            custom_kwargs['install'] = False
-            if h_template is not None:
-                if 'depends' in custom_kwargs:
-                    custom_kwargs['depends'] += [h_target]
-                else:
-                    custom_kwargs['depends'] = h_target
-            c_target = self._make_mkenum_custom_target(state, c_sources,
-                                                       c_output, c_cmd,
-                                                       custom_kwargs)
+            c_sources = [c_template] + 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_builtin_option('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')
-    def mkenums_simple(self, state, args, kwargs):
-        hdr_filename = args[0] + '.h'
-        body_filename = 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('mkenums_simple() does not take a %s keyword argument' % (arg, ))
-
-        # 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', '')
+    @typed_pos_args('gnome.mkenums_simple', str)
+    @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'
+
+        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:
-            fhead += '#include "%s"\n' % os.path.basename(str(hdr))
-        fhead += '''
-#define C_ENUM(v) ((gint) v)
-#define C_FLAGS(v) ((guint) v)
-'''
-        c_file_kwargs['fhead'] = fhead
-
-        c_file_kwargs['fprod'] = '''
-/* enumerations from "@basename@" */
-'''
-
-        c_file_kwargs['vhead'] = '''
-GType
-%s@enum_name@_get_type (void)
-{
-  static volatile gsize gtype_id = 0;
-  static const G@Type@Value values[] = {''' % func_prefix
-
-        c_file_kwargs['vprod'] = '    { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },'
-
-        c_file_kwargs['vtail'] = '''    { 0, NULL, NULL }
-  };
-  if (g_once_init_enter (>ype_id)) {
-    GType new_type = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
-    g_once_init_leave (>ype_id, new_type);
-  }
-  return (GType) gtype_id;
-}'''
+        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_cmd.extend(['--fhead', fhead])
+
+        c_cmd.append('--fprod')
+        c_cmd.append(textwrap.dedent(
+            '''
+            /* enumerations from "@basename@" */
+            '''))
+
+        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[] = {{'''))
+
+        c_cmd.extend(['--vprod', '    { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },'])
+
+        c_cmd.append('--vtail')
+        c_cmd.append(textwrap.dedent(
+            '''    { 0, NULL, NULL }
+            };
+            if (g_once_init_enter (>ype_id)) {
+                GType new_type = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
+                g_once_init_leave (>ype_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_file_kwargs['fhead'] = '''#pragma once
-
-#include 
-{}
-
-G_BEGIN_DECLS
-'''.format(header_prefix)
-
-        h_file_kwargs['fprod'] = '''
-/* enumerations from "@basename@" */
-'''
-
-        h_file_kwargs['vhead'] = '''
-{}
-GType {}@enum_name@_get_type (void);
-#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ ({}@enum_name@_get_type())'''.format(decl_decorator, func_prefix, func_prefix)
-
-        h_file_kwargs['ftail'] = '''
-G_END_DECLS'''
+        h_cmd = cmd.copy()
 
-        rv = self.mkenums(state, [hdr_filename], h_file_kwargs)
-        h_file = rv.return_value
+        h_cmd.append('--fhead')
+        h_cmd.append(textwrap.dedent(
+            f'''#pragma once
+
+            #include 
+            {header_prefix}
+
+            G_BEGIN_DECLS
+            '''))
+
+        h_cmd.append('--fprod')
+        h_cmd.append(textwrap.dedent(
+            '''
+            /* enumerations from "@basename@" */
+            '''))
+
+        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())'''))
+
+        h_cmd.append('--ftail')
+        h_cmd.append(textwrap.dedent(
+            '''
+            G_END_DECLS'''))
+        h_cmd.append('@INPUT@')
+
+        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(state, sources, output, cmd, kwargs):
+    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],
+            *,
+            install: bool = False,
+            install_dir: T.Optional[T.Sequence[T.Union[str, bool]]] = None,
+            depends: T.Optional[T.List[CustomTarget]] = 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,
+            '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': 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)
 
-    @permittedKwargs({'sources', 'prefix', 'install_header', 'install_dir', 'stdinc',
-                      'nostdinc', 'internal', 'skip_source', 'valist_marshallers',
-                      'extra_args'})
-    def genmarshal(self, state, args, kwargs):
-        if len(args) != 1:
-            raise MesonException(
-                'Genmarshal requires one positional argument.')
+    @typed_pos_args('gnome.genmarshal', str)
+    @typed_kwargs(
+        'gnome.genmarshal',
+        DEPEND_FILES_KW.evolve(since='0.61.0'),
+        DEPENDS_KW.evolve(since='0.61.0'),
+        INSTALL_KW.evolve(name='install_header'),
+        KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
+        KwargInfo('install_dir', (str, NoneType)),
+        KwargInfo('internal', bool, default=False),
+        KwargInfo('nostdinc', bool, default=False),
+        KwargInfo('prefix', (str, NoneType)),
+        KwargInfo('skip_source', bool, default=False),
+        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),
+    )
+    def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarshal') -> ModuleReturnValue:
         output = 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.')
+        sources = kwargs['sources']
 
         new_genmarshal = mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.3')
 
-        cmd = [self.interpreter.find_program_impl('glib-genmarshal')]
-        known_kwargs = ['internal', 'nostdinc', 'skip_source', 'stdinc',
-                        'valist_marshallers', 'extra_args']
-        known_custom_target_kwargs = ['build_always', 'depends',
-                                      'depend_files', 'install_dir',
-                                      'install_header']
-        for arg, value in kwargs.items():
-            if arg == 'prefix':
-                cmd += ['--prefix', value]
-            elif arg == 'extra_args':
-                if new_genmarshal:
-                    cmd += mesonlib.stringlistify(value)
-                else:
-                    mlog.warning('The current version of GLib does not support extra arguments \n'
-                                 'for glib-genmarshal. You need at least GLib 2.53.3. See ',
-                                 mlog.bold('https://github.com/mesonbuild/meson/pull/2049'))
-            elif arg in known_kwargs and value:
-                cmd += ['--' + arg.replace('_', '-')]
-            elif arg not in known_custom_target_kwargs:
-                raise MesonException(
-                    'Genmarshal does not take a %s keyword argument.' % (
-                        arg, ))
+        cmd: T.List[T.Union['ExternalProgram', str]] = [state.find_program('glib-genmarshal')]
+        if kwargs['prefix']:
+            cmd.extend(['--prefix', kwargs['prefix']])
+        if kwargs['extra_args']:
+            if new_genmarshal:
+                cmd.extend(kwargs['extra_args'])
+            else:
+                mlog.warning('The current version of GLib does not support extra arguments \n'
+                             'for glib-genmarshal. You need at least GLib 2.53.3. See ',
+                             mlog.bold('https://github.com/mesonbuild/meson/pull/2049'))
+        for k in ['internal', 'nostdinc', 'skip_source', 'stdinc', 'valist_marshallers']:
+            # Mypy can't figure out that this is correct
+            if kwargs[k]:                                            # type: ignore
+                cmd.append(f'--{k.replace("_", "-")}')
 
-        install_header = kwargs.pop('install_header', False)
-        install_dir = kwargs.pop('install_dir', None)
+        install_header = kwargs['install_header']
+        install_dir: T.List[T.Union[str, bool]] = kwargs['install_dir'] or []
 
-        custom_kwargs = {
+
+        custom_kwargs: T.Dict[str, T.Any] = {
             'input': sources,
+            'depend_files': kwargs['depend_files'],
+            'install_dir': kwargs['install_dir'],
         }
 
         # https://github.com/GNOME/glib/commit/0fbc98097fac4d3e647684f344e508abae109fdf
@@ -1530,10 +1855,6 @@
         else:
             custom_kwargs['capture'] = True
 
-        for arg in known_custom_target_kwargs:
-            if arg in kwargs:
-                custom_kwargs[arg] = kwargs[arg]
-
         header_file = output + '.h'
         custom_kwargs['command'] = cmd + ['--body', '@INPUT@']
         if mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.4'):
@@ -1543,8 +1864,7 @@
         body = build.CustomTarget(output + '_c', state.subdir, state.subproject, custom_kwargs)
 
         custom_kwargs['install'] = install_header
-        if install_dir is not None:
-            custom_kwargs['install_dir'] = install_dir
+        custom_kwargs['install_dir'] = install_dir
         if new_genmarshal:
             cmd += ['--pragma-once']
         custom_kwargs['command'] = cmd + ['--header', '@INPUT@']
@@ -1554,18 +1874,8 @@
         rv = [body, header]
         return ModuleReturnValue(rv, rv)
 
-    @staticmethod
-    def _vapi_args_to_command(prefix, variable, kwargs, accept_vapi=False):
-        arg_list = mesonlib.extract_as_list(kwargs, variable)
-        ret = []
-        for arg in arg_list:
-            if not isinstance(arg, str):
-                types = 'strings' + ' or InternalDependencys' if accept_vapi else ''
-                raise MesonException('All {} must be {}'.format(variable, types))
-            ret.append(prefix + arg)
-        return ret
-
-    def _extract_vapi_packages(self, state, kwargs):
+    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]]:
         '''
         Packages are special because we need to:
         - Get a list of packages for the .deps file
@@ -1573,18 +1883,14 @@
         - Get package name from VapiTargets
         - Add include dirs for any VapiTargets
         '''
-        arg_list = kwargs.get('packages')
-        if not arg_list:
-            return [], [], [], []
-        arg_list = mesonlib.listify(arg_list)
-        vapi_depends = []
-        vapi_packages = []
-        vapi_includes = []
-        ret = []
+        if not packages:
+            return [], [], [], [], []
+        vapi_depends: T.List[build.Target] = []
+        vapi_packages: T.List[str] = []
+        vapi_includes: T.List[str] = []
+        vapi_args: T.List[str] = []
         remaining_args = []
-        for arg in arg_list:
-            if hasattr(arg, 'held_object'):
-                arg = arg.held_object
+        for arg in packages:
             if isinstance(arg, InternalDependency):
                 targets = [t for t in arg.sources if isinstance(t, VapiTarget)]
                 for target in targets:
@@ -1593,30 +1899,31 @@
                     outdir = os.path.join(state.environment.get_build_dir(),
                                           target.get_subdir())
                     outfile = target.get_outputs()[0][:-5] # Strip .vapi
-                    ret.append('--vapidir=' + outdir)
-                    ret.append('--girdir=' + outdir)
-                    ret.append('--pkg=' + outfile)
+                    vapi_args.append('--vapidir=' + outdir)
+                    vapi_args.append('--girdir=' + outdir)
+                    vapi_args.append('--pkg=' + outfile)
                     vapi_depends.append(target)
                     vapi_packages.append(outfile)
                     vapi_includes.append(srcdir)
             else:
+                assert isinstance(arg, str), 'for mypy'
+                vapi_args.append(f'--pkg={arg}')
                 vapi_packages.append(arg)
                 remaining_args.append(arg)
 
-        kwargs['packages'] = remaining_args
-        vapi_args = ret + self._vapi_args_to_command('--pkg=', 'packages', kwargs, accept_vapi=True)
-        return vapi_args, vapi_depends, vapi_packages, vapi_includes
+        # TODO: this is supposed to take IncludeDirs, but it never worked
+        return vapi_args, vapi_depends, vapi_packages, vapi_includes, remaining_args
 
-    def _generate_deps(self, state, library, packages, install_dir):
+    def _generate_deps(self, state: 'ModuleState', library: str, packages: T.List[str], install_dir: str) -> build.Data:
         outdir = state.environment.scratch_dir
         fname = os.path.join(outdir, library + '.deps')
-        with open(fname, 'w') as ofile:
+        with open(fname, 'w', encoding='utf-8') as ofile:
             for package in packages:
                 ofile.write(package + '\n')
-        return build.Data(mesonlib.File(True, outdir, fname), install_dir)
+        return build.Data([mesonlib.File(True, outdir, fname)], install_dir, install_dir, mesonlib.FileMode(), state.subproject)
 
-    def _get_vapi_link_with(self, target):
-        link_with = []
+    def _get_vapi_link_with(self, target: build.CustomTarget) -> T.List[T.Union[build.BuildTarget, build.CustomTarget]]:
+        link_with: T.List[T.Union[build.BuildTarget, build.CustomTarget]] = []
         for dep in target.get_target_dependencies():
             if isinstance(dep, build.SharedLibrary):
                 link_with.append(dep)
@@ -1624,48 +1931,48 @@
                 link_with += self._get_vapi_link_with(dep)
         return link_with
 
-    @permittedKwargs({'sources', 'packages', 'metadata_dirs', 'gir_dirs',
-                      'vapi_dirs', 'install', 'install_dir'})
-    def generate_vapi(self, state, args, kwargs):
-        if len(args) != 1:
-            raise MesonException('The library name is required')
-
-        if not isinstance(args[0], str):
-            raise MesonException('The first argument must be the name of the library')
-        created_values = []
-
+    @typed_pos_args('gnome.generate_vapi', str)
+    @typed_kwargs(
+        'gnome.generate_vapi',
+        INSTALL_KW,
+        KwargInfo(
+            'sources',
+            ContainerTypeInfo(list, (str, GirTarget), allow_empty=False),
+            listify=True,
+            required=True,
+        ),
+        KwargInfo('install_dir', (str, NoneType)),
+        KwargInfo('vapi_dirs', ContainerTypeInfo(list, str), listify=True, default=[]),
+        KwargInfo('metadata_dirs', ContainerTypeInfo(list, str), listify=True, default=[]),
+        KwargInfo('gir_dirs', ContainerTypeInfo(list, str), listify=True, default=[]),
+        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] = []
         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)
-        pkg_cmd, vapi_depends, vapi_packages, vapi_includes = self._extract_vapi_packages(state, kwargs)
-        if 'VAPIGEN' in os.environ:
-            cmd = [self.interpreter.find_program_impl(os.environ['VAPIGEN'])]
-        else:
-            cmd = [self.interpreter.find_program_impl('vapigen')]
-        cmd += ['--quiet', '--library=' + library, '--directory=' + build_dir]
-        cmd += self._vapi_args_to_command('--vapidir=', 'vapi_dirs', kwargs)
-        cmd += self._vapi_args_to_command('--metadatadir=', 'metadata_dirs', kwargs)
-        cmd += self._vapi_args_to_command('--girdir=', 'gir_dirs', kwargs)
+        pkg_cmd, vapi_depends, vapi_packages, vapi_includes, packages = self._extract_vapi_packages(state, kwargs['packages'])
+        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'--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]
 
-        if 'sources' not in kwargs:
-            raise MesonException('sources are required to generate the vapi file')
-
-        inputs = mesonlib.extract_as_list(kwargs, 'sources')
+        inputs = kwargs['sources']
 
         link_with = []
         for i in inputs:
             if isinstance(i, str):
                 cmd.append(os.path.join(source_dir, i))
-            elif hasattr(i, 'held_object') and isinstance(i.held_object, GirTarget):
-                link_with += self._get_vapi_link_with(i.held_object)
+            elif isinstance(i, GirTarget):
+                link_with += self._get_vapi_link_with(i)
                 subdir = os.path.join(state.environment.get_build_dir(),
-                                      i.held_object.get_subdir())
-                gir_file = os.path.join(subdir, i.held_object.get_outputs()[0])
+                                      i.get_subdir())
+                gir_file = os.path.join(subdir, i.get_outputs()[0])
                 cmd.append(gir_file)
-            else:
-                raise MesonException('Input must be a str or GirTarget')
 
         vapi_output = library + '.vapi'
         custom_kwargs = {
@@ -1674,13 +1981,14 @@
             'output': vapi_output,
             'depends': vapi_depends,
         }
-        install_dir = kwargs.get('install_dir',
-                                 os.path.join(state.environment.coredata.get_builtin_option('datadir'),
-                                              'vala', 'vapi'))
-        if kwargs.get('install'):
-            custom_kwargs['install'] = kwargs['install']
-            custom_kwargs['install_dir'] = install_dir
+        datadir = state.environment.coredata.get_option(mesonlib.OptionKey('datadir'))
+        assert isinstance(datadir, str), 'for mypy'
+        install_dir = kwargs['install_dir'] or os.path.join(datadir, 'vala', 'vapi')
+        custom_kwargs['install'] = kwargs['install']
+        custom_kwargs['install_dir'] = install_dir
+        custom_kwargs['packages'] = packages
 
+        if kwargs['install']:
             # We shouldn't need this locally but we install it
             deps_target = self._generate_deps(state, library, vapi_packages, install_dir)
             created_values.append(deps_target)
@@ -1692,9 +2000,15 @@
         # - add relevant directories to include dirs
         incs = [build.IncludeDirs(state.subdir, ['.'] + vapi_includes, False)]
         sources = [vapi_target] + vapi_depends
-        rv = InternalDependency(None, incs, [], [], link_with, [], sources, [])
+        rv = InternalDependency(None, incs, [], [], link_with, [], sources, [], {})
         created_values.append(rv)
         return ModuleReturnValue(rv, created_values)
 
-def initialize(*args, **kwargs):
-    return GnomeModule(*args, **kwargs)
+def initialize(interp: 'Interpreter') -> GnomeModule:
+    mod = GnomeModule(interp)
+    mod.interpreter.append_holder_map(GResourceTarget, interpreter.CustomTargetHolder)
+    mod.interpreter.append_holder_map(GResourceHeaderTarget, interpreter.CustomTargetHolder)
+    mod.interpreter.append_holder_map(GirTarget, interpreter.CustomTargetHolder)
+    mod.interpreter.append_holder_map(TypelibTarget, interpreter.CustomTargetHolder)
+    mod.interpreter.append_holder_map(VapiTarget, interpreter.CustomTargetHolder)
+    return mod
diff -Nru meson-0.53.2/mesonbuild/modules/hotdoc.py meson-0.61.2/mesonbuild/modules/hotdoc.py
--- meson-0.53.2/mesonbuild/modules/hotdoc.py	2019-11-28 15:13:28.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/hotdoc.py	2021-12-26 16:24:25.000000000 +0000
@@ -22,10 +22,10 @@
 from mesonbuild.coredata import MesonException
 from . import ModuleReturnValue
 from . import ExtensionModule
-from . import get_include_args
-from ..dependencies import Dependency, InternalDependency, ExternalProgram
+from ..dependencies import Dependency, InternalDependency
 from ..interpreterbase import FeatureNew, InvalidArguments, noPosargs, noKwargs
 from ..interpreter import CustomTargetHolder
+from ..programs import ExternalProgram
 
 
 def ensure_list(value):
@@ -100,20 +100,19 @@
             # When an option expects a single value, the unambiguous way
             # to specify it is with =
             if isinstance(value, str):
-                self.cmd.extend(['%s=%s' % (option, value)])
+                self.cmd.extend([f'{option}={value}'])
             else:
                 self.cmd.extend([option, value])
 
     def check_extra_arg_type(self, arg, value):
-        value = getattr(value, 'held_object', value)
         if isinstance(value, list):
             for v in value:
                 self.check_extra_arg_type(arg, v)
             return
 
-        valid_types = (str, bool, mesonlib.File, build.IncludeDirs, build.CustomTarget, build.BuildTarget)
+        valid_types = (str, bool, mesonlib.File, build.IncludeDirs, build.CustomTarget, build.CustomTargetIndex, build.BuildTarget)
         if not isinstance(value, valid_types):
-            raise InvalidArguments('Argument "%s=%s" should be of type: %s.' % (
+            raise InvalidArguments('Argument "{}={}" should be of type: {}.'.format(
                 arg, value, [t.__name__ for t in valid_types]))
 
     def process_extra_args(self):
@@ -136,12 +135,11 @@
                     if force_list and not isinstance(value, list):
                         return [value], uvalue
                     return value, uvalue
-            raise MesonException("%s field value %s is not valid,"
-                                 " valid types are %s" % (argname, value,
-                                                          types))
+            raise MesonException(f"{argname} field value {value} is not valid,"
+                                 f" valid types are {types}")
         except KeyError:
             if mandatory:
-                raise MesonException("%s mandatory field not found" % argname)
+                raise MesonException(f"{argname} mandatory field not found")
 
             if default is not None:
                 return default, default
@@ -188,9 +186,8 @@
     def process_dependencies(self, deps):
         cflags = set()
         for dep in mesonlib.listify(ensure_list(deps)):
-            dep = getattr(dep, "held_object", dep)
             if isinstance(dep, InternalDependency):
-                inc_args = get_include_args(dep.include_directories)
+                inc_args = self.state.get_include_args(dep.include_directories)
                 cflags.update([self.replace_dirs_in_string(x)
                                for x in inc_args])
                 cflags.update(self.process_dependencies(dep.libraries))
@@ -212,6 +209,8 @@
                 self.add_extension_paths(dep.extra_extension_paths)
             elif isinstance(dep, build.CustomTarget) or isinstance(dep, build.BuildTarget):
                 self._dependencies.append(dep)
+            elif isinstance(dep, build.CustomTargetIndex):
+                self._dependencies.append(dep.target)
 
         return [f.strip('-I') for f in cflags]
 
@@ -232,7 +231,6 @@
     def flatten_config_command(self):
         cmd = []
         for arg in mesonlib.listify(self.cmd, flatten=True):
-            arg = getattr(arg, 'held_object', arg)
             if isinstance(arg, mesonlib.File):
                 arg = arg.absolute_path(self.state.environment.get_source_dir(),
                                         self.state.environment.get_build_dir())
@@ -242,9 +240,12 @@
                     cmd.append(os.path.join(self.builddir, arg.get_curdir(), inc_dir))
 
                 continue
-            elif isinstance(arg, build.CustomTarget) or isinstance(arg, build.BuildTarget):
+            elif isinstance(arg, (build.BuildTarget, build.CustomTarget)):
                 self._dependencies.append(arg)
                 arg = self.interpreter.backend.get_target_filename_abs(arg)
+            elif isinstance(arg, build.CustomTargetIndex):
+                self._dependencies.append(arg.target)
+                arg = self.interpreter.backend.get_target_filename_abs(arg)
 
             cmd.append(arg)
 
@@ -265,7 +266,7 @@
                 res.append(self.ensure_file(val))
             return res
 
-        if not isinstance(value, mesonlib.File):
+        if isinstance(value, str):
             return mesonlib.File.from_source_file(self.sourcedir, self.subdir, value)
 
         return value
@@ -277,21 +278,21 @@
             _dir = os.path.join(self.sourcedir, self.subdir, value)
 
         if not os.path.isdir(_dir):
-            raise InvalidArguments('"%s" is not a directory.' % _dir)
+            raise InvalidArguments(f'"{_dir}" is not a directory.')
 
         return os.path.relpath(_dir, os.path.join(self.builddir, self.subdir))
 
-    def check_forbiden_args(self):
+    def check_forbidden_args(self):
         for arg in ['conf_file']:
             if arg in self.kwargs:
-                raise InvalidArguments('Argument "%s" is forbidden.' % arg)
+                raise InvalidArguments(f'Argument "{arg}" is forbidden.')
 
     def add_include_path(self, path):
         self.include_paths[path] = path
 
     def make_targets(self):
-        self.check_forbiden_args()
-        file_types = (str, mesonlib.File)
+        self.check_forbidden_args()
+        file_types = (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex)
         self.process_known_arg("--index", file_types, mandatory=True, value_processor=self.ensure_file)
         self.process_known_arg("--project-version", str, mandatory=True)
         self.process_known_arg("--sitemap", file_types, mandatory=True, value_processor=self.ensure_file)
@@ -313,7 +314,7 @@
         hotdoc_config_name = fullname + '.json'
         hotdoc_config_path = os.path.join(
             self.builddir, self.subdir, hotdoc_config_name)
-        with open(hotdoc_config_path, 'w') as f:
+        with open(hotdoc_config_path, 'w', encoding='utf-8') as f:
             f.write('{}')
 
         self.cmd += ['--conf-file', hotdoc_config_path]
@@ -326,7 +327,7 @@
         for path in self.include_paths.keys():
             self.cmd.extend(['--include-path', path])
 
-        if self.state.environment.coredata.get_builtin_option('werror'):
+        if self.state.environment.coredata.get_option(mesonlib.OptionKey('werror', subproject=self.state.subproject)):
             self.cmd.append('--fatal-warning')
         self.generate_hotdoc_config()
 
@@ -350,13 +351,14 @@
 
         install_script = None
         if install is True:
-            install_script = HotdocRunScript(self.build_command, [
+            install_script = self.state.backend.get_executable_serialisation(self.build_command + [
                 "--internal", "hotdoc",
                 "--install", os.path.join(fullname, 'html'),
                 '--name', self.name,
                 '--builddir', os.path.join(self.builddir, self.subdir)] +
                 self.hotdoc.get_command() +
                 ['run', '--conf-file', hotdoc_config_name])
+            install_script.tag = 'doc'
 
         return (target, install_script)
 
@@ -371,7 +373,7 @@
     def config_path_method(self, *args, **kwargs):
         conf = self.held_object.hotdoc_conf.absolute_path(self.interpreter.environment.source_dir,
                                                           self.interpreter.environment.build_dir)
-        return self.interpreter.holderify(conf)
+        return conf
 
 
 class HotdocTarget(build.CustomTarget):
@@ -391,11 +393,6 @@
         return res
 
 
-class HotdocRunScript(build.RunScript):
-    def __init__(self, script, args):
-        super().__init__(script, args)
-
-
 class HotDocModule(ExtensionModule):
     @FeatureNew('Hotdoc Module', '0.48.0')
     def __init__(self, interpreter):
@@ -408,13 +405,15 @@
             from hotdoc.run_hotdoc import run  # noqa: F401
             self.hotdoc.run_hotdoc = run
         except Exception as e:
-            raise MesonException('hotdoc %s required but not found. (%s)' % (
-                MIN_HOTDOC_VERSION, e))
+            raise MesonException(f'hotdoc {MIN_HOTDOC_VERSION} required but not found. ({e})')
+        self.methods.update({
+            'has_extensions': self.has_extensions,
+            'generate_doc': self.generate_doc,
+        })
 
     @noKwargs
     def has_extensions(self, state, args, kwargs):
-        res = self.hotdoc.run_hotdoc(['--has-extension=%s' % extension for extension in args]) == 0
-        return ModuleReturnValue(res, [res])
+        return self.hotdoc.run_hotdoc([f'--has-extension={extension}' for extension in args]) == 0
 
     def generate_doc(self, state, args, kwargs):
         if len(args) != 1:
@@ -424,7 +423,7 @@
         project_name = args[0]
         builder = HotdocTargetBuilder(project_name, state, self.hotdoc, self.interpreter, kwargs)
         target, install_script = builder.make_targets()
-        targets = [HotdocTargetHolder(target, self.interpreter)]
+        targets = [target]
         if install_script:
             targets.append(install_script)
 
@@ -432,4 +431,6 @@
 
 
 def initialize(interpreter):
-    return HotDocModule(interpreter)
+    mod = HotDocModule(interpreter)
+    mod.interpreter.append_holder_map(HotdocTarget, HotdocTargetHolder)
+    return mod
diff -Nru meson-0.53.2/mesonbuild/modules/i18n.py meson-0.61.2/mesonbuild/modules/i18n.py
--- meson-0.53.2/mesonbuild/modules/i18n.py	2019-09-28 23:52:33.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/i18n.py	2021-12-26 16:24:25.000000000 +0000
@@ -12,14 +12,67 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from os import path
 import shutil
+import typing as T
 
-from os import path
-from .. import coredata, mesonlib, build, mlog
-from ..mesonlib import MesonException, run_once
-from . import ModuleReturnValue
-from . import ExtensionModule
-from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs
+from . import ExtensionModule, ModuleReturnValue
+from .. import build
+from .. import mesonlib
+from .. import mlog
+from ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, CT_INSTALL_DIR_KW, CT_INSTALL_TAG_KW, CT_OUTPUT_KW, INSTALL_KW, NoneType, in_set_validator
+from ..interpreterbase import FeatureNew
+from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args
+from ..scripts.gettext import read_linguas
+
+if T.TYPE_CHECKING:
+    from typing_extensions import Literal, TypedDict
+
+    from . import ModuleState
+    from ..build import Target
+    from ..interpreter import Interpreter
+    from ..interpreterbase import TYPE_var
+    from ..programs import ExternalProgram
+
+    class MergeFile(TypedDict):
+
+        input: T.List[T.Union[
+            str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex,
+            build.ExtractedObjects, build.GeneratedList, ExternalProgram,
+            mesonlib.File]]
+        output: T.List[str]
+        build_by_default: bool
+        install: bool
+        install_dir: T.List[T.Union[str, bool]]
+        install_tag: T.List[str]
+        args: T.List[str]
+        data_dirs: T.List[str]
+        po_dir: str
+        type: Literal['xml', 'desktop']
+
+    class Gettext(TypedDict):
+
+        args: T.List[str]
+        data_dirs: T.List[str]
+        install: bool
+        install_dir: T.Optional[str]
+        languages: T.List[str]
+        preset: T.Optional[str]
+
+
+_ARGS: KwargInfo[T.List[str]] = KwargInfo(
+    'args',
+    ContainerTypeInfo(list, str),
+    default=[],
+    listify=True,
+)
+
+_DATA_DIRS: KwargInfo[T.List[str]] = KwargInfo(
+    'data_dirs',
+    ContainerTypeInfo(list, str),
+    default=[],
+    listify=True
+)
 
 PRESET_ARGS = {
     'glib': [
@@ -57,134 +110,164 @@
 
 
 class I18nModule(ExtensionModule):
+    def __init__(self, interpreter: 'Interpreter'):
+        super().__init__(interpreter)
+        self.methods.update({
+            'merge_file': self.merge_file,
+            'gettext': self.gettext,
+        })
 
     @staticmethod
-    @run_once
-    def nogettext_warning():
-        mlog.warning('Gettext not found, all translation targets will be ignored.')
-        return ModuleReturnValue(None, [])
+    def nogettext_warning() -> None:
+        mlog.warning('Gettext not found, all translation targets will be ignored.', once=True)
 
     @staticmethod
-    def _get_data_dirs(state, dirs):
+    def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]:
         """Returns source directories of relative paths"""
         src_dir = path.join(state.environment.get_source_dir(), state.subdir)
         return [path.join(src_dir, d) for d in dirs]
 
     @FeatureNew('i18n.merge_file', '0.37.0')
-    @FeatureNewKwargs('i18n.merge_file', '0.51.0', ['args'])
-    @permittedKwargs(build.CustomTarget.known_kwargs | {'data_dirs', 'po_dir', 'type', 'args'})
-    def merge_file(self, state, args, kwargs):
+    @noPosargs
+    @typed_kwargs(
+        'i18n.merge_file',
+        CT_BUILD_BY_DEFAULT,
+        CT_INPUT_KW,
+        CT_INSTALL_DIR_KW,
+        CT_INSTALL_TAG_KW,
+        CT_OUTPUT_KW,
+        INSTALL_KW,
+        _ARGS.evolve(since='0.51.0'),
+        _DATA_DIRS.evolve(since='0.41.0'),
+        KwargInfo('po_dir', str, required=True),
+        KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})),
+    )
+    def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue:
         if not shutil.which('xgettext'):
-            return self.nogettext_warning()
-        podir = kwargs.pop('po_dir', None)
-        if not podir:
-            raise MesonException('i18n: po_dir is a required kwarg')
-        podir = path.join(state.build_to_src, state.subdir, podir)
-
-        file_type = kwargs.pop('type', 'xml')
-        VALID_TYPES = ('xml', 'desktop')
-        if file_type not in VALID_TYPES:
-            raise MesonException('i18n: "{}" is not a valid type {}'.format(file_type, VALID_TYPES))
-
-        datadirs = self._get_data_dirs(state, mesonlib.stringlistify(kwargs.pop('data_dirs', [])))
-        datadirs = '--datadirs=' + ':'.join(datadirs) if datadirs else None
-
-        command = state.environment.get_build_command() + [
+            self.nogettext_warning()
+            return ModuleReturnValue(None, [])
+        podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir'])
+
+        ddirs = self._get_data_dirs(state, kwargs['data_dirs'])
+        datadirs = '--datadirs=' + ':'.join(ddirs) if ddirs else None
+
+        command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget,
+                                build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = []
+        command.extend(state.environment.get_build_command())
+        command.extend([
             '--internal', 'msgfmthelper',
-            '@INPUT@', '@OUTPUT@', file_type, podir
-        ]
+            '@INPUT@', '@OUTPUT@', kwargs['type'], podir
+        ])
         if datadirs:
             command.append(datadirs)
 
-        if 'args' in kwargs:
+        if kwargs['args']:
             command.append('--')
-            command.append(mesonlib.stringlistify(kwargs.pop('args', [])))
+            command.extend(kwargs['args'])
+
+        build_by_default = kwargs['build_by_default']
+        if build_by_default is None:
+            build_by_default = kwargs['install']
+
+        real_kwargs = {
+            'build_by_default': build_by_default,
+            'command': command,
+            'install': kwargs['install'],
+            'install_dir': kwargs['install_dir'],
+            'output': kwargs['output'],
+            'input': kwargs['input'],
+            'install_tag': kwargs['install_tag'],
+        }
 
-        kwargs['command'] = command
+        ct = build.CustomTarget('', state.subdir, state.subproject,
+                T.cast(T.Dict[str, T.Any], real_kwargs))
 
-        inputfile = kwargs['input']
-        if hasattr(inputfile, 'held_object'):
-            ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, state.subproject, kwargs)
-        else:
-            if isinstance(inputfile, list):
-                # We only use this input file to create a name of the custom target.
-                # Thus we can ignore the other entries.
-                inputfile = inputfile[0]
-            if isinstance(inputfile, str):
-                inputfile = mesonlib.File.from_source_file(state.environment.source_dir,
-                                                           state.subdir, inputfile)
-            output = kwargs['output']
-            ifile_abs = inputfile.absolute_path(state.environment.source_dir,
-                                                state.environment.build_dir)
-            values = mesonlib.get_filenames_templates_dict([ifile_abs], None)
-            outputs = mesonlib.substitute_values([output], values)
-            output = outputs[0]
-            ct = build.CustomTarget(output + '_' + state.subdir.replace('/', '@').replace('\\', '@') + '_merge', state.subdir, state.subproject, kwargs)
         return ModuleReturnValue(ct, [ct])
 
-    @FeatureNewKwargs('i18n.gettext', '0.37.0', ['preset'])
-    @FeatureNewKwargs('i18n.gettext', '0.50.0', ['install_dir'])
-    @permittedKwargs({'po_dir', 'data_dirs', 'type', 'languages', 'args', 'preset', 'install', 'install_dir'})
-    def gettext(self, state, args, kwargs):
-        if len(args) != 1:
-            raise coredata.MesonException('Gettext requires one positional argument (package name).')
+    @typed_pos_args('i81n.gettex', str)
+    @typed_kwargs(
+        'i18n.gettext',
+        _ARGS,
+        _DATA_DIRS.evolve(since='0.36.0'),
+        INSTALL_KW.evolve(default=True),
+        KwargInfo('install_dir', (str, NoneType), since='0.50.0'),
+        KwargInfo('languages', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo(
+            'preset',
+            (str, NoneType),
+            validator=in_set_validator(set(PRESET_ARGS)),
+            since='0.37.0',
+        ),
+    )
+    def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') -> ModuleReturnValue:
         if not shutil.which('xgettext'):
-            return self.nogettext_warning()
+            self.nogettext_warning()
+            return ModuleReturnValue(None, [])
         packagename = args[0]
-        languages = mesonlib.stringlistify(kwargs.get('languages', []))
-        datadirs = self._get_data_dirs(state, mesonlib.stringlistify(kwargs.get('data_dirs', [])))
-        extra_args = mesonlib.stringlistify(kwargs.get('args', []))
+        pkg_arg = f'--pkgname={packagename}'
 
-        preset = kwargs.pop('preset', None)
+        languages = kwargs['languages']
+        lang_arg = '--langs=' + '@@'.join(languages) if languages else None
+
+        _datadirs = ':'.join(self._get_data_dirs(state, kwargs['data_dirs']))
+        datadirs = f'--datadirs={_datadirs}' if _datadirs else None
+
+        extra_args = kwargs['args']
+        targets: T.List['Target'] = []
+        gmotargets: T.List['build.CustomTarget'] = []
+
+        preset = kwargs['preset']
         if preset:
-            preset_args = PRESET_ARGS.get(preset)
-            if not preset_args:
-                raise coredata.MesonException('i18n: Preset "{}" is not one of the valid options: {}'.format(
-                                              preset, list(PRESET_ARGS.keys())))
-            extra_args = set(preset_args + extra_args)
+            preset_args = PRESET_ARGS[preset]
+            extra_args = list(mesonlib.OrderedSet(preset_args + extra_args))
 
-        pkg_arg = '--pkgname=' + packagename
-        lang_arg = '--langs=' + '@@'.join(languages) if languages else None
-        datadirs = '--datadirs=' + ':'.join(datadirs) if datadirs else None
-        extra_args = '--extra-args=' + '@@'.join(extra_args) if extra_args else None
+        extra_arg = '--extra-args=' + '@@'.join(extra_args) if extra_args else None
 
         potargs = state.environment.get_build_command() + ['--internal', 'gettext', 'pot', pkg_arg]
         if datadirs:
             potargs.append(datadirs)
-        if extra_args:
-            potargs.append(extra_args)
-        pottarget = build.RunTarget(packagename + '-pot', potargs[0], potargs[1:], [], state.subdir, state.subproject)
+        if extra_arg:
+            potargs.append(extra_arg)
+        pottarget = build.RunTarget(packagename + '-pot', potargs, [], state.subdir, state.subproject)
+        targets.append(pottarget)
+
+        install = kwargs['install']
+        install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('localedir'))
+        assert isinstance(install_dir, str), 'for mypy'
+        if not languages:
+            languages = read_linguas(path.join(state.environment.source_dir, state.subdir))
+        for l in languages:
+            po_file = mesonlib.File.from_source_file(state.environment.source_dir,
+                                                     state.subdir, l+'.po')
+            gmo_kwargs = {'command': ['msgfmt', '@INPUT@', '-o', '@OUTPUT@'],
+                          'input': po_file,
+                          'output': packagename+'.mo',
+                          'install': install,
+                          # We have multiple files all installed as packagename+'.mo' in different install subdirs.
+                          # What we really wanted to do, probably, is have a rename: kwarg, but that's not available
+                          # to custom_targets. Crude hack: set the build target's subdir manually.
+                          # Bonus: the build tree has something usable as an uninstalled bindtextdomain() target dir.
+                          'install_dir': path.join(install_dir, l, 'LC_MESSAGES'),
+                          'install_tag': 'i18n',
+                          }
+            gmotarget = build.CustomTarget(f'{packagename}-{l}.mo', path.join(state.subdir, l, 'LC_MESSAGES'), state.subproject, gmo_kwargs)
+            targets.append(gmotarget)
+            gmotargets.append(gmotarget)
 
-        gmoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'gen_gmo']
-        if lang_arg:
-            gmoargs.append(lang_arg)
-        gmotarget = build.RunTarget(packagename + '-gmo', gmoargs[0], gmoargs[1:], [], state.subdir, state.subproject)
+        allgmotarget = build.AliasTarget(packagename + '-gmo', gmotargets, state.subdir, state.subproject)
+        targets.append(allgmotarget)
 
         updatepoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'update_po', pkg_arg]
         if lang_arg:
             updatepoargs.append(lang_arg)
         if datadirs:
             updatepoargs.append(datadirs)
-        if extra_args:
-            updatepoargs.append(extra_args)
-        updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs[0], updatepoargs[1:], [], state.subdir, state.subproject)
-
-        targets = [pottarget, gmotarget, updatepotarget]
-
-        install = kwargs.get('install', True)
-        if install:
-            install_dir = kwargs.get('install_dir', state.environment.coredata.get_builtin_option('localedir'))
-            script = state.environment.get_build_command()
-            args = ['--internal', 'gettext', 'install',
-                    '--subdir=' + state.subdir,
-                    '--localedir=' + install_dir,
-                    pkg_arg]
-            if lang_arg:
-                args.append(lang_arg)
-            iscript = build.RunScript(script, args)
-            targets.append(iscript)
+        if extra_arg:
+            updatepoargs.append(extra_arg)
+        updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs, [], state.subdir, state.subproject)
+        targets.append(updatepotarget)
 
-        return ModuleReturnValue(None, targets)
+        return ModuleReturnValue([gmotargets, pottarget, updatepotarget], targets)
 
-def initialize(*args, **kwargs):
-    return I18nModule(*args, **kwargs)
+def initialize(interp: 'Interpreter') -> I18nModule:
+    return I18nModule(interp)
diff -Nru meson-0.53.2/mesonbuild/modules/__init__.py meson-0.61.2/mesonbuild/modules/__init__.py
--- meson-0.53.2/mesonbuild/modules/__init__.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/__init__.py	2022-01-17 10:50:38.000000000 +0000
@@ -12,77 +12,197 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# This file contains the detection logic for external dependencies that
-# are UI-related.
+# This file contains the base representation for import('modname')
 
 import os
+import typing as T
 
-from .. import build
+from .. import build, mesonlib
+from ..mesonlib import relpath, HoldableObject, MachineChoice, OptionKey
+from ..interpreterbase.decorators import noKwargs, noPosargs
+
+if T.TYPE_CHECKING:
+    from ..interpreter import Interpreter
+    from ..interpreterbase import TYPE_var, TYPE_kwargs
+    from ..programs import ExternalProgram
+    from ..wrap import WrapMode
+
+class ModuleState:
+    """Object passed to all module methods.
+
+    This is a WIP API provided to modules, it should be extended to have everything
+    needed so modules does not touch any other part of Meson internal APIs.
+    """
+
+    def __init__(self, interpreter: 'Interpreter') -> None:
+        # Keep it private, it should be accessed only through methods.
+        self._interpreter = interpreter
+
+        self.source_root = interpreter.environment.get_source_dir()
+        self.build_to_src = relpath(interpreter.environment.get_source_dir(),
+                                    interpreter.environment.get_build_dir())
+        self.subproject = interpreter.subproject
+        self.subdir = interpreter.subdir
+        self.current_lineno = interpreter.current_lineno
+        self.environment = interpreter.environment
+        self.project_name = interpreter.build.project_name
+        self.project_version = interpreter.build.dep_manifest[interpreter.active_projectname].version
+        # The backend object is under-used right now, but we will need it:
+        # https://github.com/mesonbuild/meson/issues/1419
+        self.backend = interpreter.backend
+        self.targets = interpreter.build.targets
+        self.data = interpreter.build.data
+        self.headers = interpreter.build.get_headers()
+        self.man = interpreter.build.get_man()
+        self.global_args = interpreter.build.global_args.host
+        self.project_args = interpreter.build.projects_args.host.get(interpreter.subproject, {})
+        self.build_machine = T.cast('MachineHolder', interpreter.builtin['build_machine']).held_object
+        self.host_machine = T.cast('MachineHolder', interpreter.builtin['host_machine']).held_object
+        self.target_machine = T.cast('MachineHolder', interpreter.builtin['target_machine']).held_object
+        self.current_node = interpreter.current_node
+
+    def get_include_args(self, include_dirs: T.Iterable[T.Union[str, build.IncludeDirs]], prefix: str = '-I') -> T.List[str]:
+        if not include_dirs:
+            return []
+
+        srcdir = self.environment.get_source_dir()
+        builddir = self.environment.get_build_dir()
+
+        dirs_str: T.List[str] = []
+        for dirs in include_dirs:
+            if isinstance(dirs, str):
+                dirs_str += [f'{prefix}{dirs}']
+            else:
+                dirs_str.extend([f'{prefix}{i}' for i in dirs.to_string_list(srcdir, builddir)])
+                dirs_str.extend([f'{prefix}{i}' for i in dirs.get_extra_build_dirs()])
+
+        return dirs_str
+
+    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, 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,
+             env: T.Union[T.List[str], T.Dict[str, str], str] = None,
+             depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]] = None) -> None:
+        kwargs = {'workdir': workdir,
+                  '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, real_args, kwargs)
+
+    def get_option(self, name: str, subproject: str = '',
+                   machine: MachineChoice = MachineChoice.HOST,
+                   lang: T.Optional[str] = None,
+                   module: T.Optional[str] = None) -> T.Union[str, int, bool, 'WrapMode']:
+        return self.environment.coredata.get_option(mesonlib.OptionKey(name, subproject, machine, lang, module))
+
+
+class ModuleObject(HoldableObject):
+    """Base class for all objects returned by modules
+    """
+    def __init__(self) -> None:
+        self.methods: T.Dict[
+            str,
+            T.Callable[[ModuleState, T.List['TYPE_var'], 'TYPE_kwargs'], T.Union[ModuleReturnValue, 'TYPE_var']]
+        ] = {}
+
+
+class MutableModuleObject(ModuleObject):
+    pass
+
+
+# FIXME: Port all modules to stop using self.interpreter and use API on
+# ModuleState instead. Modules should stop using this class and instead use
+# ModuleObject base class.
+class ExtensionModule(ModuleObject):
+    def __init__(self, interpreter: 'Interpreter') -> None:
+        super().__init__()
+        self.interpreter = interpreter
+        self.methods.update({
+            'found': self.found_method,
+        })
 
+    @noPosargs
+    @noKwargs
+    def found_method(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        return self.found()
 
-class ExtensionModule:
-    def __init__(self, interpreter):
-        self.interpreter = interpreter
-        self.snippets = set() # List of methods that operate only on the interpreter.
+    @staticmethod
+    def found() -> bool:
+        return True
+
+
+class NewExtensionModule(ModuleObject):
+
+    """Class for modern modules
+
+    provides the found method.
+    """
+
+    def __init__(self) -> None:
+        super().__init__()
+        self.methods.update({
+            'found': self.found_method,
+        })
 
-    def is_snippet(self, funcname):
-        return funcname in self.snippets
+    @noPosargs
+    @noKwargs
+    def found_method(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+        return self.found()
 
+    @staticmethod
+    def found() -> bool:
+        return True
 
-def get_include_args(include_dirs, prefix='-I'):
+
+class NotFoundExtensionModule(NewExtensionModule):
+
+    """Class for modern modules
+
+    provides the found method.
+    """
+
+    @staticmethod
+    def found() -> bool:
+        return False
+
+
+def is_module_library(fname):
     '''
-    Expand include arguments to refer to the source and build dirs
-    by using @SOURCE_ROOT@ and @BUILD_ROOT@ for later substitution
+    Check if the file is a library-like file generated by a module-specific
+    target, such as GirTarget or TypelibTarget
     '''
-    if not include_dirs:
-        return []
-
-    dirs_str = []
-    for incdirs in include_dirs:
-        if hasattr(incdirs, "held_object"):
-            dirs = incdirs.held_object
-        else:
-            dirs = incdirs
-
-        if isinstance(dirs, str):
-            dirs_str += ['%s%s' % (prefix, dirs)]
-            continue
-
-        # Should be build.IncludeDirs object.
-        basedir = dirs.get_curdir()
-        for d in dirs.get_incdirs():
-            expdir = os.path.join(basedir, d)
-            srctreedir = os.path.join('@SOURCE_ROOT@', expdir)
-            buildtreedir = os.path.join('@BUILD_ROOT@', expdir)
-            dirs_str += ['%s%s' % (prefix, buildtreedir),
-                         '%s%s' % (prefix, srctreedir)]
-        for d in dirs.get_extra_build_dirs():
-            dirs_str += ['%s%s' % (prefix, d)]
+    if hasattr(fname, 'fname'):
+        fname = fname.fname
+    suffix = fname.split('.')[-1]
+    return suffix in ('gir', 'typelib')
 
-    return dirs_str
 
 class ModuleReturnValue:
-    def __init__(self, return_value, new_objects):
+    def __init__(self, return_value: T.Optional['TYPE_var'],
+                 new_objects: T.Sequence[T.Union['TYPE_var', 'build.ExecutableSerialisation']]) -> None:
         self.return_value = return_value
-        assert(isinstance(new_objects, list))
-        self.new_objects = new_objects
+        assert isinstance(new_objects, list)
+        self.new_objects: T.List[T.Union['TYPE_var', 'build.ExecutableSerialisation']] = new_objects
 
 class GResourceTarget(build.CustomTarget):
-    def __init__(self, name, subdir, subproject, kwargs):
-        super().__init__(name, subdir, subproject, kwargs)
+    pass
 
 class GResourceHeaderTarget(build.CustomTarget):
-    def __init__(self, name, subdir, subproject, kwargs):
-        super().__init__(name, subdir, subproject, kwargs)
+    pass
 
 class GirTarget(build.CustomTarget):
-    def __init__(self, name, subdir, subproject, kwargs):
-        super().__init__(name, subdir, subproject, kwargs)
+    pass
 
 class TypelibTarget(build.CustomTarget):
-    def __init__(self, name, subdir, subproject, kwargs):
-        super().__init__(name, subdir, subproject, kwargs)
+    pass
 
 class VapiTarget(build.CustomTarget):
-    def __init__(self, name, subdir, subproject, kwargs):
-        super().__init__(name, subdir, subproject, kwargs)
+    pass
diff -Nru meson-0.53.2/mesonbuild/modules/java.py meson-0.61.2/mesonbuild/modules/java.py
--- meson-0.53.2/mesonbuild/modules/java.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/java.py	2021-11-02 19:58:13.000000000 +0000
@@ -0,0 +1,76 @@
+# Copyright 2021 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 pathlib
+import typing as T
+from mesonbuild.build import CustomTarget
+from mesonbuild.compilers import detect_compiler_for
+from mesonbuild.interpreterbase.decorators import FeatureNew, KwargInfo, typed_pos_args, typed_kwargs
+from mesonbuild.interpreter.interpreterobjects import FileHolder
+from mesonbuild.mesonlib import version_compare, MachineChoice
+from . import ExtensionModule, ModuleReturnValue, ModuleState
+from ..interpreter import Interpreter
+
+class JavaModule(ExtensionModule):
+    @FeatureNew('Java Module', '0.60.0')
+    def __init__(self, interpreter: Interpreter):
+        super().__init__(interpreter)
+        self.methods.update({
+            'generate_native_header': self.generate_native_header,
+        })
+
+        if 'java' not in interpreter.environment.coredata.compilers[MachineChoice.BUILD]:
+            detect_compiler_for(interpreter.environment, 'java', MachineChoice.BUILD)
+        self.javac = interpreter.environment.coredata.compilers[MachineChoice.BUILD]['java']
+
+    @typed_pos_args('generate_native_header', (str, FileHolder))
+    @typed_kwargs('java.generate_native_header', KwargInfo('package', str, default=None))
+    def generate_native_header(self, state: ModuleState, args: T.Tuple[T.Union[str, FileHolder]],
+                               kwargs: T.Dict[str, T.Optional[str]]) -> ModuleReturnValue:
+        assert state.backend
+
+        package = kwargs.get('package')
+
+        file = self.interpreter.source_strings_to_files(
+            [a.held_object if isinstance(a, FileHolder) else a for a in args])[0]
+
+        if package:
+            header = f'{package.replace(".", "_")}_{pathlib.Path(file.fname).stem}.h'
+        else:
+            header = f'{pathlib.Path(file.fname).stem}.h'
+
+        ct_kwargs = {
+            'input': file,
+            'output': header,
+            'command': [
+                self.javac.exelist[0],
+                '-d',
+                '@PRIVATE_DIR@',
+                '-h',
+                state.subdir,
+                '@INPUT@',
+            ]
+        }
+
+        target = CustomTarget(os.path.basename(header), state.subdir, state.subproject, backend=state.backend, kwargs=ct_kwargs)
+        # It is only known that 1.8.0 won't pre-create the directory. 11 and 16
+        # do not exhibit this behavior.
+        if version_compare(self.javac.version, '1.8.0'):
+            pathlib.Path(state.backend.get_target_private_dir_abs(target)).mkdir(parents=True, exist_ok=True)
+
+        return ModuleReturnValue(target, [target])
+
+def initialize(*args: T.Any, **kwargs: T.Any) -> JavaModule:
+    return JavaModule(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/keyval.py meson-0.61.2/mesonbuild/modules/keyval.py
--- meson-0.53.2/mesonbuild/modules/keyval.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/keyval.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,73 @@
+# Copyright 2017, 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import typing as T
+
+from . import ExtensionModule
+from .. import mesonlib
+from ..interpreterbase import FeatureNew, noKwargs, typed_pos_args
+
+if T.TYPE_CHECKING:
+    from ..interpreter import Interpreter
+    from . import ModuleState
+
+class KeyvalModule(ExtensionModule):
+
+    @FeatureNew('Keyval Module', '0.55.0')
+    def __init__(self, interp: 'Interpreter'):
+        super().__init__(interp)
+        self.methods.update({
+            'load': self.load,
+        })
+
+    @staticmethod
+    def _load_file(path_to_config: str) -> T.Dict[str, str]:
+        result: T.Dict[str, str] = {}
+        try:
+            with open(path_to_config, encoding='utf-8') as f:
+                for line in f:
+                    if '#' in line:
+                        comment_idx = line.index('#')
+                        line = line[:comment_idx]
+                    line = line.strip()
+                    try:
+                        name, val = line.split('=', 1)
+                    except ValueError:
+                        continue
+                    result[name.strip()] = val.strip()
+        except OSError as e:
+            raise mesonlib.MesonException(f'Failed to load {path_to_config}: {e}')
+
+        return result
+
+    @noKwargs
+    @typed_pos_args('keyval.laod', (str, mesonlib.File))
+    def load(self, state: 'ModuleState', args: T.Tuple['mesonlib.FileOrString'], kwargs: T.Dict[str, T.Any]) -> T.Dict[str, str]:
+        s = args[0]
+        is_built = False
+        if isinstance(s, mesonlib.File):
+            is_built = is_built or s.is_built
+            s = s.absolute_path(self.interpreter.environment.source_dir, self.interpreter.environment.build_dir)
+        else:
+            s = os.path.join(self.interpreter.environment.source_dir, s)
+
+        if s not in self.interpreter.build_def_files and not is_built:
+            self.interpreter.build_def_files.append(s)
+
+        return self._load_file(s)
+
+
+def initialize(interp: 'Interpreter') -> KeyvalModule:
+    return KeyvalModule(interp)
diff -Nru meson-0.53.2/mesonbuild/modules/modtest.py meson-0.61.2/mesonbuild/modules/modtest.py
--- meson-0.53.2/mesonbuild/modules/modtest.py	2018-08-25 08:05:43.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/modtest.py	2021-08-18 11:22:15.000000000 +0000
@@ -12,17 +12,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from . import ModuleReturnValue
 from . import ExtensionModule
 from ..interpreterbase import noKwargs
 
 class TestModule(ExtensionModule):
+    def __init__(self, interpreter):
+        super().__init__(interpreter)
+        self.methods.update({
+            'print_hello': self.print_hello,
+        })
 
     @noKwargs
     def print_hello(self, state, args, kwargs):
         print('Hello from a Meson module')
-        rv = ModuleReturnValue(None, [])
-        return rv
 
 def initialize(*args, **kwargs):
     return TestModule(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/pkgconfig.py meson-0.61.2/mesonbuild/modules/pkgconfig.py
--- meson-0.53.2/mesonbuild/modules/pkgconfig.py	2020-01-23 22:29:05.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/pkgconfig.py	2021-12-26 16:24:25.000000000 +0000
@@ -12,21 +12,27 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os, types
 from pathlib import PurePath
+import os
+import typing as T
 
+from . import ExtensionModule
+from . import ModuleReturnValue
 from .. import build
 from .. import dependencies
 from .. import mesonlib
 from .. import mlog
-from . import ModuleReturnValue
-from . import ExtensionModule
+from ..dependencies import ThreadDependency
 from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs
 
+if T.TYPE_CHECKING:
+    from . import ModuleState
+
 already_warned_objs = set()
 
 class DependenciesHelper:
-    def __init__(self, name):
+    def __init__(self, state, name):
+        self.state = state
         self.name = name
         self.pub_libs = []
         self.pub_reqs = []
@@ -34,6 +40,7 @@
         self.priv_reqs = []
         self.cflags = []
         self.version_reqs = {}
+        self.link_whole_targets = []
 
     def add_pub_libs(self, libs):
         libs, reqs, cflags = self._process_libs(libs, True)
@@ -72,15 +79,12 @@
     def _process_reqs(self, reqs):
         '''Returns string names of requirements'''
         processed_reqs = []
-        for obj in mesonlib.listify(reqs, unholder=True):
+        for obj in mesonlib.listify(reqs):
+            if not isinstance(obj, str):
+                FeatureNew.single_use('pkgconfig.generate requirement from non-string object', '0.46.0', self.state.subproject)
             if hasattr(obj, 'generated_pc'):
                 self._check_generated_pc_deprecation(obj)
                 processed_reqs.append(obj.generated_pc)
-            elif hasattr(obj, 'pcdep'):
-                pcdeps = mesonlib.listify(obj.pcdep)
-                for d in pcdeps:
-                    processed_reqs.append(d.name)
-                    self.add_version_reqs(d.name, obj.version_reqs)
             elif isinstance(obj, dependencies.PkgConfigDependency):
                 if obj.found():
                     processed_reqs.append(obj.name)
@@ -91,53 +95,40 @@
                 self.add_version_reqs(name, version_req)
             elif isinstance(obj, dependencies.Dependency) and not obj.found():
                 pass
-            elif isinstance(obj, dependencies.ThreadDependency):
+            elif isinstance(obj, ThreadDependency):
                 pass
             else:
                 raise mesonlib.MesonException('requires argument not a string, '
                                               'library with pkgconfig-generated file '
-                                              'or pkgconfig-dependency object, '
-                                              'got {!r}'.format(obj))
+                                              'or pkgconfig-dependency object, got {obj!r}')
         return processed_reqs
 
     def add_cflags(self, cflags):
         self.cflags += mesonlib.stringlistify(cflags)
 
-    def _process_libs(self, libs, public):
-        libs = mesonlib.listify(libs, unholder=True)
+    def _process_libs(self, libs, public: bool):
+        libs = mesonlib.listify(libs)
         processed_libs = []
         processed_reqs = []
         processed_cflags = []
         for obj in libs:
-            shared_library_only = getattr(obj, 'shared_library_only', False)
-            if hasattr(obj, 'pcdep'):
-                pcdeps = mesonlib.listify(obj.pcdep)
-                for d in pcdeps:
-                    processed_reqs.append(d.name)
-                    self.add_version_reqs(d.name, obj.version_reqs)
-            elif hasattr(obj, 'generated_pc'):
+            if hasattr(obj, 'generated_pc'):
                 self._check_generated_pc_deprecation(obj)
                 processed_reqs.append(obj.generated_pc)
             elif isinstance(obj, dependencies.PkgConfigDependency):
                 if obj.found():
                     processed_reqs.append(obj.name)
                     self.add_version_reqs(obj.name, obj.version_reqs)
-            elif isinstance(obj, dependencies.ThreadDependency):
-                processed_libs += obj.get_compiler().thread_link_flags(obj.env)
-                processed_cflags += obj.get_compiler().thread_flags(obj.env)
             elif isinstance(obj, dependencies.InternalDependency):
                 if obj.found():
                     processed_libs += obj.get_link_args()
                     processed_cflags += obj.get_compile_args()
-                    if public:
-                        self.add_pub_libs(obj.libraries)
-                    else:
-                        self.add_priv_libs(obj.libraries)
+                    self._add_lib_dependencies(obj.libraries, obj.whole_libraries, obj.ext_deps, public, private_external_deps=True)
             elif isinstance(obj, dependencies.Dependency):
                 if obj.found():
                     processed_libs += obj.get_link_args()
                     processed_cflags += obj.get_compile_args()
-            elif isinstance(obj, build.SharedLibrary) and shared_library_only:
+            elif isinstance(obj, build.SharedLibrary) and obj.shared_library_only:
                 # Do not pull dependencies for shared libraries because they are
                 # only required for static linking. Adding private requires has
                 # the side effect of exposing their cflags, which is the
@@ -147,19 +138,54 @@
                 processed_libs.append(obj)
             elif isinstance(obj, (build.SharedLibrary, build.StaticLibrary)):
                 processed_libs.append(obj)
-                if isinstance(obj, build.StaticLibrary) and public:
-                    self.add_pub_libs(obj.get_dependencies(for_pkgconfig=True))
-                    self.add_pub_libs(obj.get_external_deps())
-                else:
-                    self.add_priv_libs(obj.get_dependencies(for_pkgconfig=True))
-                    self.add_priv_libs(obj.get_external_deps())
+                # If there is a static library in `Libs:` all its deps must be
+                # public too, otherwise the generated pc file will never be
+                # usable without --static.
+                self._add_lib_dependencies(obj.link_targets,
+                                           obj.link_whole_targets,
+                                           obj.external_deps,
+                                           isinstance(obj, build.StaticLibrary) and public)
+            elif isinstance(obj, (build.CustomTarget, build.CustomTargetIndex)):
+                if not obj.is_linkable_target():
+                    raise mesonlib.MesonException('library argument contains a not linkable custom_target.')
+                FeatureNew.single_use('custom_target in pkgconfig.generate libraries', '0.58.0', self.state.subproject)
+                processed_libs.append(obj)
             elif isinstance(obj, str):
                 processed_libs.append(obj)
             else:
-                raise mesonlib.MesonException('library argument not a string, library or dependency object.')
+                raise mesonlib.MesonException(f'library argument of type {type(obj).__name__} not a string, library or dependency object.')
 
         return processed_libs, processed_reqs, processed_cflags
 
+    def _add_lib_dependencies(self, link_targets, link_whole_targets, external_deps, public, private_external_deps=False):
+        add_libs = self.add_pub_libs if public else self.add_priv_libs
+        # Recursively add all linked libraries
+        for t in link_targets:
+            # Internal libraries (uninstalled static library) will be promoted
+            # to link_whole, treat them as such here.
+            if t.is_internal():
+                self._add_link_whole(t, public)
+            else:
+                add_libs([t])
+        for t in link_whole_targets:
+            self._add_link_whole(t, public)
+        # And finally its external dependencies
+        if private_external_deps:
+            self.add_priv_libs(external_deps)
+        else:
+            add_libs(external_deps)
+
+    def _add_link_whole(self, t, public):
+        # Don't include static libraries that we link_whole. But we still need to
+        # include their dependencies: a static library we link_whole
+        # could itself link to a shared library or an installed static library.
+        # Keep track of link_whole_targets so we can remove them from our
+        # 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)
+        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:
             if name not in self.version_reqs:
@@ -195,6 +221,32 @@
         return ', '.join(result)
 
     def remove_dups(self):
+        # Set of ids that have already been handled and should not be added any more
+        exclude = set()
+
+        # We can't just check if 'x' is excluded because we could have copies of
+        # the same SharedLibrary object for example.
+        def _ids(x):
+            if hasattr(x, 'generated_pc'):
+                yield x.generated_pc
+            if isinstance(x, build.Target):
+                yield x.get_id()
+            yield x
+
+        # Exclude 'x' in all its forms and return if it was already excluded
+        def _add_exclude(x):
+            was_excluded = False
+            for i in _ids(x):
+                if i in exclude:
+                    was_excluded = True
+                else:
+                    exclude.add(i)
+            return was_excluded
+
+        # link_whole targets are already part of other targets, exclude them all.
+        for t in self.link_whole_targets:
+            _add_exclude(t)
+
         def _fn(xs, libs=False):
             # Remove duplicates whilst preserving original order
             result = []
@@ -205,22 +257,35 @@
                 cannot_dedup = libs and isinstance(x, str) and \
                     not x.startswith(('-l', '-L')) and \
                     x not in known_flags
-                if x not in result or cannot_dedup:
-                    result.append(x)
+                if not cannot_dedup and _add_exclude(x):
+                    continue
+                result.append(x)
             return result
-        self.pub_libs = _fn(self.pub_libs, True)
+
+        # Handle lists in priority order: public items can be excluded from
+        # private and Requires can excluded from Libs.
         self.pub_reqs = _fn(self.pub_reqs)
-        self.priv_libs = _fn(self.priv_libs, True)
+        self.pub_libs = _fn(self.pub_libs, True)
         self.priv_reqs = _fn(self.priv_reqs)
+        self.priv_libs = _fn(self.priv_libs, True)
+        # Reset exclude list just in case some values can be both cflags and libs.
+        exclude = set()
         self.cflags = _fn(self.cflags)
 
-        # Remove from private libs/reqs if they are in public already
-        self.priv_libs = [i for i in self.priv_libs if i not in self.pub_libs]
-        self.priv_reqs = [i for i in self.priv_reqs if i not in self.pub_reqs]
-
 class PkgConfigModule(ExtensionModule):
-
-    def _get_lname(self, l, msg, pcfile):
+    def __init__(self, interpreter):
+        super().__init__(interpreter)
+        self.methods.update({
+            'generate': self.generate,
+        })
+
+    def _get_lname(self, l, msg, pcfile, is_custom_target):
+        if is_custom_target:
+            basename = os.path.basename(l.get_filename())
+            name = os.path.splitext(basename)[0]
+            if name.startswith('lib'):
+                name = name[3:]
+            return name
         # Nothing special
         if not l.name_prefix_set:
             return l.name
@@ -251,45 +316,58 @@
         return value.replace(' ', r'\ ')
 
     def _make_relative(self, prefix, subdir):
-        if isinstance(prefix, PurePath):
-            prefix = prefix.as_posix()
-        if isinstance(subdir, PurePath):
-            subdir = subdir.as_posix()
-        if subdir.startswith(prefix):
-            subdir = subdir.replace(prefix, '')
-        return subdir
-
-    def generate_pkgconfig_file(self, state, deps, subdirs, name, description,
-                                url, version, pcfile, conflicts, variables):
-        deps.remove_dups()
+        prefix = PurePath(prefix)
+        subdir = PurePath(subdir)
+        try:
+            libdir = subdir.relative_to(prefix)
+        except ValueError:
+            libdir = subdir
+        # pathlib joining makes sure absolute libdir is not appended to '${prefix}'
+        return ('${prefix}' / libdir).as_posix()
+
+    def _generate_pkgconfig_file(self, state, deps, subdirs, name, description,
+                                 url, version, pcfile, conflicts, variables,
+                                 unescaped_variables, uninstalled=False, dataonly=False):
         coredata = state.environment.get_coredata()
-        outdir = state.environment.scratch_dir
-        fname = os.path.join(outdir, pcfile)
-        prefix = PurePath(coredata.get_builtin_option('prefix'))
+        if uninstalled:
+            outdir = os.path.join(state.environment.build_dir, 'meson-uninstalled')
+            if not os.path.exists(outdir):
+                os.mkdir(outdir)
+            prefix = PurePath(state.environment.get_build_dir())
+            srcdir = PurePath(state.environment.get_source_dir())
+        else:
+            outdir = state.environment.scratch_dir
+            prefix = PurePath(coredata.get_option(mesonlib.OptionKey('prefix')))
         # These always return paths relative to prefix
-        libdir = PurePath(coredata.get_builtin_option('libdir'))
-        incdir = PurePath(coredata.get_builtin_option('includedir'))
+        libdir = PurePath(coredata.get_option(mesonlib.OptionKey('libdir')))
+        incdir = PurePath(coredata.get_option(mesonlib.OptionKey('includedir')))
+        fname = os.path.join(outdir, pcfile)
         with open(fname, 'w', encoding='utf-8') as ofile:
-            ofile.write('prefix={}\n'.format(self._escape(prefix)))
-            ofile.write('libdir={}\n'.format(self._escape('${prefix}' / libdir)))
-            ofile.write('includedir={}\n'.format(self._escape('${prefix}' / incdir)))
-            if variables:
+            if not dataonly:
+                ofile.write('prefix={}\n'.format(self._escape(prefix)))
+                if uninstalled:
+                    ofile.write('srcdir={}\n'.format(self._escape(srcdir)))
+                ofile.write('libdir={}\n'.format(self._escape('${prefix}' / libdir)))
+                ofile.write('includedir={}\n'.format(self._escape('${prefix}' / incdir)))
+            if variables or unescaped_variables:
                 ofile.write('\n')
             for k, v in variables:
                 ofile.write('{}={}\n'.format(k, self._escape(v)))
+            for k, v in unescaped_variables:
+                ofile.write(f'{k}={v}\n')
             ofile.write('\n')
-            ofile.write('Name: %s\n' % name)
+            ofile.write(f'Name: {name}\n')
             if len(description) > 0:
-                ofile.write('Description: %s\n' % description)
+                ofile.write(f'Description: {description}\n')
             if len(url) > 0:
-                ofile.write('URL: %s\n' % url)
-            ofile.write('Version: %s\n' % version)
+                ofile.write(f'URL: {url}\n')
+            ofile.write(f'Version: {version}\n')
             reqs_str = deps.format_reqs(deps.pub_reqs)
             if len(reqs_str) > 0:
-                ofile.write('Requires: {}\n'.format(reqs_str))
+                ofile.write(f'Requires: {reqs_str}\n')
             reqs_str = deps.format_reqs(deps.priv_reqs)
             if len(reqs_str) > 0:
-                ofile.write('Requires.private: {}\n'.format(reqs_str))
+                ofile.write(f'Requires.private: {reqs_str}\n')
             if len(conflicts) > 0:
                 ofile.write('Conflicts: {}\n'.format(' '.join(conflicts)))
 
@@ -302,75 +380,116 @@
                     if isinstance(l, str):
                         yield l
                     else:
-                        install_dir = l.get_custom_install_dir()[0]
+                        if uninstalled:
+                            install_dir = os.path.dirname(state.backend.get_target_filename_abs(l))
+                        else:
+                            _i = l.get_custom_install_dir()
+                            install_dir = _i[0] if _i else None
                         if install_dir is False:
                             continue
-                        if 'cs' in l.compilers:
+                        is_custom_target = isinstance(l, (build.CustomTarget, build.CustomTargetIndex))
+                        if not is_custom_target and 'cs' in l.compilers:
                             if isinstance(install_dir, str):
-                                Lflag = '-r${prefix}/%s/%s ' % (self._escape(self._make_relative(prefix, install_dir)), l.filename)
+                                Lflag = '-r{}/{}'.format(self._escape(self._make_relative(prefix, install_dir)), l.filename)
                             else:  # install_dir is True
                                 Lflag = '-r${libdir}/%s' % l.filename
                         else:
                             if isinstance(install_dir, str):
-                                Lflag = '-L${prefix}/%s ' % self._escape(self._make_relative(prefix, install_dir))
+                                Lflag = '-L{}'.format(self._escape(self._make_relative(prefix, install_dir)))
                             else:  # install_dir is True
                                 Lflag = '-L${libdir}'
                         if Lflag not in Lflags:
                             Lflags.append(Lflag)
                             yield Lflag
-                        lname = self._get_lname(l, msg, pcfile)
+                        lname = self._get_lname(l, msg, pcfile, is_custom_target)
                         # If using a custom suffix, the compiler may not be able to
                         # find the library
-                        if l.name_suffix_set:
+                        if not is_custom_target and l.name_suffix_set:
                             mlog.warning(msg.format(l.name, 'name_suffix', lname, pcfile))
-                        if 'cs' not in l.compilers:
-                            yield '-l%s' % lname
+                        if is_custom_target or 'cs' not in l.compilers:
+                            yield f'-l{lname}'
+
+            def get_uninstalled_include_dirs(libs):
+                result = []
+                for l in libs:
+                    if isinstance(l, (str, build.CustomTarget, build.CustomTargetIndex)):
+                        continue
+                    if l.get_subdir() not in result:
+                        result.append(l.get_subdir())
+                    for i in l.get_include_dirs():
+                        curdir = i.get_curdir()
+                        for d in i.get_incdirs():
+                            path = os.path.join(curdir, d)
+                            if path not in result:
+                                result.append(path)
+                return result
+
+            def generate_uninstalled_cflags(libs):
+                for d in get_uninstalled_include_dirs(libs):
+                    for basedir in ['${prefix}', '${srcdir}']:
+                        path = PurePath(basedir, d)
+                        yield '-I%s' % self._escape(path.as_posix())
 
             if len(deps.pub_libs) > 0:
                 ofile.write('Libs: {}\n'.format(' '.join(generate_libs_flags(deps.pub_libs))))
             if len(deps.priv_libs) > 0:
                 ofile.write('Libs.private: {}\n'.format(' '.join(generate_libs_flags(deps.priv_libs))))
-            ofile.write('Cflags:')
-            for h in subdirs:
-                ofile.write(' ')
-                if h == '.':
-                    ofile.write('-I${includedir}')
-                else:
-                    ofile.write(self._escape(PurePath('-I${includedir}') / h))
-            for f in deps.cflags:
-                ofile.write(' ')
-                ofile.write(self._escape(f))
-            ofile.write('\n')
 
+            cflags = []
+            if uninstalled:
+                cflags += generate_uninstalled_cflags(deps.pub_libs + deps.priv_libs)
+            else:
+                for d in subdirs:
+                    if d == '.':
+                        cflags.append('-I${includedir}')
+                    else:
+                        cflags.append(self._escape(PurePath('-I${includedir}') / d))
+            cflags += [self._escape(f) for f in deps.cflags]
+            if cflags and not dataonly:
+                ofile.write('Cflags: {}\n'.format(' '.join(cflags)))
+
+    @FeatureNewKwargs('pkgconfig.generate', '0.59.0', ['unescaped_variables', 'unescaped_uninstalled_variables'])
+    @FeatureNewKwargs('pkgconfig.generate', '0.54.0', ['uninstalled_variables'])
     @FeatureNewKwargs('pkgconfig.generate', '0.42.0', ['extra_cflags'])
     @FeatureNewKwargs('pkgconfig.generate', '0.41.0', ['variables'])
+    @FeatureNewKwargs('pkgconfig.generate', '0.54.0', ['dataonly'])
     @permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase',
                       'subdirs', 'requires', 'requires_private', 'libraries_private',
-                      'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions'})
-    def generate(self, state, args, kwargs):
-        if 'variables' in kwargs:
-            FeatureNew('custom pkgconfig variables', '0.41.0').use(state.subproject)
-        default_version = state.project_version['version']
+                      'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions',
+                      'dataonly', 'conflicts', 'uninstalled_variables',
+                      'unescaped_variables', 'unescaped_uninstalled_variables'})
+    def generate(self, state: 'ModuleState', args, kwargs):
+        default_version = state.project_version
         default_install_dir = None
         default_description = None
         default_name = None
         mainlib = None
+        default_subdirs = ['.']
         if not args and 'version' not in kwargs:
-            FeatureNew('pkgconfig.generate implicit version keyword', '0.46.0').use(state.subproject)
+            FeatureNew.single_use('pkgconfig.generate implicit version keyword', '0.46.0', state.subproject)
         elif len(args) == 1:
-            FeatureNew('pkgconfig.generate optional positional argument', '0.46.0').use(state.subproject)
-            mainlib = getattr(args[0], 'held_object', args[0])
+            FeatureNew.single_use('pkgconfig.generate optional positional argument', '0.46.0', state.subproject)
+            mainlib = args[0]
             if not isinstance(mainlib, (build.StaticLibrary, build.SharedLibrary)):
                 raise mesonlib.MesonException('Pkgconfig_gen first positional argument must be a library object')
             default_name = mainlib.name
             default_description = state.project_name + ': ' + mainlib.name
-            install_dir = mainlib.get_custom_install_dir()[0]
-            if isinstance(install_dir, str):
-                default_install_dir = os.path.join(install_dir, 'pkgconfig')
+            install_dir = mainlib.get_custom_install_dir()
+            if install_dir and isinstance(install_dir[0], str):
+                default_install_dir = os.path.join(install_dir[0], 'pkgconfig')
         elif len(args) > 1:
             raise mesonlib.MesonException('Too many positional arguments passed to Pkgconfig_gen.')
 
-        subdirs = mesonlib.stringlistify(kwargs.get('subdirs', ['.']))
+        dataonly = kwargs.get('dataonly', False)
+        if not isinstance(dataonly, bool):
+            raise mesonlib.MesonException('dataonly must be boolean.')
+        if dataonly:
+            default_subdirs = []
+            blocked_vars = ['libraries', 'libraries_private', 'require_private', 'extra_cflags', 'subdirs']
+            if any(k in kwargs for k in blocked_vars):
+                raise mesonlib.MesonException(f'Cannot combine dataonly with any of {blocked_vars}')
+
+        subdirs = mesonlib.stringlistify(kwargs.get('subdirs', default_subdirs))
         version = kwargs.get('version', default_version)
         if not isinstance(version, str):
             raise mesonlib.MesonException('Version must be specified.')
@@ -395,7 +514,7 @@
         if mainlib:
             libraries = [mainlib] + libraries
 
-        deps = DependenciesHelper(filebase)
+        deps = DependenciesHelper(state, filebase)
         deps.add_pub_libs(libraries)
         deps.add_priv_libs(kwargs.get('libraries_private', []))
         deps.add_pub_reqs(kwargs.get('requires', []))
@@ -408,44 +527,46 @@
             if compiler:
                 deps.add_cflags(compiler.get_feature_args({'versions': dversions}, None))
 
-        def parse_variable_list(stringlist):
+        deps.remove_dups()
+
+        def parse_variable_list(vardict):
             reserved = ['prefix', 'libdir', 'includedir']
             variables = []
-            for var in stringlist:
-                # foo=bar=baz is ('foo', 'bar=baz')
-                l = var.split('=', 1)
-                if len(l) < 2:
-                    raise mesonlib.MesonException('Invalid variable "{}". Variables must be in \'name=value\' format'.format(var))
-
-                name, value = l[0].strip(), l[1].strip()
-                if not name or not value:
-                    raise mesonlib.MesonException('Invalid variable "{}". Variables must be in \'name=value\' format'.format(var))
-
-                # Variable names must not contain whitespaces
-                if any(c.isspace() for c in name):
-                    raise mesonlib.MesonException('Invalid whitespace in assignment "{}"'.format(var))
-
-                if name in reserved:
-                    raise mesonlib.MesonException('Variable "{}" is reserved'.format(name))
-
+            for name, value in vardict.items():
+                if not dataonly and name in reserved:
+                    raise mesonlib.MesonException(f'Variable "{name}" is reserved')
                 variables.append((name, value))
-
             return variables
 
-        variables = parse_variable_list(mesonlib.stringlistify(kwargs.get('variables', [])))
+        variables = self.interpreter.extract_variables(kwargs, dict_new=True)
+        variables = parse_variable_list(variables)
+        unescaped_variables = self.interpreter.extract_variables(kwargs, argname='unescaped_variables')
+        unescaped_variables = parse_variable_list(unescaped_variables)
 
         pcfile = filebase + '.pc'
-        pkgroot = kwargs.get('install_dir', default_install_dir)
+        pkgroot = pkgroot_name = kwargs.get('install_dir', default_install_dir)
         if pkgroot is None:
             if mesonlib.is_freebsd():
-                pkgroot = os.path.join(state.environment.coredata.get_builtin_option('prefix'), 'libdata', 'pkgconfig')
+                pkgroot = os.path.join(state.environment.coredata.get_option(mesonlib.OptionKey('prefix')), 'libdata', 'pkgconfig')
+                pkgroot_name = os.path.join('{prefix}', 'libdata', 'pkgconfig')
             else:
-                pkgroot = os.path.join(state.environment.coredata.get_builtin_option('libdir'), 'pkgconfig')
+                pkgroot = os.path.join(state.environment.coredata.get_option(mesonlib.OptionKey('libdir')), 'pkgconfig')
+                pkgroot_name = os.path.join('{libdir}', 'pkgconfig')
         if not isinstance(pkgroot, str):
             raise mesonlib.MesonException('Install_dir must be a string.')
-        self.generate_pkgconfig_file(state, deps, subdirs, name, description, url,
-                                     version, pcfile, conflicts, variables)
-        res = build.Data(mesonlib.File(True, state.environment.get_scratch_dir(), pcfile), pkgroot)
+        self._generate_pkgconfig_file(state, deps, subdirs, name, description, url,
+                                      version, pcfile, conflicts, variables,
+                                      unescaped_variables, False, dataonly)
+        res = build.Data([mesonlib.File(True, state.environment.get_scratch_dir(), pcfile)], pkgroot, pkgroot_name, None, state.subproject, install_tag='devel')
+        variables = self.interpreter.extract_variables(kwargs, argname='uninstalled_variables', dict_new=True)
+        variables = parse_variable_list(variables)
+        unescaped_variables = self.interpreter.extract_variables(kwargs, argname='unescaped_uninstalled_variables')
+        unescaped_variables = parse_variable_list(unescaped_variables)
+
+        pcfile = filebase + '-uninstalled.pc'
+        self._generate_pkgconfig_file(state, deps, subdirs, name, description, url,
+                                      version, pcfile, conflicts, variables,
+                                      unescaped_variables, uninstalled=True, dataonly=dataonly)
         # Associate the main library with this generated pc file. If the library
         # is used in any subsequent call to the generated, it will generate a
         # 'Requires:' or 'Requires.private:'.
@@ -461,8 +582,7 @@
             for lib in deps.pub_libs:
                 if not isinstance(lib, str) and not hasattr(lib, 'generated_pc'):
                     lib.generated_pc = filebase
-                    location = types.SimpleNamespace(subdir=state.subdir,
-                                                     lineno=state.current_lineno)
+                    location = state.current_node
                     lib.generated_pc_warn = [name, location]
         return ModuleReturnValue(res, [res])
 
diff -Nru meson-0.53.2/mesonbuild/modules/python3.py meson-0.61.2/mesonbuild/modules/python3.py
--- meson-0.53.2/mesonbuild/modules/python3.py	2019-02-07 09:08:55.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/python3.py	2022-01-02 20:12:32.000000000 +0000
@@ -13,22 +13,28 @@
 # limitations under the License.
 
 import sysconfig
-from .. import mesonlib, dependencies
+from .. import mesonlib
 
 from . import ExtensionModule
-from mesonbuild.modules import ModuleReturnValue
-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)
-        self.snippets.add('extension_module')
+        self.methods.update({
+            'extension_module': self.extension_module,
+            'find_python': self.find_python,
+            'language_version': self.language_version,
+            'sysconfig_path': self.sysconfig_path,
+        })
 
     @permittedKwargs(known_shmod_kwargs)
-    def extension_module(self, interpreter, state, args, kwargs):
+    def extension_module(self, state, args, kwargs):
         if 'name_prefix' in kwargs:
             raise mesonlib.MesonException('Name_prefix is set automatically, specifying it is forbidden.')
         if 'name_suffix' in kwargs:
@@ -44,20 +50,20 @@
             suffix = []
         kwargs['name_prefix'] = ''
         kwargs['name_suffix'] = suffix
-        return interpreter.func_shared_module(None, args, kwargs)
+        return self.interpreter.func_shared_module(None, args, kwargs)
 
     @noKwargs
     def find_python(self, state, args, kwargs):
-        command = state.environment.binaries.host.lookup_entry('python3')
+        command = state.environment.lookup_binary_entry(mesonlib.MachineChoice.HOST, 'python3')
         if command is not None:
-            py3 = dependencies.ExternalProgram.from_entry('python3', command)
+            py3 = ExternalProgram.from_entry('python3', command)
         else:
-            py3 = dependencies.ExternalProgram('python3', mesonlib.python_command, silent=True)
-        return ModuleReturnValue(py3, [py3])
+            py3 = ExternalProgram('python3', mesonlib.python_command, silent=True)
+        return py3
 
     @noKwargs
     def language_version(self, state, args, kwargs):
-        return ModuleReturnValue(sysconfig.get_python_version(), [])
+        return sysconfig.get_python_version()
 
     @noKwargs
     def sysconfig_path(self, state, args, kwargs):
@@ -66,11 +72,10 @@
         path_name = args[0]
         valid_names = sysconfig.get_path_names()
         if path_name not in valid_names:
-            raise mesonlib.MesonException('{} is not a valid path name {}.'.format(path_name, valid_names))
+            raise mesonlib.MesonException(f'{path_name} is not a valid path name {valid_names}.')
 
         # Get a relative path without a prefix, e.g. lib/python3.6/site-packages
-        path = sysconfig.get_path(path_name, vars={'base': '', 'platbase': '', 'installed_base': ''})[1:]
-        return ModuleReturnValue(path, [])
+        return sysconfig.get_path(path_name, vars={'base': '', 'platbase': '', 'installed_base': ''})[1:]
 
 
 def initialize(*args, **kwargs):
diff -Nru meson-0.53.2/mesonbuild/modules/python.py meson-0.61.2/mesonbuild/modules/python.py
--- meson-0.53.2/mesonbuild/modules/python.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/python.py	2021-12-26 16:24:25.000000000 +0000
@@ -12,122 +12,99 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os
+from pathlib import Path
+import functools
 import json
+import os
 import shutil
 import typing as T
 
-from pathlib import Path
-from .. import mesonlib
-from ..mesonlib import MesonException
 from . import ExtensionModule
-from mesonbuild.modules import ModuleReturnValue
-from ..interpreterbase import (
-    noPosargs, noKwargs, permittedKwargs,
-    InvalidArguments,
-    FeatureNew, FeatureNewKwargs, disablerIfNotFound
-)
-from ..interpreter import ExternalProgramHolder, extract_required_kwarg, permitted_kwargs
-from ..build import known_shmod_kwargs
+from .. import mesonlib
 from .. import mlog
+from ..coredata import UserFeatureOption
+from ..build import known_shmod_kwargs
+from ..dependencies import DependencyMethods, PkgConfigDependency, NotFoundDependency, SystemDependency, ExtraFrameworkDependency
+from ..dependencies.base import process_method_kw
 from ..environment import detect_cpu_family
-from ..dependencies.base import (
-    DependencyMethods, ExternalDependency,
-    ExternalProgram, PkgConfigDependency,
-    NonExistingExternalProgram
+from ..interpreter import ExternalProgramHolder, extract_required_kwarg, permitted_dependency_kwargs
+from ..interpreter.type_checking import NoneType
+from ..interpreterbase import (
+    noPosargs, noKwargs, permittedKwargs, ContainerTypeInfo,
+    InvalidArguments, typed_pos_args, typed_kwargs, KwargInfo,
+    FeatureNew, FeatureNewKwargs, disablerIfNotFound
 )
+from ..mesonlib import MachineChoice
+from ..programs import ExternalProgram, NonExistingExternalProgram
+
+if T.TYPE_CHECKING:
+    from . import ModuleState
+    from ..build import SharedModule, Data
+    from ..dependencies import ExternalDependency, Dependency
+    from ..dependencies.factory import DependencyGenerator
+    from ..environment import Environment
+    from ..interpreter import Interpreter
+    from ..interpreterbase.interpreterbase import TYPE_var, TYPE_kwargs
+
+    from typing_extensions import TypedDict
 
-mod_kwargs = set(['subdir'])
+
+mod_kwargs = {'subdir'}
 mod_kwargs.update(known_shmod_kwargs)
-mod_kwargs -= set(['name_prefix', 'name_suffix'])
+mod_kwargs -= {'name_prefix', 'name_suffix'}
+
 
-class PythonDependency(ExternalDependency):
+if T.TYPE_CHECKING:
+    _Base = ExternalDependency
+else:
+    _Base = object
 
-    def __init__(self, python_holder, environment, kwargs):
-        super().__init__('python', environment, None, kwargs)
-        self.name = 'python'
-        self.static = kwargs.get('static', False)
-        self.embed = kwargs.get('embed', False)
-        self.version = python_holder.version
+class _PythonDependencyBase(_Base):
+
+    def __init__(self, python_holder: 'PythonInstallation', embed: bool):
+        self.name = 'python'  # override the name from the "real" dependency lookup
+        self.embed = embed
+        self.version: str = python_holder.version
         self.platform = python_holder.platform
-        self.pkgdep = None
         self.variables = python_holder.variables
         self.paths = python_holder.paths
         self.link_libpython = python_holder.link_libpython
+        self.info: T.Optional[T.Dict[str, str]] = None
         if mesonlib.version_compare(self.version, '>= 3.0'):
             self.major_version = 3
         else:
             self.major_version = 2
 
-        # We first try to find the necessary python variables using pkgconfig
-        if DependencyMethods.PKGCONFIG in self.methods and not python_holder.is_pypy:
-            pkg_version = self.variables.get('LDVERSION') or self.version
-            pkg_libdir = self.variables.get('LIBPC')
-            pkg_embed = '-embed' if self.embed and mesonlib.version_compare(self.version, '>=3.8') else ''
-            pkg_name = 'python-{}{}'.format(pkg_version, pkg_embed)
-
-            # If python-X.Y.pc exists in LIBPC, we will try to use it
-            if pkg_libdir is not None and Path(os.path.join(pkg_libdir, '{}.pc'.format(pkg_name))).is_file():
-                old_pkg_libdir = os.environ.get('PKG_CONFIG_LIBDIR')
-                old_pkg_path = os.environ.get('PKG_CONFIG_PATH')
-
-                os.environ.pop('PKG_CONFIG_PATH', None)
-
-                if pkg_libdir:
-                    os.environ['PKG_CONFIG_LIBDIR'] = pkg_libdir
-
-                try:
-                    self.pkgdep = PkgConfigDependency(pkg_name, environment, kwargs)
-                    mlog.debug('Found "{}" via pkgconfig lookup in LIBPC ({})'.format(pkg_name, pkg_libdir))
-                    py_lookup_method = 'pkgconfig'
-                except MesonException as e:
-                    mlog.debug('"{}" could not be found in LIBPC ({})'.format(pkg_name, pkg_libdir))
-                    mlog.debug(e)
 
-                if old_pkg_path is not None:
-                    os.environ['PKG_CONFIG_PATH'] = old_pkg_path
+class PythonPkgConfigDependency(PkgConfigDependency, _PythonDependencyBase):
 
-                if old_pkg_libdir is not None:
-                    os.environ['PKG_CONFIG_LIBDIR'] = old_pkg_libdir
-                else:
-                    os.environ.pop('PKG_CONFIG_LIBDIR', None)
-            else:
-                mlog.debug('"{}" could not be found in LIBPC ({}), this is likely due to a relocated python installation'.format(pkg_name, pkg_libdir))
+    def __init__(self, name: str, environment: 'Environment',
+                 kwargs: T.Dict[str, T.Any], installation: 'PythonInstallation'):
+        PkgConfigDependency.__init__(self, name, environment, kwargs)
+        _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False))
+
+
+class PythonFrameworkDependency(ExtraFrameworkDependency, _PythonDependencyBase):
+
+    def __init__(self, name: str, environment: 'Environment',
+                 kwargs: T.Dict[str, T.Any], installation: 'PythonInstallation'):
+        ExtraFrameworkDependency.__init__(self, name, environment, kwargs)
+        _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False))
 
-            # If lookup via LIBPC failed, try to use fallback PKG_CONFIG_LIBDIR/PKG_CONFIG_PATH mechanisms
-            if self.pkgdep is None or not self.pkgdep.found():
-                try:
-                    self.pkgdep = PkgConfigDependency(pkg_name, environment, kwargs)
-                    mlog.debug('Found "{}" via fallback pkgconfig lookup in PKG_CONFIG_LIBDIR/PKG_CONFIG_PATH'.format(pkg_name))
-                    py_lookup_method = 'pkgconfig-fallback'
-                except MesonException as e:
-                    mlog.debug('"{}" could not be found via fallback pkgconfig lookup in PKG_CONFIG_LIBDIR/PKG_CONFIG_PATH'.format(pkg_name))
-                    mlog.debug(e)
-
-        if self.pkgdep and self.pkgdep.found():
-            self.compile_args = self.pkgdep.get_compile_args()
-            self.link_args = self.pkgdep.get_link_args()
-            self.is_found = True
-            self.pcdep = self.pkgdep
-        else:
-            self.pkgdep = None
-
-            # Finally, try to find python via SYSCONFIG as a final measure
-            if DependencyMethods.SYSCONFIG in self.methods:
-                if mesonlib.is_windows():
-                    self._find_libpy_windows(environment)
-                else:
-                    self._find_libpy(python_holder, environment)
-                if self.is_found:
-                    mlog.debug('Found "python-{}" via SYSCONFIG module'.format(self.version))
-                    py_lookup_method = 'sysconfig'
 
-        if self.is_found:
-            mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES ({})'.format(py_lookup_method)))
+class PythonSystemDependency(SystemDependency, _PythonDependencyBase):
+
+    def __init__(self, name: str, environment: 'Environment',
+                 kwargs: T.Dict[str, T.Any], installation: 'PythonInstallation'):
+        SystemDependency.__init__(self, name, environment, kwargs)
+        _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False))
+
+        if mesonlib.is_windows():
+            self._find_libpy_windows(environment)
         else:
-            mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO'))
+            self._find_libpy(installation, environment)
 
-    def _find_libpy(self, python_holder, environment):
+    def _find_libpy(self, python_holder: 'PythonInstallation', environment: 'Environment') -> None:
         if python_holder.is_pypy:
             if self.major_version == 3:
                 libname = 'pypy3-c'
@@ -136,7 +113,7 @@
             libdir = os.path.join(self.variables.get('base'), 'bin')
             libdirs = [libdir]
         else:
-            libname = 'python{}'.format(self.version)
+            libname = f'python{self.version}'
             if 'DEBUG_EXT' in self.variables:
                 libname += self.variables['DEBUG_EXT']
             if 'ABIFLAGS' in self.variables:
@@ -156,7 +133,7 @@
 
         self.compile_args += ['-I' + path for path in inc_paths if path]
 
-    def get_windows_python_arch(self):
+    def _get_windows_python_arch(self) -> T.Optional[str]:
         if self.platform == 'mingw':
             pycc = self.variables.get('CC')
             if pycc.startswith('x86_64'):
@@ -164,45 +141,48 @@
             elif pycc.startswith(('i686', 'i386')):
                 return '32'
             else:
-                mlog.log('MinGW Python built with unknown CC {!r}, please file'
-                         'a bug'.format(pycc))
+                mlog.log(f'MinGW Python built with unknown CC {pycc!r}, please file a bug')
                 return None
         elif self.platform == 'win32':
             return '32'
         elif self.platform in ('win64', 'win-amd64'):
             return '64'
-        mlog.log('Unknown Windows Python platform {!r}'.format(self.platform))
+        mlog.log(f'Unknown Windows Python platform {self.platform!r}')
         return None
 
-    def get_windows_link_args(self):
+    def _get_windows_link_args(self) -> T.Optional[T.List[str]]:
         if self.platform.startswith('win'):
             vernum = self.variables.get('py_version_nodot')
             if self.static:
-                libpath = Path('libs') / 'libpython{}.a'.format(vernum)
+                libpath = Path('libs') / f'libpython{vernum}.a'
             else:
                 comp = self.get_compiler()
                 if comp.id == "gcc":
-                    libpath = 'python{}.dll'.format(vernum)
+                    libpath = Path(f'python{vernum}.dll')
                 else:
-                    libpath = Path('libs') / 'python{}.lib'.format(vernum)
-            lib = Path(self.variables.get('base')) / libpath
+                    libpath = Path('libs') / f'python{vernum}.lib'
+            # base_prefix to allow for virtualenvs.
+            lib = Path(self.variables.get('base_prefix')) / libpath
         elif self.platform == 'mingw':
             if self.static:
                 libname = self.variables.get('LIBRARY')
             else:
                 libname = self.variables.get('LDLIBRARY')
             lib = Path(self.variables.get('LIBDIR')) / libname
+        else:
+            raise mesonlib.MesonBugException(
+                'On a Windows path, but the OS doesn\'t appear to be Windows or MinGW.')
         if not lib.exists():
             mlog.log('Could not find Python3 library {!r}'.format(str(lib)))
             return None
         return [str(lib)]
 
-    def _find_libpy_windows(self, env):
+    def _find_libpy_windows(self, env: 'Environment') -> None:
         '''
         Find python3 libraries on Windows and also verify that the arch matches
         what we are building for.
         '''
-        pyarch = self.get_windows_python_arch()
+        pyarch = self._get_windows_python_arch()
         if pyarch is None:
             self.is_found = False
             return
@@ -213,18 +193,17 @@
             arch = '64'
         else:
             # We can't cross-compile Python 3 dependencies on Windows yet
-            mlog.log('Unknown architecture {!r} for'.format(arch),
+            mlog.log(f'Unknown architecture {arch!r} for',
                      mlog.bold(self.name))
             self.is_found = False
             return
         # Pyarch ends in '32' or '64'
         if arch != pyarch:
-            mlog.log('Need', mlog.bold(self.name), 'for {}-bit, but '
-                     'found {}-bit'.format(arch, pyarch))
+            mlog.log('Need', mlog.bold(self.name), f'for {arch}-bit, but found {pyarch}-bit')
             self.is_found = False
             return
         # This can fail if the library is not found
-        largs = self.get_windows_link_args()
+        largs = self._get_windows_link_args()
         if largs is None:
             self.is_found = False
             return
@@ -243,27 +222,96 @@
 
         self.is_found = True
 
-    @staticmethod
-    def get_methods():
-        if mesonlib.is_windows():
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSCONFIG]
-        elif mesonlib.is_osx():
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.EXTRAFRAMEWORK]
-        else:
-            return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSCONFIG]
-
-    def get_pkgconfig_variable(self, variable_name, kwargs):
-        if self.pkgdep:
-            return self.pkgdep.get_pkgconfig_variable(variable_name, kwargs)
-        else:
-            return super().get_pkgconfig_variable(variable_name, kwargs)
-
 
-INTROSPECT_COMMAND = '''import sysconfig
+def python_factory(env: 'Environment', for_machine: 'MachineChoice',
+                   kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods],
+                   installation: 'PythonInstallation') -> T.List['DependencyGenerator']:
+    # We can't use the factory_methods decorator here, as we need to pass the
+    # extra installation argument
+    embed = kwargs.get('embed', False)
+    candidates: T.List['DependencyGenerator'] = []
+    pkg_version = installation.variables.get('LDVERSION') or installation.version
+
+    if DependencyMethods.PKGCONFIG in methods:
+        pkg_libdir = installation.variables.get('LIBPC')
+        pkg_embed = '-embed' if embed and mesonlib.version_compare(installation.version, '>=3.8') else ''
+        pkg_name = f'python-{pkg_version}{pkg_embed}'
+
+        # 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':
+            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
+            try:
+                return PythonPkgConfigDependency(name, env, kwargs, installation)
+            finally:
+                def set_env(name, value):
+                    if value is not None:
+                        os.environ[name] = value
+                    elif name in os.environ:
+                        del os.environ[name]
+                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)
+        ])
+
+    if DependencyMethods.SYSTEM in methods:
+        candidates.append(functools.partial(PythonSystemDependency, 'python', env, kwargs, installation))
+
+    if DependencyMethods.EXTRAFRAMEWORK in methods:
+        nkwargs = kwargs.copy()
+        if mesonlib.version_compare(pkg_version, '>= 3'):
+            # There is a python in /System/Library/Frameworks, but that's python 2.x,
+            # Python 3 will always be in /Library
+            nkwargs['paths'] = ['/Library/Frameworks']
+        candidates.append(functools.partial(PythonFrameworkDependency, 'Python', env, nkwargs, installation))
+
+    return candidates
+
+
+INTROSPECT_COMMAND = '''\
+import os.path
+import sysconfig
 import json
 import sys
+import distutils.command.install
 
-install_paths = sysconfig.get_paths(scheme='posix_prefix', vars={'base': '', 'platbase': '', 'installed_base': ''})
+def get_distutils_paths(scheme=None, prefix=None):
+    import distutils.dist
+    distribution = distutils.dist.Distribution()
+    install_cmd = distribution.get_command_obj('install')
+    if prefix is not None:
+        install_cmd.prefix = prefix
+    if scheme:
+        install_cmd.select_scheme(scheme)
+    install_cmd.finalize_options()
+    return {
+        'data': install_cmd.install_data,
+        'include': os.path.dirname(install_cmd.install_headers),
+        'platlib': install_cmd.install_platlib,
+        'purelib': install_cmd.install_purelib,
+        'scripts': install_cmd.install_scripts,
+    }
+
+# On Debian derivatives, the Python interpreter shipped by the distribution uses
+# a custom install scheme, deb_system, for the system install, and changes the
+# default scheme to a custom one pointing to /usr/local and replacing
+# site-packages with dist-packages.
+# See https://github.com/mesonbuild/meson/issues/8739.
+# XXX: We should be using sysconfig, but Debian only patches distutils.
+
+if 'deb_system' in distutils.command.install.INSTALL_SCHEMES:
+    paths = get_distutils_paths(scheme='deb_system')
+    install_paths = get_distutils_paths(scheme='deb_system', prefix='')
+else:
+    paths = sysconfig.get_paths()
+    empty_vars = {'base': '', 'platbase': '', 'installed_base': ''}
+    install_paths = sysconfig.get_paths(vars=empty_vars)
 
 def links_against_libpython():
     from distutils.core import Distribution, Extension
@@ -271,10 +319,14 @@
     cmd.ensure_finalized()
     return bool(cmd.get_libraries(Extension('dummy', [])))
 
-print (json.dumps ({
-  'variables': sysconfig.get_config_vars(),
-  'paths': sysconfig.get_paths(),
+variables = sysconfig.get_config_vars()
+variables.update({'base_prefix': getattr(sys, 'base_prefix', sys.prefix)})
+
+print(json.dumps({
+  'variables': variables,
+  'paths': paths,
   'install_paths': install_paths,
+  'sys_paths': sys.path,
   'version': sysconfig.get_python_version(),
   'platform': sysconfig.get_platform(),
   'is_pypy': '__pypy__' in sys.builtin_module_names,
@@ -282,18 +334,116 @@
 }))
 '''
 
+if T.TYPE_CHECKING:
+    class PythonIntrospectionDict(TypedDict):
+
+        install_paths: T.Dict[str, str]
+        is_pypy: bool
+        link_libpython: bool
+        paths: T.Dict[str, str]
+        platform: str
+        suffix: str
+        variables: T.Dict[str, str]
+        version: str
+
+
+class PythonExternalProgram(ExternalProgram):
+    def __init__(self, name: str, command: T.Optional[T.List[str]] = None,
+                 ext_prog: T.Optional[ExternalProgram] = None):
+        if ext_prog is None:
+            super().__init__(name, command=command, silent=True)
+        else:
+            self.name = name
+            self.command = ext_prog.command
+            self.path = ext_prog.path
+
+        # We want strong key values, so we always populate this with bogus data.
+        # Otherwise to make the type checkers happy we'd have to do .get() for
+        # everycall, even though we know that the introspection data will be
+        # complete
+        self.info: 'PythonIntrospectionDict' = {
+            'install_paths': {},
+            'is_pypy': False,
+            'link_libpython': False,
+            'paths': {},
+            'platform': 'sentinal',
+            'variables': {},
+            'version': '0.0',
+        }
+
+    def _check_version(self, version: str) -> bool:
+        if self.name == 'python2':
+            return mesonlib.version_compare(version, '< 3.0')
+        elif self.name == 'python3':
+            return mesonlib.version_compare(version, '>= 3.0')
+        return True
+
+    def sanity(self, state: T.Optional['ModuleState'] = None) -> bool:
+        # Sanity check, we expect to have something that at least quacks in tune
+        cmd = self.get_command() + ['-c', INTROSPECT_COMMAND]
+        p, stdout, stderr = mesonlib.Popen_safe(cmd)
+        try:
+            info = json.loads(stdout)
+        except json.JSONDecodeError:
+            info = None
+            mlog.debug('Could not introspect Python (%s): exit code %d' % (str(p.args), p.returncode))
+            mlog.debug('Program stdout:\n')
+            mlog.debug(stdout)
+            mlog.debug('Program stderr:\n')
+            mlog.debug(stderr)
+
+        if info is not None and self._check_version(info['version']):
+            variables = info['variables']
+            info['suffix'] = variables.get('EXT_SUFFIX') or variables.get('SO') or variables.get('.so')
+            self.info = T.cast('PythonIntrospectionDict', info)
+            self.platlib = self._get_path(state, 'platlib')
+            self.purelib = self._get_path(state, 'purelib')
+            return True
+        else:
+            return False
+
+    def _get_path(self, state: T.Optional['ModuleState'], key: str) -> None:
+        rel_path = self.info['install_paths'][key][1:]
+        if not state:
+            # This happens only from run_project_tests.py
+            return rel_path
+        value = state.get_option(f'{key}dir', module='python')
+        if value:
+            return value
+        # Use python's path relative to prefix, and warn if that's not a location
+        # python will lookup for modules.
+        abs_path = Path(state.get_option('prefix'), rel_path)
+        sys_paths = [Path(i) for i in self.info['sys_paths']]
+        if abs_path not in sys_paths:
+            mlog.warning('Python files installed by Meson might not be found by python interpreter.\n',
+                         f'This warning can be avoided by setting "python.{key}dir" option.',
+                         once=True)
+        return rel_path
+
+
+_PURE_KW = KwargInfo('pure', bool, default=True)
+_SUBDIR_KW = KwargInfo('subdir', str, default='')
+
+if T.TYPE_CHECKING:
+
+    class PyInstallKw(TypedDict):
+
+        pure: bool
+        subdir: str
+        install_tag: T.Optional[str]
+
 
 class PythonInstallation(ExternalProgramHolder):
-    def __init__(self, interpreter, python, info):
-        ExternalProgramHolder.__init__(self, python)
-        self.interpreter = interpreter
-        self.subproject = self.interpreter.subproject
-        prefix = self.interpreter.environment.coredata.get_builtin_option('prefix')
+    def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'):
+        ExternalProgramHolder.__init__(self, python, interpreter)
+        info = python.info
+        prefix = self.interpreter.environment.coredata.get_option(mesonlib.OptionKey('prefix'))
+        assert isinstance(prefix, str), 'for mypy'
         self.variables = info['variables']
+        self.suffix = info['suffix']
         self.paths = info['paths']
-        install_paths = info['install_paths']
-        self.platlib_install_path = os.path.join(prefix, install_paths['platlib'][1:])
-        self.purelib_install_path = os.path.join(prefix, install_paths['purelib'][1:])
+        self.platlib_install_path = os.path.join(prefix, python.platlib)
+        self.purelib_install_path = os.path.join(prefix, python.purelib)
         self.version = info['version']
         self.platform = info['platform']
         self.is_pypy = info['is_pypy']
@@ -313,11 +463,11 @@
         })
 
     @permittedKwargs(mod_kwargs)
-    def extension_module_method(self, args, kwargs):
-        if 'subdir' in kwargs and 'install_dir' in kwargs:
-            raise InvalidArguments('"subdir" and "install_dir" are mutually exclusive')
-
-        if 'subdir' in kwargs:
+    def extension_module_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> 'SharedModule':
+        if 'install_dir' in kwargs:
+            if 'subdir' in kwargs:
+                raise InvalidArguments('"subdir" and "install_dir" are mutually exclusive')
+        else:
             subdir = kwargs.pop('subdir', '')
             if not isinstance(subdir, str):
                 raise InvalidArguments('"subdir" argument must be a string.')
@@ -329,148 +479,137 @@
         # behavior. See https://github.com/mesonbuild/meson/issues/4117
         if not self.link_libpython:
             new_deps = []
-            for holder in mesonlib.extract_as_list(kwargs, 'dependencies'):
-                dep = holder.held_object
-                if isinstance(dep, PythonDependency):
-                    holder = self.interpreter.holderify(dep.get_partial_dependency(compile_args=True))
-                new_deps.append(holder)
+            for dep in mesonlib.extract_as_list(kwargs, 'dependencies'):
+                if isinstance(dep, _PythonDependencyBase):
+                    dep = dep.get_partial_dependency(compile_args=True)
+                new_deps.append(dep)
             kwargs['dependencies'] = new_deps
 
-        suffix = self.variables.get('EXT_SUFFIX') or self.variables.get('SO') or self.variables.get('.so')
-
         # msys2's python3 has "-cpython-36m.dll", we have to be clever
-        split = suffix.rsplit('.', 1)
-        suffix = split.pop(-1)
-        args[0] += ''.join(s for s in split)
+        # FIXME: explain what the specific cleverness is here
+        split, suffix = self.suffix.rsplit('.', 1)
+        args[0] += split
 
         kwargs['name_prefix'] = ''
         kwargs['name_suffix'] = suffix
 
         return self.interpreter.func_shared_module(None, args, kwargs)
 
-    @permittedKwargs(permitted_kwargs['dependency'])
+    @disablerIfNotFound
+    @permittedKwargs(permitted_dependency_kwargs | {'embed'})
     @FeatureNewKwargs('python_installation.dependency', '0.53.0', ['embed'])
-    def dependency_method(self, args, kwargs):
-        if args:
-            mlog.warning('python_installation.dependency() does not take any '
-                         'positional arguments. It always returns a Python '
-                         'dependency. This will become an error in the future.',
-                         location=self.interpreter.current_node)
-        dep = PythonDependency(self, self.interpreter.environment, kwargs)
-        return self.interpreter.holderify(dep)
-
-    @permittedKwargs(['pure', 'subdir'])
-    def install_sources_method(self, args, kwargs):
-        pure = kwargs.pop('pure', False)
-        if not isinstance(pure, bool):
-            raise InvalidArguments('"pure" argument must be a boolean.')
-
-        subdir = kwargs.pop('subdir', '')
-        if not isinstance(subdir, str):
-            raise InvalidArguments('"subdir" argument must be a string.')
-
-        if pure:
-            kwargs['install_dir'] = os.path.join(self.purelib_install_path, subdir)
+    @noPosargs
+    def dependency_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> 'Dependency':
+        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
+        # it's theoretically (though not practically) possible for the else clse
+        # to not bind dep, let's ensure it is.
+        dep: 'Dependency' = NotFoundDependency('python', self.interpreter.environment)
+        if disabled:
+            mlog.log('Dependency', mlog.bold('python'), 'skipped: feature', mlog.bold(feature), 'disabled')
         else:
-            kwargs['install_dir'] = os.path.join(self.platlib_install_path, subdir)
-
-        return self.interpreter.holderify(self.interpreter.func_install_data(None, args, kwargs))
+            new_kwargs = kwargs.copy()
+            new_kwargs['required'] = False
+            methods = process_method_kw({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM}, kwargs)
+            for d in python_factory(self.interpreter.environment,
+                                    MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST,
+                                    new_kwargs, methods, self):
+                dep = d()
+                if dep.found():
+                    break
+            if required and not dep.found():
+                raise mesonlib.MesonException('Python dependency not found')
+
+        return dep
+
+    @typed_pos_args('install_data', varargs=(str, mesonlib.File))
+    @typed_kwargs('python_installation.install_sources', _PURE_KW, _SUBDIR_KW,
+                  KwargInfo('install_tag', (str, NoneType), since='0.60.0'))
+    def install_sources_method(self, args: T.Tuple[T.List[T.Union[str, mesonlib.File]]],
+                               kwargs: 'PyInstallKw') -> 'Data':
+        tag = kwargs['install_tag'] or 'runtime'
+        return self.interpreter.install_data_impl(
+            self.interpreter.source_strings_to_files(args[0]),
+            self._get_install_dir_impl(kwargs['pure'], kwargs['subdir']),
+            mesonlib.FileMode(), rename=None, tag=tag, install_data_type='python',
+            install_dir_name=self._get_install_dir_name_impl(kwargs['pure'], kwargs['subdir']))
 
     @noPosargs
-    @permittedKwargs(['pure', 'subdir'])
-    def get_install_dir_method(self, args, kwargs):
-        pure = kwargs.pop('pure', True)
-        if not isinstance(pure, bool):
-            raise InvalidArguments('"pure" argument must be a boolean.')
-
-        subdir = kwargs.pop('subdir', '')
-        if not isinstance(subdir, str):
-            raise InvalidArguments('"subdir" argument must be a string.')
+    @typed_kwargs('python_installation.install_dir', _PURE_KW, _SUBDIR_KW)
+    def get_install_dir_method(self, args: T.List['TYPE_var'], kwargs: 'PyInstallKw') -> str:
+        return self._get_install_dir_impl(kwargs['pure'], kwargs['subdir'])
+
+    def _get_install_dir_impl(self, pure: bool, subdir: str) -> str:
+        return os.path.join(
+            self.purelib_install_path if pure else self.platlib_install_path, subdir)
 
-        if pure:
-            res = os.path.join(self.purelib_install_path, subdir)
-        else:
-            res = os.path.join(self.platlib_install_path, subdir)
-
-        return self.interpreter.module_method_callback(ModuleReturnValue(res, []))
+    def _get_install_dir_name_impl(self, pure: bool, subdir: str) -> str:
+        return os.path.join('{py_purelib}' if pure else '{py_platlib}', subdir)
 
     @noPosargs
     @noKwargs
-    def language_version_method(self, args, kwargs):
-        return self.interpreter.module_method_callback(ModuleReturnValue(self.version, []))
+    def language_version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
+        return self.version
 
+    @typed_pos_args('python_installation.has_path', str)
     @noKwargs
-    def has_path_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InvalidArguments('has_path takes exactly one positional argument.')
-        path_name = args[0]
-        if not isinstance(path_name, str):
-            raise InvalidArguments('has_path argument must be a string.')
-
-        return self.interpreter.module_method_callback(ModuleReturnValue(path_name in self.paths, []))
+    def has_path_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
+        return args[0] in self.paths
 
+    @typed_pos_args('python_installation.get_path', str, optargs=[object])
     @noKwargs
-    def get_path_method(self, args, kwargs):
-        if len(args) not in (1, 2):
-            raise InvalidArguments('get_path must have one or two arguments.')
-        path_name = args[0]
-        if not isinstance(path_name, str):
-            raise InvalidArguments('get_path argument must be a string.')
-
+    def get_path_method(self, args: T.Tuple[str, T.Optional['TYPE_var']], kwargs: 'TYPE_kwargs') -> 'TYPE_var':
+        path_name, fallback = args
         try:
-            path = self.paths[path_name]
+            return self.paths[path_name]
         except KeyError:
-            if len(args) == 2:
-                path = args[1]
-            else:
-                raise InvalidArguments('{} is not a valid path name'.format(path_name))
-
-        return self.interpreter.module_method_callback(ModuleReturnValue(path, []))
+            if fallback is not None:
+                return fallback
+            raise InvalidArguments(f'{path_name} is not a valid path name')
 
+    @typed_pos_args('python_installation.has_variable', str)
     @noKwargs
-    def has_variable_method(self, args, kwargs):
-        if len(args) != 1:
-            raise InvalidArguments('has_variable takes exactly one positional argument.')
-        var_name = args[0]
-        if not isinstance(var_name, str):
-            raise InvalidArguments('has_variable argument must be a string.')
-
-        return self.interpreter.module_method_callback(ModuleReturnValue(var_name in self.variables, []))
+    def has_variable_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
+        return args[0] in self.variables
 
+    @typed_pos_args('python_installation.get_variable', str, optargs=[object])
     @noKwargs
-    def get_variable_method(self, args, kwargs):
-        if len(args) not in (1, 2):
-            raise InvalidArguments('get_variable must have one or two arguments.')
-        var_name = args[0]
-        if not isinstance(var_name, str):
-            raise InvalidArguments('get_variable argument must be a string.')
-
+    def get_variable_method(self, args: T.Tuple[str, T.Optional['TYPE_var']], kwargs: 'TYPE_kwargs') -> 'TYPE_var':
+        var_name, fallback = args
         try:
-            var = self.variables[var_name]
+            return self.variables[var_name]
         except KeyError:
-            if len(args) == 2:
-                var = args[1]
-            else:
-                raise InvalidArguments('{} is not a valid variable name'.format(var_name))
-
-        return self.interpreter.module_method_callback(ModuleReturnValue(var, []))
+            if fallback is not None:
+                return fallback
+            raise InvalidArguments(f'{var_name} is not a valid variable name')
 
     @noPosargs
     @noKwargs
     @FeatureNew('Python module path method', '0.50.0')
-    def path_method(self, args, kwargs):
+    def path_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
         return super().path_method(args, kwargs)
 
 
+if T.TYPE_CHECKING:
+    from ..interpreter.kwargs import ExtractRequired
+
+    class FindInstallationKw(ExtractRequired):
+
+        disabler: bool
+        modules: T.List[str]
+
+
 class PythonModule(ExtensionModule):
 
     @FeatureNew('Python Module', '0.46.0')
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.snippets.add('find_installation')
+    def __init__(self, interpreter: 'Interpreter') -> None:
+        super().__init__(interpreter)
+        self.methods.update({
+            'find_installation': self.find_installation,
+        })
 
     # https://www.python.org/dev/peps/pep-0397/
-    def _get_win_pythonpath(self, name_or_path):
+    @staticmethod
+    def _get_win_pythonpath(name_or_path: str) -> T.Optional[str]:
         if name_or_path not in ['python2', 'python3']:
             return None
         if not shutil.which('py'):
@@ -485,66 +624,69 @@
         else:
             return None
 
-    def _check_version(self, name_or_path, version):
-        if name_or_path == 'python2':
-            return mesonlib.version_compare(version, '< 3.0')
-        elif name_or_path == 'python3':
-            return mesonlib.version_compare(version, '>= 3.0')
-        return True
-
-    @FeatureNewKwargs('python.find_installation', '0.49.0', ['disabler'])
-    @FeatureNewKwargs('python.find_installation', '0.51.0', ['modules'])
     @disablerIfNotFound
-    @permittedKwargs({'required', 'modules'})
-    def find_installation(self, interpreter, state, args, kwargs):
+    @typed_pos_args('python.find_installation', optargs=[str])
+    @typed_kwargs(
+        'python.find_installation',
+        KwargInfo('required', (bool, UserFeatureOption), default=True),
+        KwargInfo('disabler', bool, default=False, since='0.49.0'),
+        KwargInfo('modules', ContainerTypeInfo(list, str), listify=True, default=[], since='0.51.0'),
+    )
+    def find_installation(self, state: 'ModuleState', args: T.Tuple[T.Optional[str]],
+                          kwargs: 'FindInstallationKw') -> ExternalProgram:
         feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0')
         disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, feature_check)
-        want_modules = mesonlib.extract_as_list(kwargs, 'modules')  # type: T.List[str]
-        found_modules = []    # type: T.List[str]
-        missing_modules = []  # type: T.List[str]
-
-        if len(args) > 1:
-            raise InvalidArguments('find_installation takes zero or one positional argument.')
-
-        name_or_path = state.environment.binaries.host.lookup_entry('python')
-        if name_or_path is None and args:
-            name_or_path = args[0]
-            if not isinstance(name_or_path, str):
-                raise InvalidArguments('find_installation argument must be a string.')
+        want_modules = kwargs['modules']
+        found_modules: T.List[str] = []
+        missing_modules: T.List[str] = []
+
+        # FIXME: this code is *full* of sharp corners. It assumes that it's
+        # going to get a string value (or now a list of length 1), of `python2`
+        # or `python3` which is completely nonsense.  On windows the value could
+        # easily be `['py', '-3']`, or `['py', '-3.7']` to get a very specific
+        # version of python. On Linux we might want a python that's not in
+        # $PATH, or that uses a wrapper of some kind.
+        np: T.List[str] = state.environment.lookup_binary_entry(MachineChoice.HOST, 'python') or []
+        fallback = args[0]
+        display_name = fallback or 'python'
+        if not np and fallback is not None:
+            np = [fallback]
+        name_or_path = np[0] if np else None
 
         if disabled:
             mlog.log('Program', name_or_path or 'python', 'found:', mlog.red('NO'), '(disabled by:', mlog.bold(feature), ')')
-            return ExternalProgramHolder(NonExistingExternalProgram())
+            return NonExistingExternalProgram()
 
         if not name_or_path:
-            python = ExternalProgram('python3', mesonlib.python_command, silent=True)
+            python = PythonExternalProgram('python3', mesonlib.python_command)
         else:
-            python = ExternalProgram.from_entry('python3', name_or_path)
+            tmp_python = ExternalProgram.from_entry(display_name, name_or_path)
+            python = PythonExternalProgram(display_name, ext_prog=tmp_python)
 
             if not python.found() and mesonlib.is_windows():
                 pythonpath = self._get_win_pythonpath(name_or_path)
                 if pythonpath is not None:
                     name_or_path = pythonpath
-                    python = ExternalProgram(name_or_path, silent=True)
+                    python = PythonExternalProgram(name_or_path)
 
             # Last ditch effort, python2 or python3 can be named python
             # on various platforms, let's not give up just yet, if an executable
             # named python is available and has a compatible version, let's use
             # it
             if not python.found() and name_or_path in ['python2', 'python3']:
-                python = ExternalProgram('python', silent=True)
+                python = PythonExternalProgram('python')
 
         if python.found() and want_modules:
             for mod in want_modules:
-                p, out, err = mesonlib.Popen_safe(
+                p, *_ = mesonlib.Popen_safe(
                     python.command +
-                    ['-c', 'import {0}'.format(mod)])
+                    ['-c', f'import {mod}'])
                 if p.returncode != 0:
                     missing_modules.append(mod)
                 else:
                     found_modules.append(mod)
 
-        msg = ['Program', python.name]
+        msg: T.List['mlog.TV_Loggable'] = ['Program', python.name]
         if want_modules:
             msg.append('({})'.format(', '.join(want_modules)))
         msg.append('found:')
@@ -561,34 +703,25 @@
         if not python.found():
             if required:
                 raise mesonlib.MesonException('{} not found'.format(name_or_path or 'python'))
-            res = ExternalProgramHolder(NonExistingExternalProgram())
+            return NonExistingExternalProgram()
         elif missing_modules:
             if required:
                 raise mesonlib.MesonException('{} is missing modules: {}'.format(name_or_path or 'python', ', '.join(missing_modules)))
-            res = ExternalProgramHolder(NonExistingExternalProgram())
+            return NonExistingExternalProgram()
         else:
-            # Sanity check, we expect to have something that at least quacks in tune
-            try:
-                cmd = python.get_command() + ['-c', INTROSPECT_COMMAND]
-                p, stdout, stderr = mesonlib.Popen_safe(cmd)
-                info = json.loads(stdout)
-            except json.JSONDecodeError:
-                info = None
-                mlog.debug('Could not introspect Python (%s): exit code %d' % (str(p.args), p.returncode))
-                mlog.debug('Program stdout:\n')
-                mlog.debug(stdout)
-                mlog.debug('Program stderr:\n')
-                mlog.debug(stderr)
+            sane = python.sanity(state)
 
-            if isinstance(info, dict) and 'version' in info and self._check_version(name_or_path, info['version']):
-                res = PythonInstallation(interpreter, python, info)
+            if sane:
+                return python
             else:
-                res = ExternalProgramHolder(NonExistingExternalProgram())
                 if required:
-                    raise mesonlib.MesonException('{} is not a valid python or it is missing setuptools'.format(python))
+                    raise mesonlib.MesonException(f'{python} is not a valid python or it is missing distutils')
+                return NonExistingExternalProgram()
 
-        return res
+        raise mesonlib.MesonBugException('Unreachable code was reached (PythonModule.find_installation).')
 
 
-def initialize(*args, **kwargs):
-    return PythonModule(*args, **kwargs)
+def initialize(interpreter: 'Interpreter') -> PythonModule:
+    mod = PythonModule(interpreter)
+    mod.interpreter.append_holder_map(PythonExternalProgram, PythonInstallation)
+    return mod
diff -Nru meson-0.53.2/mesonbuild/modules/qt4.py meson-0.61.2/mesonbuild/modules/qt4.py
--- meson-0.53.2/mesonbuild/modules/qt4.py	2018-12-09 14:27:23.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/qt4.py	2021-04-01 21:12:21.000000000 +0000
@@ -12,7 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from .. import mlog
 from .qt import QtBaseModule
 
 
@@ -23,6 +22,4 @@
 
 
 def initialize(*args, **kwargs):
-    mlog.warning('rcc dependencies will not work properly until this upstream issue is fixed:',
-                 mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'))
     return Qt4Module(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/qt5.py meson-0.61.2/mesonbuild/modules/qt5.py
--- meson-0.53.2/mesonbuild/modules/qt5.py	2018-12-09 14:27:23.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/qt5.py	2021-04-01 21:12:21.000000000 +0000
@@ -12,7 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from .. import mlog
 from .qt import QtBaseModule
 
 
@@ -23,6 +22,4 @@
 
 
 def initialize(*args, **kwargs):
-    mlog.warning('rcc dependencies will not work reliably until this upstream issue is fixed:',
-                 mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'))
     return Qt5Module(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/qt6.py meson-0.61.2/mesonbuild/modules/qt6.py
--- meson-0.53.2/mesonbuild/modules/qt6.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/qt6.py	2022-01-02 20:12:32.000000000 +0000
@@ -0,0 +1,27 @@
+# Copyright 2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .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)
+
+
+def initialize(*args, **kwargs):
+    return Qt6Module(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/qt.py meson-0.61.2/mesonbuild/modules/qt.py
--- meson-0.53.2/mesonbuild/modules/qt.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/qt.py	2021-12-26 16:24:25.000000000 +0000
@@ -1,4 +1,5 @@
 # Copyright 2015 The Meson development team
+# Copyright © 2021 Intel Corporation
 
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,210 +14,574 @@
 # limitations under the License.
 
 import os
-from .. import mlog
-from .. import build
-from ..mesonlib import MesonException, Popen_safe, extract_as_list, File
-from ..dependencies import Dependency, Qt4Dependency, Qt5Dependency
+import shutil
+import typing as T
 import xml.etree.ElementTree as ET
-from . import ModuleReturnValue, get_include_args, ExtensionModule
-from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs
-
-_QT_DEPS_LUT = {
-    4: Qt4Dependency,
-    5: Qt5Dependency
-}
 
+from . import ModuleReturnValue, ExtensionModule
+from .. import build
+from .. import coredata
+from .. import mlog
+from ..dependencies import find_external_dependency, Dependency, ExternalLibrary
+from ..mesonlib import MesonException, File, FileOrString, version_compare, Popen_safe
+from ..interpreter import extract_required_kwarg
+from ..interpreter.type_checking import NoneType
+from ..interpreterbase import ContainerTypeInfo, FeatureDeprecated, KwargInfo, noPosargs, FeatureNew, typed_kwargs
+from ..programs import ExternalProgram, NonExistingExternalProgram
+
+if T.TYPE_CHECKING:
+    from . import ModuleState
+    from ..dependencies.qt import QtPkgConfigDependency, QmakeQtDependency
+    from ..interpreter import Interpreter
+    from ..interpreter import kwargs
+
+    QtDependencyType = T.Union[QtPkgConfigDependency, QmakeQtDependency]
+
+    from typing_extensions import TypedDict
+
+    class ResourceCompilerKwArgs(TypedDict):
+
+        """Keyword arguments for the Resource Compiler method."""
+
+        name: T.Optional[str]
+        sources: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]]
+        extra_args: T.List[str]
+        method: str
+
+    class UICompilerKwArgs(TypedDict):
+
+        """Keyword arguments for the Ui Compiler method."""
+
+        sources: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]]
+        extra_args: T.List[str]
+        method: str
+
+    class MocCompilerKwArgs(TypedDict):
+
+        """Keyword arguments for the Moc Compiler method."""
+
+        sources: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]]
+        headers: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]]
+        extra_args: T.List[str]
+        method: str
+        include_directories: T.List[T.Union[str, build.IncludeDirs]]
+        dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
+
+    class PreprocessKwArgs(TypedDict):
+
+        sources: T.List[FileOrString]
+        moc_sources: T.List[T.Union[FileOrString, build.CustomTarget]]
+        moc_headers: T.List[T.Union[FileOrString, build.CustomTarget]]
+        qresources: T.List[FileOrString]
+        ui_files: T.List[T.Union[FileOrString, build.CustomTarget]]
+        moc_extra_arguments: T.List[str]
+        rcc_extra_arguments: T.List[str]
+        uic_extra_arguments: T.List[str]
+        include_directories: T.List[T.Union[str, build.IncludeDirs]]
+        dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
+        method: str
+
+    class HasToolKwArgs(kwargs.ExtractRequired):
+
+        method: str
+
+    class CompileTranslationsKwArgs(TypedDict):
+
+        build_by_default: bool
+        install: bool
+        install_dir: T.Optional[str]
+        method: str
+        qresource: T.Optional[str]
+        rcc_extra_arguments: T.List[str]
+        ts_files: T.List[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]]
 
 class QtBaseModule(ExtensionModule):
-    tools_detected = False
+    _tools_detected = False
+    _rcc_supports_depfiles = False
+    _moc_supports_depfiles = False
 
-    def __init__(self, interpreter, qt_version=5):
+    def __init__(self, interpreter: 'Interpreter', qt_version: int = 5):
         ExtensionModule.__init__(self, interpreter)
         self.qt_version = qt_version
+        self.tools: T.Dict[str, ExternalProgram] = {
+            'moc': NonExistingExternalProgram('moc'),
+            'uic': NonExistingExternalProgram('uic'),
+            'rcc': NonExistingExternalProgram('rcc'),
+            'lrelease': NonExistingExternalProgram('lrelease'),
+        }
+        self.methods.update({
+            'has_tools': self.has_tools,
+            'preprocess': self.preprocess,
+            'compile_translations': self.compile_translations,
+            'compile_resources': self.compile_resources,
+            'compile_ui': self.compile_ui,
+            'compile_moc': self.compile_moc,
+        })
+
+    def compilers_detect(self, state: 'ModuleState', qt_dep: 'QtDependencyType') -> None:
+        """Detect Qt (4 or 5) moc, uic, rcc in the specified bindir or in PATH"""
+        # It is important that this list does not change order as the order of
+        # the returned ExternalPrograms will change as well
+        wanted = f'== {qt_dep.version}'
+
+        def gen_bins() -> T.Generator[T.Tuple[str, str], None, None]:
+            for b in self.tools:
+                if qt_dep.bindir:
+                    yield os.path.join(qt_dep.bindir, b), b
+                # prefer the -qt of the tool to the plain one, as we
+                # don't know what the unsuffixed one points to without calling it.
+                yield f'{b}-qt{qt_dep.qtver}', b
+                yield b, b
+
+        for b, name in gen_bins():
+            if self.tools[name].found():
+                continue
+
+            if name == 'lrelease':
+                arg = ['-version']
+            elif version_compare(qt_dep.version, '>= 5'):
+                arg = ['--version']
+            else:
+                arg = ['-v']
 
-    def _detect_tools(self, env, method):
-        if self.tools_detected:
-            return
-        mlog.log('Detecting Qt{version} tools'.format(version=self.qt_version))
-        # FIXME: We currently require QtX to exist while importing the module.
-        # We should make it gracefully degrade and not create any targets if
-        # the import is marked as 'optional' (not implemented yet)
-        kwargs = {'required': 'true', 'modules': 'Core', 'silent': 'true', 'method': method}
-        qt = _QT_DEPS_LUT[self.qt_version](env, kwargs)
-        # Get all tools and then make sure that they are the right version
-        self.moc, self.uic, self.rcc, self.lrelease = qt.compilers_detect(self.interpreter)
-        # Moc, uic and rcc write their version strings to stderr.
-        # Moc and rcc return a non-zero result when doing so.
-        # What kind of an idiot thought that was a good idea?
-        for compiler, compiler_name in ((self.moc, "Moc"), (self.uic, "Uic"), (self.rcc, "Rcc"), (self.lrelease, "lrelease")):
-            if compiler.found():
-                # Workaround since there is no easy way to know which tool/version support which flag
-                for flag in ['-v', '-version']:
-                    p, stdout, stderr = Popen_safe(compiler.get_command() + [flag])[0:3]
-                    if p.returncode == 0:
-                        break
-                stdout = stdout.strip()
-                stderr = stderr.strip()
-                if 'Qt {}'.format(self.qt_version) in stderr:
-                    compiler_ver = stderr
-                elif 'version {}.'.format(self.qt_version) in stderr:
-                    compiler_ver = stderr
-                elif ' {}.'.format(self.qt_version) in stdout:
-                    compiler_ver = stdout
+            # Ensure that the version of qt and each tool are the same
+            def get_version(p: ExternalProgram) -> str:
+                _, out, err = Popen_safe(p.get_command() + arg)
+                if b.startswith('lrelease') or not qt_dep.version.startswith('4'):
+                    care = out
                 else:
-                    raise MesonException('{name} preprocessor is not for Qt {version}. Output:\n{stdo}\n{stderr}'.format(
-                        name=compiler_name, version=self.qt_version, stdo=stdout, stderr=stderr))
-                mlog.log(' {}:'.format(compiler_name.lower()), mlog.green('YES'), '({path}, {version})'.format(
-                    path=compiler.get_path(), version=compiler_ver.split()[-1]))
-            else:
-                mlog.log(' {}:'.format(compiler_name.lower()), mlog.red('NO'))
-        self.tools_detected = True
+                    care = err
+                return care.split(' ')[-1].replace(')', '').strip()
 
-    def parse_qrc(self, state, rcc_file):
-        if type(rcc_file) is str:
+            p = state.find_program(b, required=False,
+                                   version_func=get_version,
+                                   wanted=wanted)
+            if p.found():
+                self.tools[name] = p
+
+    def _detect_tools(self, state: 'ModuleState', method: str, required: bool = True) -> None:
+        if self._tools_detected:
+            return
+        self._tools_detected = True
+        mlog.log(f'Detecting Qt{self.qt_version} tools')
+        kwargs = {'required': required, 'modules': 'Core', 'method': method}
+        # Just pick one to make mypy happy
+        qt = T.cast('QtPkgConfigDependency', find_external_dependency(f'qt{self.qt_version}', state.environment, kwargs))
+        if qt.found():
+            # Get all tools and then make sure that they are the right version
+            self.compilers_detect(state, qt)
+            if version_compare(qt.version, '>=5.15.0'):
+                self._moc_supports_depfiles = True
+            else:
+                mlog.warning('moc dependencies will not work properly until you move to Qt >= 5.15', fatal=False)
+            if version_compare(qt.version, '>=5.14.0'):
+                self._rcc_supports_depfiles = True
+            else:
+                mlog.warning('rcc dependencies will not work properly until you move to Qt >= 5.14:',
+                             mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'), fatal=False)
+        else:
+            suffix = f'-qt{self.qt_version}'
+            self.tools['moc'] = NonExistingExternalProgram(name='moc' + suffix)
+            self.tools['uic'] = NonExistingExternalProgram(name='uic' + suffix)
+            self.tools['rcc'] = NonExistingExternalProgram(name='rcc' + suffix)
+            self.tools['lrelease'] = NonExistingExternalProgram(name='lrelease' + suffix)
+
+    @staticmethod
+    def _qrc_nodes(state: 'ModuleState', rcc_file: 'FileOrString') -> T.Tuple[str, T.List[str]]:
+        abspath: str
+        if isinstance(rcc_file, str):
             abspath = os.path.join(state.environment.source_dir, state.subdir, rcc_file)
             rcc_dirname = os.path.dirname(abspath)
-        elif type(rcc_file) is File:
+        else:
             abspath = rcc_file.absolute_path(state.environment.source_dir, state.environment.build_dir)
             rcc_dirname = os.path.dirname(abspath)
 
+        # FIXME: what error are we actually trying to check here?
         try:
             tree = ET.parse(abspath)
             root = tree.getroot()
-            result = []
+            result: T.List[str] = []
             for child in root[0]:
                 if child.tag != 'file':
-                    mlog.warning("malformed rcc file: ", os.path.join(state.subdir, rcc_file))
+                    mlog.warning("malformed rcc file: ", os.path.join(state.subdir, str(rcc_file)))
                     break
                 else:
-                    resource_path = child.text
-                    # We need to guess if the pointed resource is:
-                    #   a) in build directory -> implies a generated file
-                    #   b) in source directory
-                    #   c) somewhere else external dependency file to bundle
-                    #
-                    # Also from qrc documentation: relative path are always from qrc file
-                    # So relative path must always be computed from qrc file !
-                    if os.path.isabs(resource_path):
-                        # a)
-                        if resource_path.startswith(os.path.abspath(state.environment.build_dir)):
-                            resource_relpath = os.path.relpath(resource_path, state.environment.build_dir)
-                            result.append(File(is_built=True, subdir='', fname=resource_relpath))
-                        # either b) or c)
-                        else:
-                            result.append(File(is_built=False, subdir=state.subdir, fname=resource_path))
-                    else:
-                        path_from_rcc = os.path.normpath(os.path.join(rcc_dirname, resource_path))
-                        # a)
-                        if path_from_rcc.startswith(state.environment.build_dir):
-                            result.append(File(is_built=True, subdir=state.subdir, fname=resource_path))
-                        # b)
-                        else:
-                            result.append(File(is_built=False, subdir=state.subdir, fname=path_from_rcc))
-            return result
+                    result.append(child.text)
+
+            return rcc_dirname, result
         except Exception:
-            return []
+            raise MesonException(f'Unable to parse resource file {abspath}')
 
-    @FeatureNewKwargs('qt.preprocess', '0.49.0', ['uic_extra_arguments'])
-    @FeatureNewKwargs('qt.preprocess', '0.44.0', ['moc_extra_arguments'])
-    @FeatureNewKwargs('qt.preprocess', '0.49.0', ['rcc_extra_arguments'])
-    @permittedKwargs({'moc_headers', 'moc_sources', 'uic_extra_arguments', 'moc_extra_arguments', 'rcc_extra_arguments', 'include_directories', 'dependencies', 'ui_files', 'qresources', 'method'})
-    def preprocess(self, state, args, kwargs):
-        rcc_files, ui_files, moc_headers, moc_sources, uic_extra_arguments, moc_extra_arguments, rcc_extra_arguments, sources, include_directories, dependencies \
-            = extract_as_list(kwargs, 'qresources', 'ui_files', 'moc_headers', 'moc_sources', 'uic_extra_arguments', 'moc_extra_arguments', 'rcc_extra_arguments', 'sources', 'include_directories', 'dependencies', pop = True)
-        sources += args[1:]
+    def _parse_qrc_deps(self, state: 'ModuleState',
+                        rcc_file_: T.Union['FileOrString', build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]) -> T.List[File]:
+        result: T.List[File] = []
+        inputs: T.Sequence['FileOrString'] = []
+        if isinstance(rcc_file_, (str, File)):
+            inputs = [rcc_file_]
+        else:
+            inputs = rcc_file_.get_outputs()
+
+        for rcc_file in inputs:
+            rcc_dirname, nodes = self._qrc_nodes(state, rcc_file)
+            for resource_path in nodes:
+                # We need to guess if the pointed resource is:
+                #   a) in build directory -> implies a generated file
+                #   b) in source directory
+                #   c) somewhere else external dependency file to bundle
+                #
+                # Also from qrc documentation: relative path are always from qrc file
+                # So relative path must always be computed from qrc file !
+                if os.path.isabs(resource_path):
+                    # a)
+                    if resource_path.startswith(os.path.abspath(state.environment.build_dir)):
+                        resource_relpath = os.path.relpath(resource_path, state.environment.build_dir)
+                        result.append(File(is_built=True, subdir='', fname=resource_relpath))
+                    # either b) or c)
+                    else:
+                        result.append(File(is_built=False, subdir=state.subdir, fname=resource_path))
+                else:
+                    path_from_rcc = os.path.normpath(os.path.join(rcc_dirname, resource_path))
+                    # a)
+                    if path_from_rcc.startswith(state.environment.build_dir):
+                        result.append(File(is_built=True, subdir=state.subdir, fname=resource_path))
+                    # b)
+                    else:
+                        result.append(File(is_built=False, subdir=state.subdir, fname=path_from_rcc))
+        return result
+
+    @FeatureNew('qt.has_tools', '0.54.0')
+    @noPosargs
+    @typed_kwargs(
+        'qt.has_tools',
+        KwargInfo('required', (bool, coredata.UserFeatureOption), default=False),
+        KwargInfo('method', str, default='auto'),
+    )
+    def has_tools(self, state: 'ModuleState', args: T.Tuple, kwargs: 'HasToolKwArgs') -> bool:
         method = kwargs.get('method', 'auto')
-        self._detect_tools(state.environment, method)
-        err_msg = "{0} sources specified and couldn't find {1}, " \
-                  "please check your qt{2} installation"
-        if (moc_headers or moc_sources) and not self.moc.found():
-            raise MesonException(err_msg.format('MOC', 'moc-qt{}'.format(self.qt_version), self.qt_version))
-        if rcc_files:
-            if not self.rcc.found():
-                raise MesonException(err_msg.format('RCC', 'rcc-qt{}'.format(self.qt_version), self.qt_version))
+        # We have to cast here because TypedDicts are invariant, even though
+        # ExtractRequiredKwArgs is a subset of HasToolKwArgs, type checkers
+        # will insist this is wrong
+        disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, default=False)
+        if disabled:
+            mlog.log('qt.has_tools skipped: feature', mlog.bold(feature), 'disabled')
+            return False
+        self._detect_tools(state, method, required=False)
+        for tool in self.tools.values():
+            if not tool.found():
+                if required:
+                    raise MesonException('Qt tools not found')
+                return False
+        return True
+
+    @FeatureNew('qt.compile_resources', '0.59.0')
+    @noPosargs
+    @typed_kwargs(
+        'qt.compile_resources',
+        KwargInfo('name', (str, NoneType)),
+        KwargInfo(
+            'sources',
+            ContainerTypeInfo(list, (File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), allow_empty=False),
+            listify=True,
+            required=True,
+        ),
+        KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
+        KwargInfo('method', str, default='auto')
+    )
+    def compile_resources(self, state: 'ModuleState', args: T.Tuple, kwargs: 'ResourceCompilerKwArgs') -> ModuleReturnValue:
+        """Compile Qt resources files.
+
+        Uses CustomTargets to generate .cpp files from .qrc files.
+        """
+        if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['sources']):
+            FeatureNew.single_use('qt.compile_resources: custom_target or generator for "sources" keyword argument',
+                                  '0.60.0', state.subproject, location=state.current_node)
+        out = self._compile_resources_impl(state, kwargs)
+        return ModuleReturnValue(out, [out])
+
+    def _compile_resources_impl(self, state: 'ModuleState', kwargs: 'ResourceCompilerKwArgs') -> T.List[build.CustomTarget]:
+        # Avoid the FeatureNew when dispatching from preprocess
+        self._detect_tools(state, kwargs['method'])
+        if not self.tools['rcc'].found():
+            err_msg = ("{0} sources specified and couldn't find {1}, "
+                       "please check your qt{2} installation")
+            raise MesonException(err_msg.format('RCC', f'rcc-qt{self.qt_version}', self.qt_version))
+
+        # List of generated CustomTargets
+        targets: T.List[build.CustomTarget] = []
+
+        # depfile arguments
+        DEPFILE_ARGS: T.List[str] = ['--depfile', '@DEPFILE@'] if self._rcc_supports_depfiles else []
+
+        name = kwargs['name']
+        sources: T.List['FileOrString'] = []
+        for s in kwargs['sources']:
+            if isinstance(s, (str, File)):
+                sources.append(s)
+            else:
+                sources.extend(s.get_outputs())
+        extra_args = kwargs['extra_args']
+
+        # If a name was set generate a single .cpp file from all of the qrc
+        # files, otherwise generate one .cpp file per qrc file.
+        if name:
+            qrc_deps: T.List[File] = []
+            for s in sources:
+                qrc_deps.extend(self._parse_qrc_deps(state, s))
+
+            rcc_kwargs: T.Dict[str, T.Any] = {  # TODO: if CustomTarget had typing information we could use that here...
+                'input': sources,
+                'output': name + '.cpp',
+                'command': self.tools['rcc'].get_command() + ['-name', name, '-o', '@OUTPUT@'] + extra_args + ['@INPUT@'] + DEPFILE_ARGS,
+                'depend_files': qrc_deps,
+                'depfile': f'{name}.d',
+            }
+            res_target = build.CustomTarget(name, state.subdir, state.subproject, rcc_kwargs)
+            targets.append(res_target)
+        else:
+            for rcc_file in sources:
+                qrc_deps = self._parse_qrc_deps(state, rcc_file)
+                if isinstance(rcc_file, str):
+                    basename = os.path.basename(rcc_file)
+                else:
+                    basename = os.path.basename(rcc_file.fname)
+                name = f'qt{self.qt_version}-{basename.replace(".", "_")}'
+                rcc_kwargs = {
+                    'input': rcc_file,
+                    'output': f'{name}.cpp',
+                    'command': self.tools['rcc'].get_command() + ['-name', '@BASENAME@', '-o', '@OUTPUT@'] + extra_args + ['@INPUT@'] + DEPFILE_ARGS,
+                    'depend_files': qrc_deps,
+                    'depfile': f'{name}.d',
+                }
+                res_target = build.CustomTarget(name, state.subdir, state.subproject, rcc_kwargs)
+                targets.append(res_target)
+
+        return targets
+
+    @FeatureNew('qt.compile_ui', '0.59.0')
+    @noPosargs
+    @typed_kwargs(
+        'qt.compile_ui',
+        KwargInfo(
+            'sources',
+            ContainerTypeInfo(list, (File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), allow_empty=False),
+            listify=True,
+            required=True,
+        ),
+        KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
+        KwargInfo('method', str, default='auto')
+    )
+    def compile_ui(self, state: 'ModuleState', args: T.Tuple, kwargs: 'UICompilerKwArgs') -> ModuleReturnValue:
+        """Compile UI resources into cpp headers."""
+        if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['sources']):
+            FeatureNew.single_use('qt.compile_ui: custom_target or generator for "sources" keyword argument',
+                                  '0.60.0', state.subproject, location=state.current_node)
+        out = self._compile_ui_impl(state, kwargs)
+        return ModuleReturnValue(out, [out])
+
+    def _compile_ui_impl(self, state: 'ModuleState', kwargs: 'UICompilerKwArgs') -> build.GeneratedList:
+        # Avoid the FeatureNew when dispatching from preprocess
+        self._detect_tools(state, kwargs['method'])
+        if not self.tools['uic'].found():
+            err_msg = ("{0} sources specified and couldn't find {1}, "
+                       "please check your qt{2} installation")
+            raise MesonException(err_msg.format('UIC', f'uic-qt{self.qt_version}', self.qt_version))
+
+        # TODO: This generator isn't added to the generator list in the Interpreter
+        gen = build.Generator(
+            self.tools['uic'],
+            kwargs['extra_args'] + ['-o', '@OUTPUT@', '@INPUT@'],
+            ['ui_@BASENAME@.h'],
+            name=f'Qt{self.qt_version} ui')
+        return gen.process_files(kwargs['sources'], state)
+
+    @FeatureNew('qt.compile_moc', '0.59.0')
+    @noPosargs
+    @typed_kwargs(
+        'qt.compile_moc',
+        KwargInfo(
+            'sources',
+            ContainerTypeInfo(list, (File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)),
+            listify=True,
+            default=[],
+        ),
+        KwargInfo(
+            'headers',
+            ContainerTypeInfo(list, (File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)),
+            listify=True,
+            default=[]
+        ),
+        KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
+        KwargInfo('method', str, default='auto'),
+        KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]),
+        KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]),
+    )
+    def compile_moc(self, state: 'ModuleState', args: T.Tuple, kwargs: 'MocCompilerKwArgs') -> ModuleReturnValue:
+        if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['headers']):
+            FeatureNew.single_use('qt.compile_moc: custom_target or generator for "headers" keyword argument',
+                                  '0.60.0', state.subproject, location=state.current_node)
+        if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['sources']):
+            FeatureNew.single_use('qt.compile_moc: custom_target or generator for "sources" keyword argument',
+                                  '0.60.0', state.subproject, location=state.current_node)
+        out = self._compile_moc_impl(state, kwargs)
+        return ModuleReturnValue(out, [out])
+
+    def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') -> T.List[build.GeneratedList]:
+        # Avoid the FeatureNew when dispatching from preprocess
+        self._detect_tools(state, kwargs['method'])
+        if not self.tools['moc'].found():
+            err_msg = ("{0} sources specified and couldn't find {1}, "
+                       "please check your qt{2} installation")
+            raise MesonException(err_msg.format('MOC', f'uic-qt{self.qt_version}', self.qt_version))
+
+        if not (kwargs['headers'] or kwargs['sources']):
+            raise build.InvalidArguments('At least one of the "headers" or "sources" keyword arguments must be provided and not empty')
+
+        inc = state.get_include_args(include_dirs=kwargs['include_directories'])
+        compile_args: T.List[str] = []
+        for dep in kwargs['dependencies']:
+            compile_args.extend([a for a in dep.get_all_compile_args() if a.startswith(('-I', '-D'))])
+
+        output: T.List[build.GeneratedList] = []
+
+        # depfile arguments (defaults to .d)
+        DEPFILE_ARGS: T.List[str] = ['--output-dep-file'] if self._moc_supports_depfiles else []
+
+        arguments = kwargs['extra_args'] + DEPFILE_ARGS + inc + compile_args + ['@INPUT@', '-o', '@OUTPUT@']
+        if kwargs['headers']:
+            moc_gen = build.Generator(
+                self.tools['moc'], arguments, ['moc_@BASENAME@.cpp'],
+                depfile='moc_@BASENAME@.cpp.d',
+                name=f'Qt{self.qt_version} moc header')
+            output.append(moc_gen.process_files(kwargs['headers'], state))
+        if kwargs['sources']:
+            moc_gen = build.Generator(
+                self.tools['moc'], arguments, ['@BASENAME@.moc'],
+                depfile='@BASENAME.moc.d@',
+                name=f'Qt{self.qt_version} moc source')
+            output.append(moc_gen.process_files(kwargs['sources'], state))
+
+        return output
+
+    # We can't use typed_pos_args here, the signature is ambiguous
+    @typed_kwargs(
+        'qt.preprocess',
+        KwargInfo('sources', ContainerTypeInfo(list, (File, str)), listify=True, default=[], deprecated='0.59.0'),
+        KwargInfo('qresources', ContainerTypeInfo(list, (File, str)), listify=True, default=[]),
+        KwargInfo('ui_files', ContainerTypeInfo(list, (File, str, build.CustomTarget)), listify=True, default=[]),
+        KwargInfo('moc_sources', ContainerTypeInfo(list, (File, str, build.CustomTarget)), listify=True, default=[]),
+        KwargInfo('moc_headers', ContainerTypeInfo(list, (File, str, build.CustomTarget)), listify=True, default=[]),
+        KwargInfo('moc_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.44.0'),
+        KwargInfo('rcc_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.49.0'),
+        KwargInfo('uic_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.49.0'),
+        KwargInfo('method', str, default='auto'),
+        KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]),
+        KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]),
+    )
+    def preprocess(self, state: 'ModuleState', args: T.List[T.Union[str, File]], kwargs: 'PreprocessKwArgs') -> ModuleReturnValue:
+        _sources = args[1:]
+        if _sources:
+            FeatureDeprecated.single_use('qt.preprocess positional sources', '0.59', state.subproject, location=state.current_node)
+        # List is invariant, os we have to cast...
+        sources = T.cast(T.List[T.Union[str, File, build.GeneratedList, build.CustomTarget]],
+                         _sources + kwargs['sources'])
+        for s in sources:
+            if not isinstance(s, (str, File)):
+                raise build.InvalidArguments('Variadic arguments to qt.preprocess must be Strings or Files')
+        method = kwargs['method']
+
+        if kwargs['qresources']:
             # custom output name set? -> one output file, multiple otherwise
+            rcc_kwargs: 'ResourceCompilerKwArgs' = {'name': '', 'sources': kwargs['qresources'], 'extra_args': kwargs['rcc_extra_arguments'], 'method': method}
             if args:
-                qrc_deps = []
-                for i in rcc_files:
-                    qrc_deps += self.parse_qrc(state, i)
                 name = args[0]
-                rcc_kwargs = {'input': rcc_files,
-                              'output': name + '.cpp',
-                              'command': [self.rcc, '-name', name, '-o', '@OUTPUT@', rcc_extra_arguments, '@INPUT@'],
-                              'depend_files': qrc_deps}
-                res_target = build.CustomTarget(name, state.subdir, state.subproject, rcc_kwargs)
-                sources.append(res_target)
-            else:
-                for rcc_file in rcc_files:
-                    qrc_deps = self.parse_qrc(state, rcc_file)
-                    if type(rcc_file) is str:
-                        basename = os.path.basename(rcc_file)
-                    elif type(rcc_file) is File:
-                        basename = os.path.basename(rcc_file.fname)
-                    name = 'qt' + str(self.qt_version) + '-' + basename.replace('.', '_')
-                    rcc_kwargs = {'input': rcc_file,
-                                  'output': name + '.cpp',
-                                  'command': [self.rcc, '-name', '@BASENAME@', '-o', '@OUTPUT@', rcc_extra_arguments, '@INPUT@'],
-                                  'depend_files': qrc_deps}
-                    res_target = build.CustomTarget(name, state.subdir, state.subproject, rcc_kwargs)
-                    sources.append(res_target)
-        if ui_files:
-            if not self.uic.found():
-                raise MesonException(err_msg.format('UIC', 'uic-qt{}'.format(self.qt_version), self.qt_version))
-            arguments = uic_extra_arguments + ['-o', '@OUTPUT@', '@INPUT@']
-            ui_kwargs = {'output': 'ui_@BASENAME@.h',
-                         'arguments': arguments}
-            ui_gen = build.Generator([self.uic], ui_kwargs)
-            ui_output = ui_gen.process_files('Qt{} ui'.format(self.qt_version), ui_files, state)
-            sources.append(ui_output)
-        inc = get_include_args(include_dirs=include_directories)
-        compile_args = []
-        for dep in dependencies:
-            if hasattr(dep, 'held_object'):
-                dep = dep.held_object
-            if isinstance(dep, Dependency):
-                for arg in dep.get_compile_args():
-                    if arg.startswith('-I') or arg.startswith('-D'):
-                        compile_args.append(arg)
-            else:
-                raise MesonException('Argument is of an unacceptable type {!r}.\nMust be '
-                                     'either an external dependency (returned by find_library() or '
-                                     'dependency()) or an internal dependency (returned by '
-                                     'declare_dependency()).'.format(type(dep).__name__))
-        if moc_headers:
-            arguments = moc_extra_arguments + inc + compile_args + ['@INPUT@', '-o', '@OUTPUT@']
-            moc_kwargs = {'output': 'moc_@BASENAME@.cpp',
-                          'arguments': arguments}
-            moc_gen = build.Generator([self.moc], moc_kwargs)
-            moc_output = moc_gen.process_files('Qt{} moc header'.format(self.qt_version), moc_headers, state)
-            sources.append(moc_output)
-        if moc_sources:
-            arguments = moc_extra_arguments + inc + compile_args + ['@INPUT@', '-o', '@OUTPUT@']
-            moc_kwargs = {'output': '@BASENAME@.moc',
-                          'arguments': arguments}
-            moc_gen = build.Generator([self.moc], moc_kwargs)
-            moc_output = moc_gen.process_files('Qt{} moc source'.format(self.qt_version), moc_sources, state)
-            sources.append(moc_output)
-        return ModuleReturnValue(sources, sources)
+                if not isinstance(name, str):
+                    raise build.InvalidArguments('First argument to qt.preprocess must be a string')
+                rcc_kwargs['name'] = name
+            sources.extend(self._compile_resources_impl(state, rcc_kwargs))
+
+        if kwargs['ui_files']:
+            ui_kwargs: 'UICompilerKwArgs' = {'sources': kwargs['ui_files'], 'extra_args': kwargs['uic_extra_arguments'], 'method': method}
+            sources.append(self._compile_ui_impl(state, ui_kwargs))
+
+        if kwargs['moc_headers'] or kwargs['moc_sources']:
+            moc_kwargs: 'MocCompilerKwArgs' = {
+                'extra_args': kwargs['moc_extra_arguments'],
+                'sources': kwargs['moc_sources'],
+                'headers': kwargs['moc_headers'],
+                'include_directories': kwargs['include_directories'],
+                'dependencies': kwargs['dependencies'],
+                'method': method,
+            }
+            sources.extend(self._compile_moc_impl(state, moc_kwargs))
+
+        return ModuleReturnValue(sources, [sources])
 
     @FeatureNew('qt.compile_translations', '0.44.0')
-    @permittedKwargs({'ts_files', 'install', 'install_dir', 'build_by_default', 'method'})
-    def compile_translations(self, state, args, kwargs):
-        ts_files, install_dir = extract_as_list(kwargs, 'ts_files', 'install_dir', pop=True)
-        self._detect_tools(state.environment, kwargs.get('method', 'auto'))
-        translations = []
+    @noPosargs
+    @typed_kwargs(
+        'qt.compile_translations',
+        KwargInfo('build_by_default', bool, default=False),
+        KwargInfo('install', bool, default=False),
+        KwargInfo('install_dir', (str, NoneType)),
+        KwargInfo('method', str, default='auto'),
+        KwargInfo('qresource', (str, NoneType), since='0.56.0'),
+        KwargInfo('rcc_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.56.0'),
+        KwargInfo('ts_files', ContainerTypeInfo(list, (str, File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)), listify=True, default=[]),
+    )
+    def compile_translations(self, state: 'ModuleState', args: T.Tuple, kwargs: 'CompileTranslationsKwArgs') -> ModuleReturnValue:
+        ts_files = kwargs['ts_files']
+        if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in ts_files):
+            FeatureNew.single_use('qt.compile_translations: custom_target or generator for "ts_files" keyword argument',
+                                  '0.60.0', state.subproject, location=state.current_node)
+        install_dir = kwargs['install_dir']
+        qresource = kwargs['qresource']
+        if qresource:
+            if ts_files:
+                raise MesonException('qt.compile_translations: Cannot specify both ts_files and qresource')
+            if os.path.dirname(qresource) != '':
+                raise MesonException('qt.compile_translations: qresource file name must not contain a subdirectory.')
+            qresource_file = File.from_built_file(state.subdir, qresource)
+            infile_abs = os.path.join(state.environment.source_dir, qresource_file.relative_name())
+            outfile_abs = os.path.join(state.environment.build_dir, qresource_file.relative_name())
+            os.makedirs(os.path.dirname(outfile_abs), exist_ok=True)
+            shutil.copy2(infile_abs, outfile_abs)
+            self.interpreter.add_build_def_file(infile_abs)
+
+            _, nodes = self._qrc_nodes(state, qresource_file)
+            for c in nodes:
+                if c.endswith('.qm'):
+                    ts_files.append(c.rstrip('.qm') + '.ts')
+                else:
+                    raise MesonException(f'qt.compile_translations: qresource can only contain qm files, found {c}')
+            results = self.preprocess(state, [], {'qresources': qresource_file, 'rcc_extra_arguments': kwargs['rcc_extra_arguments']})
+        self._detect_tools(state, kwargs['method'])
+        translations: T.List[build.CustomTarget] = []
         for ts in ts_files:
-            if not self.lrelease.found():
+            if not self.tools['lrelease'].found():
                 raise MesonException('qt.compile_translations: ' +
-                                     self.lrelease.name + ' not found')
-            cmd = [self.lrelease, '@INPUT@', '-qm', '@OUTPUT@']
-            lrelease_kwargs = {'output': '@BASENAME@.qm',
-                               'input': ts,
-                               'install': kwargs.get('install', False),
-                               'build_by_default': kwargs.get('build_by_default', False),
-                               'command': cmd}
-            if install_dir is not None:
-                lrelease_kwargs['install_dir'] = install_dir
-            lrelease_target = build.CustomTarget('qt{}-compile-{}'.format(self.qt_version, ts), state.subdir, state.subproject, lrelease_kwargs)
+                                     self.tools['lrelease'].name + ' not found')
+            if qresource:
+                # In this case we know that ts_files is always a List[str], as
+                # it's generated above and no ts_files are passed in. However,
+                # mypy can't figure that out so we use assert to assure it that
+                # what we're doing is safe
+                assert isinstance(ts, str), 'for mypy'
+                outdir = os.path.dirname(os.path.normpath(os.path.join(state.subdir, ts)))
+                ts = os.path.basename(ts)
+            else:
+                outdir = state.subdir
+            cmd = [self.tools['lrelease'], '@INPUT@', '-qm', '@OUTPUT@']
+            lrelease_kwargs: T.Dict[str, T.Any] = {
+                'output': '@BASENAME@.qm',
+                'input': ts,
+                'install': kwargs['install'],
+                'install_dir': install_dir or [],
+                'install_tag': 'i18n',
+                'build_by_default': kwargs['build_by_default'],
+                'command': cmd}
+            lrelease_target = build.CustomTarget(f'qt{self.qt_version}-compile-{ts}', outdir, state.subproject, lrelease_kwargs)
             translations.append(lrelease_target)
-        return ModuleReturnValue(translations, translations)
+        if qresource:
+            return ModuleReturnValue(results.return_value[0], [results.new_objects, translations])
+        else:
+            return ModuleReturnValue(translations, [translations])
diff -Nru meson-0.53.2/mesonbuild/modules/rpm.py meson-0.61.2/mesonbuild/modules/rpm.py
--- meson-0.53.2/mesonbuild/modules/rpm.py	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/rpm.py	2022-01-17 10:50:45.000000000 +0000
@@ -20,25 +20,28 @@
 import datetime
 from .. import mlog
 from . import GirTarget, TypelibTarget
-from . import ModuleReturnValue
 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, coredata, args, kwargs):
-        self.coredata = coredata
-        required_compilers = self.__get_required_compilers()
-        proj = coredata.project_name.replace(' ', '_').replace('\t', '_')
+    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 coredata.targets.values():
+        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:
@@ -57,21 +60,24 @@
                 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 coredata.headers:
+        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 coredata.man:
+        for man in state.man:
             for man_file in man.get_sources():
-                files.add('%%{_mandir}/man%u/%s.*' % (int(man_file.split('.')[-1]), man_file))
+                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(coredata.environment.get_build_dir(),
+        filename = os.path.join(state.environment.get_build_dir(),
                                 '%s.spec' % proj)
-        with open(filename, 'w+') as fn:
+        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')
@@ -83,7 +89,7 @@
             fn.write('BuildRequires: meson\n')
             for compiler in required_compilers:
                 fn.write('BuildRequires: %s\n' % compiler)
-            for dep in coredata.environment.coredata.deps.host:
+            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
@@ -147,11 +153,10 @@
             fn.write('- \n')
             fn.write('\n')
         mlog.log('RPM spec template written to %s.spec.\n' % proj)
-        return ModuleReturnValue(None, [])
 
-    def __get_required_compilers(self):
+    def __get_required_compilers(self, state):
         required_compilers = set()
-        for compiler in self.coredata.environment.coredata.compilers.host.values():
+        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')
diff -Nru meson-0.53.2/mesonbuild/modules/sourceset.py meson-0.61.2/mesonbuild/modules/sourceset.py
--- meson-0.53.2/mesonbuild/modules/sourceset.py	2019-08-28 17:15:39.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/sourceset.py	2021-08-18 11:22:15.000000000 +0000
@@ -14,25 +14,21 @@
 
 from collections import namedtuple
 from .. import mesonlib
-from ..mesonlib import listify
-from . import ExtensionModule
+from .. import build
+from ..mesonlib import listify, OrderedSet
+from . import ExtensionModule, ModuleObject, MutableModuleObject
 from ..interpreterbase import (
     noPosargs, noKwargs, permittedKwargs,
-    InterpreterObject, MutableInterpreterObject, ObjectHolder,
     InterpreterException, InvalidArguments, InvalidCode, FeatureNew,
 )
-from ..interpreter import (
-    GeneratedListHolder, CustomTargetHolder,
-    CustomTargetIndexHolder
-)
 
 SourceSetRule = namedtuple('SourceSetRule', 'keys sources if_false sourcesets dependencies extra_deps')
 SourceFiles = namedtuple('SourceFiles', 'sources dependencies')
 
-class SourceSetHolder(MutableInterpreterObject, ObjectHolder):
+class SourceSet(MutableModuleObject):
     def __init__(self, interpreter):
-        MutableInterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, list())
+        super().__init__()
+        self.rules = []
         self.subproject = interpreter.subproject
         self.environment = interpreter.environment
         self.subdir = interpreter.subdir
@@ -50,8 +46,8 @@
         deps = []
         for x in arg:
             if isinstance(x, (str, mesonlib.File,
-                              GeneratedListHolder, CustomTargetHolder,
-                              CustomTargetIndexHolder)):
+                              build.GeneratedList, build.CustomTarget,
+                              build.CustomTargetIndex)):
                 sources.append(x)
             elif hasattr(x, 'found'):
                 if not allow_deps:
@@ -77,7 +73,7 @@
         return keys, deps
 
     @permittedKwargs(['when', 'if_false', 'if_true'])
-    def add_method(self, args, kwargs):
+    def add_method(self, state, args, kwargs):
         if self.frozen:
             raise InvalidCode('Tried to use \'add\' after querying the source set')
         when = listify(kwargs.get('when', []))
@@ -90,10 +86,10 @@
         keys, dependencies = self.check_conditions(when)
         sources, extra_deps = self.check_source_files(if_true, True)
         if_false, _ = self.check_source_files(if_false, False)
-        self.held_object.append(SourceSetRule(keys, sources, if_false, [], dependencies, extra_deps))
+        self.rules.append(SourceSetRule(keys, sources, if_false, [], dependencies, extra_deps))
 
     @permittedKwargs(['when', 'if_true'])
-    def add_all_method(self, args, kwargs):
+    def add_all_method(self, state, args, kwargs):
         if self.frozen:
             raise InvalidCode('Tried to use \'add_all\' after querying the source set')
         when = listify(kwargs.get('when', []))
@@ -104,15 +100,15 @@
             raise InterpreterException('add_all called with both positional and keyword arguments')
         keys, dependencies = self.check_conditions(when)
         for s in if_true:
-            if not isinstance(s, SourceSetHolder):
+            if not isinstance(s, SourceSet):
                 raise InvalidCode('Arguments to \'add_all\' after the first must be source sets')
             s.frozen = True
-        self.held_object.append(SourceSetRule(keys, [], [], if_true, dependencies, []))
+        self.rules.append(SourceSetRule(keys, [], [], if_true, dependencies, []))
 
     def collect(self, enabled_fn, all_sources, into=None):
         if not into:
-            into = SourceFiles(set(), set())
-        for entry in self.held_object:
+            into = SourceFiles(OrderedSet(), OrderedSet())
+        for entry in self.rules:
             if all(x.found() for x in entry.dependencies) and \
                all(enabled_fn(key) for key in entry.keys):
                 into.sources.update(entry.sources)
@@ -127,7 +123,7 @@
 
     @noKwargs
     @noPosargs
-    def all_sources_method(self, args, kwargs):
+    def all_sources_method(self, state, args, kwargs):
         self.frozen = True
         files = self.collect(lambda x: True, True)
         return list(files.sources)
@@ -135,13 +131,13 @@
     @noKwargs
     @noPosargs
     @FeatureNew('source_set.all_dependencies() method', '0.52.0')
-    def all_dependencies_method(self, args, kwargs):
+    def all_dependencies_method(self, state, args, kwargs):
         self.frozen = True
         files = self.collect(lambda x: True, True)
         return list(files.dependencies)
 
     @permittedKwargs(['strict'])
-    def apply_method(self, args, kwargs):
+    def apply_method(self, state, args, kwargs):
         if len(args) != 1:
             raise InterpreterException('Apply takes exactly one argument')
         config_data = args[0]
@@ -150,7 +146,7 @@
         if isinstance(config_data, dict):
             def _get_from_config_data(key):
                 if strict and key not in config_data:
-                    raise InterpreterException('Entry %s not in configuration dictionary.' % key)
+                    raise InterpreterException(f'Entry {key} not in configuration dictionary.')
                 return config_data.get(key, False)
         else:
             config_cache = dict()
@@ -163,13 +159,13 @@
                 return config_cache[key]
 
         files = self.collect(_get_from_config_data, False)
-        res = SourceFilesHolder(files)
+        res = SourceFilesObject(files)
         return res
 
-class SourceFilesHolder(InterpreterObject, ObjectHolder):
+class SourceFilesObject(ModuleObject):
     def __init__(self, files):
-        InterpreterObject.__init__(self)
-        ObjectHolder.__init__(self, files)
+        super().__init__()
+        self.files = files
         self.methods.update({
             'sources': self.sources_method,
             'dependencies': self.dependencies_method,
@@ -177,24 +173,26 @@
 
     @noPosargs
     @noKwargs
-    def sources_method(self, args, kwargs):
-        return list(self.held_object.sources)
+    def sources_method(self, state, args, kwargs):
+        return list(self.files.sources)
 
     @noPosargs
     @noKwargs
-    def dependencies_method(self, args, kwargs):
-        return list(self.held_object.dependencies)
+    def dependencies_method(self, state, args, kwargs):
+        return list(self.files.dependencies)
 
 class SourceSetModule(ExtensionModule):
     @FeatureNew('SourceSet module', '0.51.0')
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        self.snippets.add('source_set')
+        self.methods.update({
+            'source_set': self.source_set,
+        })
 
     @noKwargs
     @noPosargs
-    def source_set(self, interpreter, state, args, kwargs):
-        return SourceSetHolder(interpreter)
+    def source_set(self, state, args, kwargs):
+        return SourceSet(self.interpreter)
 
 def initialize(*args, **kwargs):
     return SourceSetModule(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/unstable_cuda.py meson-0.61.2/mesonbuild/modules/unstable_cuda.py
--- meson-0.53.2/mesonbuild/modules/unstable_cuda.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/unstable_cuda.py	2021-11-02 19:58:07.000000000 +0000
@@ -12,38 +12,59 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import typing as T
 import re
 
 from ..mesonlib import version_compare
-from ..interpreter import CompilerHolder
-from ..compilers import CudaCompiler
+from ..compilers import CudaCompiler, Compiler
 
-from . import ExtensionModule, ModuleReturnValue
+from . import NewExtensionModule
 
 from ..interpreterbase import (
     flatten, permittedKwargs, noKwargs,
     InvalidArguments, FeatureNew
 )
 
-class CudaModule(ExtensionModule):
+if T.TYPE_CHECKING:
+    from . import ModuleState
+
+class CudaModule(NewExtensionModule):
 
     @FeatureNew('CUDA module', '0.50.0')
     def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
+        super().__init__()
+        self.methods.update({
+            "min_driver_version": self.min_driver_version,
+            "nvcc_arch_flags":    self.nvcc_arch_flags,
+            "nvcc_arch_readable": self.nvcc_arch_readable,
+        })
 
     @noKwargs
-    def min_driver_version(self, state, args, kwargs):
+    def min_driver_version(self, state: 'ModuleState',
+                                 args: T.Tuple[str],
+                                 kwargs: T.Dict[str, T.Any]) -> str:
         argerror = InvalidArguments('min_driver_version must have exactly one positional argument: ' +
-                                    'an NVCC compiler object, or its version string.')
+                                    'a CUDA Toolkit version string. Beware that, since CUDA 11.0, ' +
+                                    'the CUDA Toolkit\'s components (including NVCC) are versioned ' +
+                                    'independently from each other (and the CUDA Toolkit as a whole).')
 
-        if len(args) != 1:
+        if len(args) != 1 or not isinstance(args[0], str):
             raise argerror
-        else:
-            cuda_version = self._version_from_compiler(args[0])
-            if cuda_version == 'unknown':
-                raise argerror
 
+        cuda_version = args[0]
         driver_version_table = [
+            {'cuda_version': '>=11.5.0',   'windows': '496.04', 'linux': '495.29.05'},
+            {'cuda_version': '>=11.4.1',   'windows': '471.41', 'linux': '470.57.02'},
+            {'cuda_version': '>=11.4.0',   'windows': '471.11', 'linux': '470.42.01'},
+            {'cuda_version': '>=11.3.0',   'windows': '465.89', 'linux': '465.19.01'},
+            {'cuda_version': '>=11.2.2',   'windows': '461.33', 'linux': '460.32.03'},
+            {'cuda_version': '>=11.2.1',   'windows': '461.09', 'linux': '460.32.03'},
+            {'cuda_version': '>=11.2.0',   'windows': '460.82', 'linux': '460.27.03'},
+            {'cuda_version': '>=11.1.1',   'windows': '456.81', 'linux': '455.32'},
+            {'cuda_version': '>=11.1.0',   'windows': '456.38', 'linux': '455.23'},
+            {'cuda_version': '>=11.0.3',   'windows': '451.82', 'linux': '450.51.06'},
+            {'cuda_version': '>=11.0.2',   'windows': '451.48', 'linux': '450.51.05'},
+            {'cuda_version': '>=11.0.1',   'windows': '451.22', 'linux': '450.36.06'},
             {'cuda_version': '>=10.2.89',  'windows': '441.22', 'linux': '440.33'},
             {'cuda_version': '>=10.1.105', 'windows': '418.96', 'linux': '418.39'},
             {'cuda_version': '>=10.0.130', 'windows': '411.31', 'linux': '410.48'},
@@ -63,19 +84,23 @@
                 driver_version = d.get(state.host_machine.system, d['linux'])
                 break
 
-        return ModuleReturnValue(driver_version, [driver_version])
+        return driver_version
 
     @permittedKwargs(['detected'])
-    def nvcc_arch_flags(self, state, args, kwargs):
-        nvcc_arch_args = self._validate_nvcc_arch_args(state, args, kwargs)
+    def nvcc_arch_flags(self, state: 'ModuleState',
+                              args: T.Tuple[T.Union[Compiler, CudaCompiler, str]],
+                              kwargs: T.Dict[str, T.Any]) -> T.List[str]:
+        nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs)
         ret = self._nvcc_arch_flags(*nvcc_arch_args)[0]
-        return ModuleReturnValue(ret, [ret])
+        return ret
 
     @permittedKwargs(['detected'])
-    def nvcc_arch_readable(self, state, args, kwargs):
-        nvcc_arch_args = self._validate_nvcc_arch_args(state, args, kwargs)
+    def nvcc_arch_readable(self, state: 'ModuleState',
+                                 args: T.Tuple[T.Union[Compiler, CudaCompiler, str]],
+                                 kwargs: T.Dict[str, T.Any]) -> T.List[str]:
+        nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs)
         ret = self._nvcc_arch_flags(*nvcc_arch_args)[1]
-        return ModuleReturnValue(ret, [ret])
+        return ret
 
     @staticmethod
     def _break_arch_string(s):
@@ -85,23 +110,19 @@
 
     @staticmethod
     def _detected_cc_from_compiler(c):
-        if isinstance(c, CompilerHolder):
-            c = c.compiler
         if isinstance(c, CudaCompiler):
             return c.detected_cc
         return ''
 
     @staticmethod
     def _version_from_compiler(c):
-        if isinstance(c, CompilerHolder):
-            c = c.compiler
         if isinstance(c, CudaCompiler):
             return c.version
         if isinstance(c, str):
             return c
         return 'unknown'
 
-    def _validate_nvcc_arch_args(self, state, args, kwargs):
+    def _validate_nvcc_arch_args(self, args, kwargs):
         argerror = InvalidArguments('The first argument must be an NVCC compiler object, or its version string!')
 
         if len(args) < 1:
@@ -128,19 +149,45 @@
 
         return cuda_version, arch_list, detected
 
+    def _filter_cuda_arch_list(self, cuda_arch_list, lo=None, hi=None, saturate=None):
+        """
+        Filter CUDA arch list (no codenames) for >= low and < hi architecture
+        bounds, and deduplicate.
+        If saturate is provided, architectures >= hi are replaced with saturate.
+        """
+
+        filtered_cuda_arch_list = []
+        for arch in cuda_arch_list:
+            if arch:
+                if lo and version_compare(arch, '<' + lo):
+                    continue
+                if hi and version_compare(arch, '>=' + hi):
+                    if not saturate:
+                        continue
+                    arch = saturate
+                if arch not in filtered_cuda_arch_list:
+                    filtered_cuda_arch_list.append(arch)
+        return filtered_cuda_arch_list
+
     def _nvcc_arch_flags(self, cuda_version, cuda_arch_list='Auto', detected=''):
         """
-        Using the CUDA Toolkit version (the NVCC version) and the target
-        architectures, compute the NVCC architecture flags.
+        Using the CUDA Toolkit version and the target architectures, compute
+        the NVCC architecture flags.
         """
 
-        cuda_known_gpu_architectures  = ['Fermi', 'Kepler', 'Maxwell']  # noqa: E221
-        cuda_common_gpu_architectures = ['3.0', '3.5', '5.0']           # noqa: E221
-        cuda_limit_gpu_architecture   = None                            # noqa: E221
-        cuda_all_gpu_architectures    = ['3.0', '3.2', '3.5', '5.0']    # noqa: E221
+        # Replicates much of the logic of
+        #     https://github.com/Kitware/CMake/blob/master/Modules/FindCUDA/select_compute_arch.cmake
+        # except that a bug with cuda_arch_list="All" is worked around by
+        # tracking both lower and upper limits on GPU architectures.
+
+        cuda_known_gpu_architectures   = ['Fermi', 'Kepler', 'Maxwell']  # noqa: E221
+        cuda_common_gpu_architectures  = ['3.0', '3.5', '5.0']           # noqa: E221
+        cuda_hi_limit_gpu_architecture = None                            # noqa: E221
+        cuda_lo_limit_gpu_architecture = '2.0'                           # noqa: E221
+        cuda_all_gpu_architectures     = ['3.0', '3.2', '3.5', '5.0']    # noqa: E221
 
         if version_compare(cuda_version, '<7.0'):
-            cuda_limit_gpu_architecture = '5.2'
+            cuda_hi_limit_gpu_architecture = '5.2'
 
         if version_compare(cuda_version, '>=7.0'):
             cuda_known_gpu_architectures  += ['Kepler+Tegra', 'Kepler+Tesla', 'Maxwell+Tegra']  # noqa: E221
@@ -148,7 +195,7 @@
 
             if version_compare(cuda_version, '<8.0'):
                 cuda_common_gpu_architectures += ['5.2+PTX']  # noqa: E221
-                cuda_limit_gpu_architecture    = '6.0'        # noqa: E221
+                cuda_hi_limit_gpu_architecture = '6.0'        # noqa: E221
 
         if version_compare(cuda_version, '>=8.0'):
             cuda_known_gpu_architectures  += ['Pascal', 'Pascal+Tegra']  # noqa: E221
@@ -157,23 +204,45 @@
 
             if version_compare(cuda_version, '<9.0'):
                 cuda_common_gpu_architectures += ['6.1+PTX']  # noqa: E221
-                cuda_limit_gpu_architecture    = '7.0'        # noqa: E221
+                cuda_hi_limit_gpu_architecture = '7.0'        # noqa: E221
 
         if version_compare(cuda_version, '>=9.0'):
-            cuda_known_gpu_architectures  += ['Volta', 'Xavier']                   # noqa: E221
-            cuda_common_gpu_architectures += ['7.0', '7.0+PTX']                    # noqa: E221
-            cuda_all_gpu_architectures    += ['7.0', '7.0+PTX', '7.2', '7.2+PTX']  # noqa: E221
+            cuda_known_gpu_architectures  += ['Volta', 'Xavier'] # noqa: E221
+            cuda_common_gpu_architectures += ['7.0']             # noqa: E221
+            cuda_all_gpu_architectures    += ['7.0', '7.2']      # noqa: E221
+            # https://docs.nvidia.com/cuda/archive/9.0/cuda-toolkit-release-notes/index.html#unsupported-features
+            cuda_lo_limit_gpu_architecture = '3.0'               # noqa: E221
 
             if version_compare(cuda_version, '<10.0'):
-                cuda_limit_gpu_architecture = '7.5'
+                cuda_common_gpu_architectures += ['7.2+PTX']  # noqa: E221
+                cuda_hi_limit_gpu_architecture = '8.0'        # noqa: E221
 
         if version_compare(cuda_version, '>=10.0'):
-            cuda_known_gpu_architectures  += ['Turing']          # noqa: E221
-            cuda_common_gpu_architectures += ['7.5', '7.5+PTX']  # noqa: E221
-            cuda_all_gpu_architectures    += ['7.5', '7.5+PTX']  # noqa: E221
+            cuda_known_gpu_architectures  += ['Turing'] # noqa: E221
+            cuda_common_gpu_architectures += ['7.5']    # noqa: E221
+            cuda_all_gpu_architectures    += ['7.5']    # noqa: E221
 
             if version_compare(cuda_version, '<11.0'):
-                cuda_limit_gpu_architecture = '8.0'
+                cuda_common_gpu_architectures += ['7.5+PTX']  # noqa: E221
+                cuda_hi_limit_gpu_architecture = '8.0'        # noqa: E221
+
+        if version_compare(cuda_version, '>=11.0'):
+            cuda_known_gpu_architectures  += ['Ampere'] # noqa: E221
+            cuda_common_gpu_architectures += ['8.0']    # noqa: E221
+            cuda_all_gpu_architectures    += ['8.0']    # noqa: E221
+            # https://docs.nvidia.com/cuda/archive/11.0/cuda-toolkit-release-notes/index.html#deprecated-features
+            cuda_lo_limit_gpu_architecture = '3.5'      # noqa: E221
+
+            if version_compare(cuda_version, '<11.1'):
+                cuda_common_gpu_architectures += ['8.0+PTX']  # noqa: E221
+                cuda_hi_limit_gpu_architecture = '8.6'        # noqa: E221
+
+        if version_compare(cuda_version, '>=11.1'):
+            cuda_common_gpu_architectures += ['8.6', '8.6+PTX']  # noqa: E221
+            cuda_all_gpu_architectures    += ['8.6']             # noqa: E221
+
+            if version_compare(cuda_version, '<12.0'):
+                cuda_hi_limit_gpu_architecture = '9.0'        # noqa: E221
 
         if not cuda_arch_list:
             cuda_arch_list = 'Auto'
@@ -188,22 +257,16 @@
                     cuda_arch_list = detected
                 else:
                     cuda_arch_list = self._break_arch_string(detected)
-
-                if cuda_limit_gpu_architecture:
-                    filtered_cuda_arch_list = []
-                    for arch in cuda_arch_list:
-                        if arch:
-                            if version_compare(arch, '>=' + cuda_limit_gpu_architecture):
-                                arch = cuda_common_gpu_architectures[-1]
-                            if arch not in filtered_cuda_arch_list:
-                                filtered_cuda_arch_list.append(arch)
-                    cuda_arch_list = filtered_cuda_arch_list
+                cuda_arch_list = self._filter_cuda_arch_list(cuda_arch_list,
+                                                             cuda_lo_limit_gpu_architecture,
+                                                             cuda_hi_limit_gpu_architecture,
+                                                             cuda_common_gpu_architectures[-1])
             else:
                 cuda_arch_list = cuda_common_gpu_architectures
         elif isinstance(cuda_arch_list, str):
             cuda_arch_list = self._break_arch_string(cuda_arch_list)
 
-        cuda_arch_list = sorted([x for x in set(cuda_arch_list) if x])
+        cuda_arch_list = sorted(x for x in set(cuda_arch_list) if x)
 
         cuda_arch_bin = []
         cuda_arch_ptx = []
@@ -229,11 +292,11 @@
                     'Volta':         (['7.0'],             ['7.0']),
                     'Xavier':        (['7.2'],             []),
                     'Turing':        (['7.5'],             ['7.5']),
+                    'Ampere':        (['8.0'],             ['8.0']),
                 }.get(arch_name, (None, None))
 
             if arch_bin is None:
-                raise InvalidArguments('Unknown CUDA Architecture Name {}!'
-                                       .format(arch_name))
+                raise InvalidArguments(f'Unknown CUDA Architecture Name {arch_name}!')
 
             cuda_arch_bin += arch_bin
 
@@ -242,10 +305,6 @@
                     arch_ptx = arch_bin
                 cuda_arch_ptx += arch_ptx
 
-        cuda_arch_bin = re.sub('\\.', '', ' '.join(cuda_arch_bin))
-        cuda_arch_ptx = re.sub('\\.', '', ' '.join(cuda_arch_ptx))
-        cuda_arch_bin = re.findall('[0-9()]+', cuda_arch_bin)
-        cuda_arch_ptx = re.findall('[0-9]+',   cuda_arch_ptx)
         cuda_arch_bin = sorted(list(set(cuda_arch_bin)))
         cuda_arch_ptx = sorted(list(set(cuda_arch_ptx)))
 
@@ -253,15 +312,37 @@
         nvcc_archs_readable = []
 
         for arch in cuda_arch_bin:
-            m = re.match('([0-9]+)\\(([0-9]+)\\)', arch)
-            if m:
-                nvcc_flags += ['-gencode', 'arch=compute_' + m[2] + ',code=sm_' + m[1]]
-                nvcc_archs_readable += ['sm_' + m[1]]
+            arch, codev = re.fullmatch(
+                '([0-9]+\\.[0-9])(?:\\(([0-9]+\\.[0-9])\\))?', arch).groups()
+
+            if version_compare(arch, '<' + cuda_lo_limit_gpu_architecture):
+                continue
+            if version_compare(arch, '>=' + cuda_hi_limit_gpu_architecture):
+                continue
+
+            if codev:
+                arch = arch.replace('.', '')
+                codev = codev.replace('.', '')
+                nvcc_flags += ['-gencode', 'arch=compute_' + codev + ',code=sm_' + arch]
+                nvcc_archs_readable += ['sm_' + arch]
             else:
+                arch = arch.replace('.', '')
                 nvcc_flags += ['-gencode', 'arch=compute_' + arch + ',code=sm_' + arch]
                 nvcc_archs_readable += ['sm_' + arch]
 
         for arch in cuda_arch_ptx:
+            arch, codev = re.fullmatch(
+                '([0-9]+\\.[0-9])(?:\\(([0-9]+\\.[0-9])\\))?', arch).groups()
+
+            if codev:
+                arch = codev
+
+            if version_compare(arch, '<' + cuda_lo_limit_gpu_architecture):
+                continue
+            if version_compare(arch, '>=' + cuda_hi_limit_gpu_architecture):
+                continue
+
+            arch = arch.replace('.', '')
             nvcc_flags += ['-gencode', 'arch=compute_' + arch + ',code=compute_' + arch]
             nvcc_archs_readable += ['compute_' + arch]
 
diff -Nru meson-0.53.2/mesonbuild/modules/unstable_external_project.py meson-0.61.2/mesonbuild/modules/unstable_external_project.py
--- meson-0.53.2/mesonbuild/modules/unstable_external_project.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/unstable_external_project.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,297 @@
+# Copyright 2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from pathlib import Path
+import os
+import shlex
+import subprocess
+import typing as T
+
+from . import ExtensionModule, ModuleReturnValue, NewExtensionModule
+from .. import mlog, build
+from ..compilers.compilers import CFLAGS_MAPPING
+from ..envconfig import ENV_VAR_PROG_MAP
+from ..dependencies import InternalDependency, PkgConfigDependency
+from ..interpreterbase import FeatureNew
+from ..interpreter.type_checking import ENV_KW
+from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args
+from ..mesonlib import (EnvironmentException, MesonException, Popen_safe, MachineChoice,
+                        get_variable_regex, do_replacement, join_args, OptionKey)
+
+if T.TYPE_CHECKING:
+    from typing_extensions import TypedDict
+
+    from . import ModuleState
+    from ..interpreter import Interpreter
+    from ..interpreterbase import TYPE_var
+
+    class Dependency(TypedDict):
+
+        subdir: str
+
+    class AddProject(TypedDict):
+
+        configure_options: T.List[str]
+        cross_configure_options: T.List[str]
+        verbose: bool
+        env: build.EnvironmentVariables
+
+
+class ExternalProject(NewExtensionModule):
+    def __init__(self,
+                 state: 'ModuleState',
+                 configure_command: str,
+                 configure_options: T.List[str],
+                 cross_configure_options: T.List[str],
+                 env: build.EnvironmentVariables,
+                 verbose: bool):
+        super().__init__()
+        self.methods.update({'dependency': self.dependency_method,
+                             })
+
+        self.subdir = Path(state.subdir)
+        self.project_version = state.project_version
+        self.subproject = state.subproject
+        self.env = state.environment
+        self.build_machine = state.build_machine
+        self.host_machine = state.host_machine
+        self.configure_command = configure_command
+        self.configure_options = configure_options
+        self.cross_configure_options = cross_configure_options
+        self.verbose = verbose
+        self.user_env = env
+
+        self.src_dir = Path(self.env.get_source_dir(), self.subdir)
+        self.build_dir = Path(self.env.get_build_dir(), self.subdir, 'build')
+        self.install_dir = Path(self.env.get_build_dir(), self.subdir, 'dist')
+        _p = self.env.coredata.get_option(OptionKey('prefix'))
+        assert isinstance(_p, str), 'for mypy'
+        self.prefix = Path(_p)
+        _l = self.env.coredata.get_option(OptionKey('libdir'))
+        assert isinstance(_l, str), 'for mypy'
+        self.libdir = Path(_l)
+        _i = self.env.coredata.get_option(OptionKey('includedir'))
+        assert isinstance(_i, str), 'for mypy'
+        self.includedir = Path(_i)
+        self.name = self.src_dir.name
+
+        # On Windows if the prefix is "c:/foo" and DESTDIR is "c:/bar", `make`
+        # will install files into "c:/bar/c:/foo" which is an invalid path.
+        # Work around that issue by removing the drive from prefix.
+        if self.prefix.drive:
+            self.prefix = self.prefix.relative_to(self.prefix.drive)
+
+        # self.prefix is an absolute path, so we cannot append it to another path.
+        self.rel_prefix = self.prefix.relative_to(self.prefix.root)
+
+        self._configure(state)
+
+        self.targets = self._create_targets()
+
+    def _configure(self, state: 'ModuleState') -> None:
+        if self.configure_command == 'waf':
+            FeatureNew('Waf external project', '0.60.0', location=state.current_node).use(self.subproject)
+            waf = state.find_program('waf')
+            configure_cmd = waf.get_command()
+            configure_cmd += ['configure', '-o', str(self.build_dir)]
+            workdir = self.src_dir
+            self.make = waf.get_command() + ['build']
+        else:
+            # Assume it's the name of a script in source dir, like 'configure',
+            # 'autogen.sh', etc).
+            configure_path = Path(self.src_dir, self.configure_command)
+            configure_prog = state.find_program(configure_path.as_posix())
+            configure_cmd = configure_prog.get_command()
+            workdir = self.build_dir
+            self.make = state.find_program('make').get_command()
+
+        d = [('PREFIX', '--prefix=@PREFIX@', self.prefix.as_posix()),
+             ('LIBDIR', '--libdir=@PREFIX@/@LIBDIR@', self.libdir.as_posix()),
+             ('INCLUDEDIR', None, self.includedir.as_posix()),
+             ]
+        self._validate_configure_options(d, state)
+
+        configure_cmd += self._format_options(self.configure_options, d)
+
+        if self.env.is_cross_build():
+            host = '{}-{}-{}'.format(self.host_machine.cpu_family,
+                                     self.build_machine.system,
+                                     self.host_machine.system)
+            d = [('HOST', None, host)]
+            configure_cmd += self._format_options(self.cross_configure_options, d)
+
+        # Set common env variables like CFLAGS, CC, etc.
+        link_exelist: T.List[str] = []
+        link_args: T.List[str] = []
+        self.run_env = os.environ.copy()
+        for lang, compiler in self.env.coredata.compilers[MachineChoice.HOST].items():
+            if any(lang not in i for i in (ENV_VAR_PROG_MAP, CFLAGS_MAPPING)):
+                continue
+            cargs = self.env.coredata.get_external_args(MachineChoice.HOST, lang)
+            assert isinstance(cargs, list), 'for mypy'
+            self.run_env[ENV_VAR_PROG_MAP[lang]] = self._quote_and_join(compiler.get_exelist())
+            self.run_env[CFLAGS_MAPPING[lang]] = self._quote_and_join(cargs)
+            if not link_exelist:
+                link_exelist = compiler.get_linker_exelist()
+                _l = self.env.coredata.get_external_link_args(MachineChoice.HOST, lang)
+                assert isinstance(_l, list), 'for mypy'
+                link_args = _l
+        if link_exelist:
+            # FIXME: Do not pass linker because Meson uses CC as linker wrapper,
+            # but autotools often expects the real linker (e.h. GNU ld).
+            # self.run_env['LD'] = self._quote_and_join(link_exelist)
+            pass
+        self.run_env['LDFLAGS'] = self._quote_and_join(link_args)
+
+        self.run_env = self.user_env.get_env(self.run_env)
+
+        PkgConfigDependency.setup_env(self.run_env, self.env, MachineChoice.HOST,
+                                      Path(self.env.get_build_dir(), 'meson-uninstalled').as_posix())
+
+        self.build_dir.mkdir(parents=True, exist_ok=True)
+        self._run('configure', configure_cmd, workdir)
+
+    def _quote_and_join(self, array: T.List[str]) -> str:
+        return ' '.join([shlex.quote(i) for i in array])
+
+    def _validate_configure_options(self, variables: T.List[T.Tuple[str, str, str]], state: 'ModuleState') -> None:
+        # Ensure the user at least try to pass basic info to the build system,
+        # like the prefix, libdir, etc.
+        for key, default, val in variables:
+            if default is None:
+                continue
+            key_format = f'@{key}@'
+            for option in self.configure_options:
+                if key_format in option:
+                    break
+            else:
+                FeatureNew('Default configure_option', '0.57.0', location=state.current_node).use(self.subproject)
+                self.configure_options.append(default)
+
+    def _format_options(self, options: T.List[str], variables: T.List[T.Tuple[str, str, str]]) -> T.List[str]:
+        out: T.List[str] = []
+        missing = set()
+        regex = get_variable_regex('meson')
+        confdata: T.Dict[str, T.Tuple[str, T.Optional[str]]] = {k: (v, None) for k, _, v in variables}
+        for o in options:
+            arg, missing_vars = do_replacement(regex, o, 'meson', confdata)
+            missing.update(missing_vars)
+            out.append(arg)
+        if missing:
+            var_list = ", ".join(map(repr, sorted(missing)))
+            raise EnvironmentException(
+                f"Variables {var_list} in configure options are missing.")
+        return out
+
+    def _run(self, step: str, command: T.List[str], workdir: Path) -> None:
+        mlog.log(f'External project {self.name}:', mlog.bold(step))
+        m = 'Running command ' + str(command) + ' in directory ' + str(workdir) + '\n'
+        log_filename = Path(mlog.log_dir, f'{self.name}-{step}.log')
+        output = None
+        if not self.verbose:
+            output = open(log_filename, 'w', encoding='utf-8')
+            output.write(m + '\n')
+            output.flush()
+        else:
+            mlog.log(m)
+        p, *_ = Popen_safe(command, cwd=str(workdir), env=self.run_env,
+                           stderr=subprocess.STDOUT,
+                           stdout=output)
+        if p.returncode != 0:
+            m = f'{step} step returned error code {p.returncode}.'
+            if not self.verbose:
+                m += '\nSee logs: ' + str(log_filename)
+            raise MesonException(m)
+
+    def _create_targets(self) -> T.List['TYPE_var']:
+        cmd = self.env.get_build_command()
+        cmd += ['--internal', 'externalproject',
+                '--name', self.name,
+                '--srcdir', self.src_dir.as_posix(),
+                '--builddir', self.build_dir.as_posix(),
+                '--installdir', self.install_dir.as_posix(),
+                '--logdir', mlog.log_dir,
+                '--make', join_args(self.make),
+                ]
+        if self.verbose:
+            cmd.append('--verbose')
+
+        target_kwargs = {'output': f'{self.name}.stamp',
+                         'depfile': f'{self.name}.d',
+                         'command': cmd + ['@OUTPUT@', '@DEPFILE@'],
+                         'console': True,
+                         }
+        self.target = build.CustomTarget(self.name,
+                                         self.subdir.as_posix(),
+                                         self.subproject,
+                                         target_kwargs)
+
+        idir = build.InstallDir(self.subdir.as_posix(),
+                                Path('dist', self.rel_prefix).as_posix(),
+                                install_dir='.',
+                                install_mode=None,
+                                exclude=None,
+                                strip_directory=True,
+                                from_source_dir=False,
+                                subproject=self.subproject)
+
+        return [self.target, idir]
+
+    @typed_pos_args('external_project.dependency', str)
+    @typed_kwargs('external_project.dependency', KwargInfo('subdir', str, default=''))
+    def dependency_method(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Dependency') -> InternalDependency:
+        libname = args[0]
+
+        abs_includedir = Path(self.install_dir, self.rel_prefix, self.includedir)
+        if kwargs['subdir']:
+            abs_includedir = Path(abs_includedir, kwargs['subdir'])
+        abs_libdir = Path(self.install_dir, self.rel_prefix, self.libdir)
+
+        version = self.project_version
+        compile_args = [f'-I{abs_includedir}']
+        link_args = [f'-L{abs_libdir}', f'-l{libname}']
+        sources = self.target
+        dep = InternalDependency(version, [], compile_args, link_args, [],
+                                 [], [sources], [], {})
+        return dep
+
+
+class ExternalProjectModule(ExtensionModule):
+    @FeatureNew('External build system Module', '0.56.0')
+    def __init__(self, interpreter: 'Interpreter'):
+        super().__init__(interpreter)
+        self.methods.update({'add_project': self.add_project,
+                             })
+
+    @typed_pos_args('external_project_mod.add_project', str)
+    @typed_kwargs(
+        'external_project.add_project',
+        KwargInfo('configure_options', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('cross_configure_options', ContainerTypeInfo(list, str), default=['--host=@HOST@'], listify=True),
+        KwargInfo('verbose', bool, default=False),
+        ENV_KW,
+    )
+    def add_project(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'AddProject') -> ModuleReturnValue:
+        configure_command = args[0]
+        project = ExternalProject(state,
+                                  configure_command,
+                                  kwargs['configure_options'],
+                                  kwargs['cross_configure_options'],
+                                  kwargs['env'],
+                                  kwargs['verbose'])
+        return ModuleReturnValue(project, project.targets)
+
+
+def initialize(interp: 'Interpreter') -> ExternalProjectModule:
+    return ExternalProjectModule(interp)
diff -Nru meson-0.53.2/mesonbuild/modules/unstable_icestorm.py meson-0.61.2/mesonbuild/modules/unstable_icestorm.py
--- meson-0.53.2/mesonbuild/modules/unstable_icestorm.py	2019-05-02 18:59:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/unstable_icestorm.py	2021-08-18 11:22:15.000000000 +0000
@@ -23,19 +23,21 @@
     @FeatureNew('FPGA/Icestorm Module', '0.45.0')
     def __init__(self, interpreter):
         super().__init__(interpreter)
-        self.snippets.add('project')
         self.yosys_bin = None
+        self.methods.update({
+            'project': self.project,
+        })
+
+    def detect_binaries(self, state):
+        self.yosys_bin = state.find_program('yosys')
+        self.arachne_bin = state.find_program('arachne-pnr')
+        self.icepack_bin = state.find_program('icepack')
+        self.iceprog_bin = state.find_program('iceprog')
+        self.icetime_bin = state.find_program('icetime')
 
-    def detect_binaries(self, interpreter):
-        self.yosys_bin = interpreter.find_program_impl(['yosys'])
-        self.arachne_bin = interpreter.find_program_impl(['arachne-pnr'])
-        self.icepack_bin = interpreter.find_program_impl(['icepack'])
-        self.iceprog_bin = interpreter.find_program_impl(['iceprog'])
-        self.icetime_bin = interpreter.find_program_impl(['icetime'])
-
-    def project(self, interpreter, state, args, kwargs):
+    def project(self, state, args, kwargs):
         if not self.yosys_bin:
-            self.detect_binaries(interpreter)
+            self.detect_binaries(state)
         if not args:
             raise mesonlib.MesonException('Project requires at least one argument, which is the project name.')
         proj_name = args[0]
@@ -45,11 +47,11 @@
         kwarg_sources = kwargs.get('sources', [])
         if not isinstance(kwarg_sources, list):
             kwarg_sources = [kwarg_sources]
-        all_sources = interpreter.source_strings_to_files(flatten(arg_sources + kwarg_sources))
+        all_sources = self.interpreter.source_strings_to_files(flatten(arg_sources + kwarg_sources))
         if 'constraint_file' not in kwargs:
             raise mesonlib.MesonException('Constraint file not specified.')
 
-        constraint_file = interpreter.source_strings_to_files(kwargs['constraint_file'])
+        constraint_file = self.interpreter.source_strings_to_files(kwargs['constraint_file'])
         if len(constraint_file) != 1:
             raise mesonlib.MesonException('Constraint file must contain one and only one entry.')
         blif_name = proj_name + '_blif'
@@ -61,26 +63,26 @@
         time_name = proj_name + '-time'
         upload_name = proj_name + '-upload'
 
-        blif_target = interpreter.func_custom_target(None, [blif_name], {
+        blif_target = self.interpreter.func_custom_target(None, [blif_name], {
             'input': all_sources,
             'output': blif_fname,
             'command': [self.yosys_bin, '-q', '-p', 'synth_ice40 -blif @OUTPUT@', '@INPUT@']})
 
-        asc_target = interpreter.func_custom_target(None, [asc_name], {
+        asc_target = self.interpreter.func_custom_target(None, [asc_name], {
             'input': blif_target,
             'output': asc_fname,
             'command': [self.arachne_bin, '-q', '-d', '1k', '-p', constraint_file, '@INPUT@', '-o', '@OUTPUT@']})
 
-        bin_target = interpreter.func_custom_target(None, [bin_name], {
+        bin_target = self.interpreter.func_custom_target(None, [bin_name], {
             'input': asc_target,
             'output': bin_fname,
             'command': [self.icepack_bin, '@INPUT@', '@OUTPUT@'],
             'build_by_default': True})
 
-        interpreter.func_run_target(None, [upload_name], {
+        self.interpreter.func_run_target(None, [upload_name], {
             'command': [self.iceprog_bin, bin_target]})
 
-        interpreter.func_run_target(None, [time_name], {
+        self.interpreter.func_run_target(None, [time_name], {
             'command': [self.icetime_bin, bin_target]})
 
 def initialize(*args, **kwargs):
diff -Nru meson-0.53.2/mesonbuild/modules/unstable_kconfig.py meson-0.61.2/mesonbuild/modules/unstable_kconfig.py
--- meson-0.53.2/mesonbuild/modules/unstable_kconfig.py	2019-08-28 17:15:39.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/unstable_kconfig.py	1970-01-01 00:00:00.000000000 +0000
@@ -1,73 +0,0 @@
-# Copyright 2017, 2019 The Meson development team
-
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-
-#     http://www.apache.org/licenses/LICENSE-2.0
-
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from . import ExtensionModule
-
-from .. import mesonlib
-from ..mesonlib import typeslistify
-from ..interpreterbase import FeatureNew, noKwargs
-from ..interpreter import InvalidCode
-
-import os
-
-class KconfigModule(ExtensionModule):
-
-    @FeatureNew('Kconfig Module', '0.51.0')
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.snippets.add('load')
-
-    def _load_file(self, path_to_config):
-        result = dict()
-        try:
-            with open(path_to_config) as f:
-                for line in f:
-                    if '#' in line:
-                        comment_idx = line.index('#')
-                        line = line[:comment_idx]
-                    line = line.strip()
-                    try:
-                        name, val = line.split('=', 1)
-                    except ValueError:
-                        continue
-                    result[name.strip()] = val.strip()
-        except IOError as e:
-            raise mesonlib.MesonException('Failed to load {}: {}'.format(path_to_config, e))
-
-        return result
-
-    @noKwargs
-    def load(self, interpreter, state, args, kwargs):
-        sources = typeslistify(args, (str, mesonlib.File))
-        if len(sources) != 1:
-            raise InvalidCode('load takes only one file input.')
-
-        s = sources[0]
-        is_built = False
-        if isinstance(s, mesonlib.File):
-            if s.is_built:
-                FeatureNew('kconfig.load() of built files', '0.52.0').use(state.subproject)
-                is_built = True
-            s = s.absolute_path(interpreter.environment.source_dir, interpreter.environment.build_dir)
-        else:
-            s = os.path.join(interpreter.environment.source_dir, s)
-
-        if s not in interpreter.build_def_files and not is_built:
-            interpreter.build_def_files.append(s)
-
-        return self._load_file(s)
-
-
-def initialize(*args, **kwargs):
-    return KconfigModule(*args, **kwargs)
diff -Nru meson-0.53.2/mesonbuild/modules/unstable_rust.py meson-0.61.2/mesonbuild/modules/unstable_rust.py
--- meson-0.53.2/mesonbuild/modules/unstable_rust.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/unstable_rust.py	2021-11-25 22:00:46.000000000 +0000
@@ -0,0 +1,234 @@
+# Copyright © 2020 Intel Corporation
+
+# 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 typing as T
+
+from . import ExtensionModule, ModuleReturnValue
+from .. import mlog
+from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget
+from ..dependencies import Dependency, ExternalLibrary
+from ..interpreter.interpreter import TEST_KWARGS
+from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, FeatureNew, typed_kwargs, typed_pos_args, noPosargs
+from ..mesonlib import File
+
+if T.TYPE_CHECKING:
+    from . import ModuleState
+    from ..interpreter import Interpreter
+    from ..interpreter import kwargs as _kwargs
+    from ..interpreter.interpreter import SourceInputs, SourceOutputs
+    from ..programs import ExternalProgram
+
+    from typing_extensions import TypedDict
+
+    class FuncTest(_kwargs.BaseTest):
+
+        dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
+        is_parallel: bool
+
+    class FuncBindgen(TypedDict):
+
+        args: T.List[str]
+        c_args: T.List[str]
+        include_directories: T.List[IncludeDirs]
+        input: T.List[SourceInputs]
+        output: str
+
+
+class RustModule(ExtensionModule):
+
+    """A module that holds helper functions for rust."""
+
+    @FeatureNew('rust module', '0.57.0')
+    def __init__(self, interpreter: 'Interpreter') -> None:
+        super().__init__(interpreter)
+        self._bindgen_bin: T.Optional['ExternalProgram'] = None
+        self.methods.update({
+            'test': self.test,
+            'bindgen': self.bindgen,
+        })
+
+    @typed_pos_args('rust.test', str, BuildTarget)
+    @typed_kwargs(
+        'rust.test',
+        *TEST_KWARGS,
+        KwargInfo('is_parallel', bool, default=False),
+        KwargInfo(
+            'dependencies',
+            ContainerTypeInfo(list, (Dependency, ExternalLibrary)),
+            listify=True,
+            default=[]),
+    )
+    def test(self, state: 'ModuleState', args: T.Tuple[str, BuildTarget], kwargs: 'FuncTest') -> ModuleReturnValue:
+        """Generate a rust test target from a given rust target.
+
+        Rust puts it's unitests inside it's main source files, unlike most
+        languages that put them in external files. This means that normally
+        you have to define two separate targets with basically the same
+        arguments to get tests:
+
+        ```meson
+        rust_lib_sources = [...]
+        rust_lib = static_library(
+            'rust_lib',
+            rust_lib_sources,
+        )
+
+        rust_lib_test = executable(
+            'rust_lib_test',
+            rust_lib_sources,
+            rust_args : ['--test'],
+        )
+
+        test(
+            'rust_lib_test',
+            rust_lib_test,
+            protocol : 'rust',
+        )
+        ```
+
+        This is all fine, but not very DRY. This method makes it much easier
+        to define rust tests:
+
+        ```meson
+        rust = import('unstable-rust')
+
+        rust_lib = static_library(
+            'rust_lib',
+            [sources],
+        )
+
+        rust.test('rust_lib_test', rust_lib)
+        ```
+        """
+        name = args[0]
+        base_target: BuildTarget = args[1]
+        if not base_target.uses_rust():
+            raise InterpreterException('Second positional argument to rustmod.test() must be a rust based target')
+        extra_args = kwargs['args']
+
+        # Delete any arguments we don't want passed
+        if '--test' in extra_args:
+            mlog.warning('Do not add --test to rustmod.test arguments')
+            extra_args.remove('--test')
+        if '--format' in extra_args:
+            mlog.warning('Do not add --format to rustmod.test arguments')
+            i = extra_args.index('--format')
+            # Also delete the argument to --format
+            del extra_args[i + 1]
+            del extra_args[i]
+        for i, a in enumerate(extra_args):
+            if isinstance(a, str) and a.startswith('--format='):
+                del extra_args[i]
+                break
+
+        dependencies = [d for d in kwargs['dependencies']]
+
+        # We need to cast here, as currently these don't have protocol in them, but test itself does.
+        tkwargs = T.cast('_kwargs.FuncTest', kwargs.copy())
+
+        tkwargs['args'] = extra_args + ['--test', '--format', 'pretty']
+        tkwargs['protocol'] = 'rust'
+
+        new_target_kwargs = base_target.kwargs.copy()
+        # Don't mutate the shallow copied list, instead replace it with a new
+        # one
+        new_target_kwargs['rust_args'] = new_target_kwargs.get('rust_args', []) + ['--test']
+        new_target_kwargs['install'] = False
+        new_target_kwargs['dependencies'] = new_target_kwargs.get('dependencies', []) + dependencies
+
+        new_target = Executable(
+            name, base_target.subdir, state.subproject,
+            base_target.for_machine, base_target.sources,
+            base_target.objects, base_target.environment,
+            new_target_kwargs
+        )
+
+        test = self.interpreter.make_test(
+            self.interpreter.current_node, (name, new_target), tkwargs)
+
+        return ModuleReturnValue(None, [new_target, test])
+
+    @noPosargs
+    @typed_kwargs(
+        'rust.bindgen',
+        KwargInfo('c_args', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('args', ContainerTypeInfo(list, str), default=[], listify=True),
+        KwargInfo('include_directories', ContainerTypeInfo(list, IncludeDirs), default=[], listify=True),
+        KwargInfo(
+            'input',
+            ContainerTypeInfo(list, (File, GeneratedList, BuildTarget, BothLibraries, ExtractedObjects, CustomTargetIndex, CustomTarget, str), allow_empty=False),
+            default=[],
+            listify=True,
+            required=True,
+        ),
+        KwargInfo('output', str, required=True),
+    )
+    def bindgen(self, state: 'ModuleState', args: T.List, kwargs: 'FuncBindgen') -> ModuleReturnValue:
+        """Wrapper around bindgen to simplify it's use.
+
+        The main thing this simplifies is the use of `include_directory`
+        objects, instead of having to pass a plethora of `-I` arguments.
+        """
+        header, *_deps = self.interpreter.source_strings_to_files(kwargs['input'])
+
+        # Split File and Target dependencies to add pass to CustomTarget
+        depends: T.List['SourceOutputs'] = []
+        depend_files: T.List[File] = []
+        for d in _deps:
+            if isinstance(d, File):
+                depend_files.append(d)
+            else:
+                depends.append(d)
+
+        inc_strs: T.List[str] = []
+        for i in kwargs['include_directories']:
+            # bindgen always uses clang, so it's safe to hardcode -I here
+            inc_strs.extend([f'-I{x}' for x in i.to_string_list(state.environment.get_source_dir())])
+
+        if self._bindgen_bin is None:
+            self._bindgen_bin = state.find_program('bindgen')
+
+        name: str
+        if isinstance(header, File):
+            name = header.fname
+        elif isinstance(header, (BuildTarget, BothLibraries, ExtractedObjects)):
+            raise InterpreterException('bindgen source file must be a C header, not an object or build target')
+        else:
+            name = header.get_outputs()[0]
+
+        target = CustomTarget(
+            f'rustmod-bindgen-{name}'.replace('/', '_'),
+            state.subdir,
+            state.subproject,
+            {
+                'input': header,
+                'output': kwargs['output'],
+                'command': self._bindgen_bin.get_command() + [
+                    '@INPUT@', '--output',
+                    os.path.join(state.environment.build_dir, '@OUTPUT@')] +
+                    kwargs['args'] + ['--'] + kwargs['c_args'] + inc_strs +
+                    ['-MD', '-MQ', '@INPUT@', '-MF', '@DEPFILE@'],
+                'depfile': '@PLAINNAME@.d',
+                'depends': depends,
+                'depend_files': depend_files,
+            },
+            backend=state.backend,
+        )
+
+        return ModuleReturnValue([target], [target])
+
+
+def initialize(interp: 'Interpreter') -> RustModule:
+    return RustModule(interp)
diff -Nru meson-0.53.2/mesonbuild/modules/unstable_simd.py meson-0.61.2/mesonbuild/modules/unstable_simd.py
--- meson-0.53.2/mesonbuild/modules/unstable_simd.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/unstable_simd.py	2021-08-18 11:22:15.000000000 +0000
@@ -23,7 +23,6 @@
     @FeatureNew('SIMD module', '0.42.0')
     def __init__(self, interpreter):
         super().__init__(interpreter)
-        self.snippets.add('check')
         # FIXME add Altivec and AVX512.
         self.isets = ('mmx',
                       'sse',
@@ -36,8 +35,11 @@
                       'avx2',
                       'neon',
                       )
+        self.methods.update({
+            'check': self.check,
+        })
 
-    def check(self, interpreter, state, args, kwargs):
+    def check(self, state, args, kwargs):
         result = []
         if len(args) != 1:
             raise mesonlib.MesonException('Check requires one argument, a name prefix for checks.')
@@ -52,11 +54,11 @@
         for key, value in kwargs.items():
             if key not in self.isets and key != 'compiler':
                 basic_kwargs[key] = value
-        compiler = kwargs['compiler'].compiler
+        compiler = kwargs['compiler']
         if not isinstance(compiler, compilers.compilers.Compiler):
             raise mesonlib.MesonException('Compiler argument must be a compiler object.')
-        cdata = interpreter.func_configuration_data(None, [], {})
-        conf = cdata.held_object
+        cdata = self.interpreter.func_configuration_data(None, [], {})
+        conf = cdata.conf_data
         for iset in self.isets:
             if iset not in kwargs:
                 continue
@@ -79,7 +81,7 @@
             old_lang_args = mesonlib.extract_as_list(lib_kwargs, langarg_key)
             all_lang_args = old_lang_args + args
             lib_kwargs[langarg_key] = all_lang_args
-            result.append(interpreter.func_static_lib(None, [libname], lib_kwargs))
+            result.append(self.interpreter.func_static_lib(None, [libname], lib_kwargs))
         return [result, cdata]
 
 def initialize(*args, **kwargs):
diff -Nru meson-0.53.2/mesonbuild/modules/windows.py meson-0.61.2/mesonbuild/modules/windows.py
--- meson-0.53.2/mesonbuild/modules/windows.py	2019-08-28 17:15:39.000000000 +0000
+++ meson-0.61.2/mesonbuild/modules/windows.py	2021-12-26 16:24:25.000000000 +0000
@@ -15,40 +15,70 @@
 import enum
 import os
 import re
+import typing as T
+
 
-from .. import mlog
-from .. import mesonlib, build
-from ..mesonlib import MachineChoice, MesonException, extract_as_list
-from . import get_include_args
-from . import ModuleReturnValue
 from . import ExtensionModule
-from ..interpreter import CustomTargetHolder
-from ..interpreterbase import permittedKwargs, FeatureNewKwargs, flatten
-from ..dependencies import ExternalProgram
+from . import ModuleReturnValue
+from .. import mesonlib, build
+from .. import mlog
+from ..interpreter.type_checking import DEPEND_FILES_KW, DEPENDS_KW, INCLUDE_DIRECTORIES
+from ..interpreterbase.decorators import ContainerTypeInfo, FeatureNew, KwargInfo, typed_kwargs, typed_pos_args
+from ..mesonlib import MachineChoice, MesonException
+from ..programs import ExternalProgram
+
+if T.TYPE_CHECKING:
+    from . import ModuleState
+    from ..compilers import Compiler
+    from ..interpreter import Interpreter
+
+    from typing_extensions import TypedDict
+
+    class CompileResources(TypedDict):
+
+        depend_files: T.List[mesonlib.FileOrString]
+        depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]]
+        include_directories: T.List[T.Union[str, build.IncludeDirs]]
+        args: T.List[str]
+
+    class RcKwargs(TypedDict):
+        output: str
+        input: T.List[T.Union[mesonlib.FileOrString, build.CustomTargetIndex]]
+        depfile: T.Optional[str]
+        depend_files: T.List[mesonlib.FileOrString]
+        depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]]
+        command: T.List[T.Union[str, ExternalProgram]]
 
 class ResourceCompilerType(enum.Enum):
     windres = 1
     rc = 2
+    wrc = 3
 
 class WindowsModule(ExtensionModule):
+    def __init__(self, interpreter: 'Interpreter'):
+        super().__init__(interpreter)
+        self._rescomp: T.Optional[T.Tuple[ExternalProgram, ResourceCompilerType]] = None
+        self.methods.update({
+            'compile_resources': self.compile_resources,
+        })
 
-    def detect_compiler(self, compilers):
+    def detect_compiler(self, compilers: T.Dict[str, 'Compiler']) -> 'Compiler':
         for l in ('c', 'cpp'):
             if l in compilers:
                 return compilers[l]
         raise MesonException('Resource compilation requires a C or C++ compiler.')
 
-    def _find_resource_compiler(self, state):
+    def _find_resource_compiler(self, state: 'ModuleState') -> T.Tuple[ExternalProgram, ResourceCompilerType]:
         # FIXME: Does not handle `native: true` executables, see
         # See https://github.com/mesonbuild/meson/issues/1531
         # Take a parameter instead of the hardcoded definition below
         for_machine = MachineChoice.HOST
 
-        if hasattr(self, '_rescomp'):
+        if self._rescomp:
             return self._rescomp
 
         # Will try cross / native file and then env var
-        rescomp = ExternalProgram.from_bin_list(state.environment.binaries[for_machine], 'windres')
+        rescomp = ExternalProgram.from_bin_list(state.environment, for_machine, 'windres')
 
         if not rescomp or not rescomp.found():
             comp = self.detect_compiler(state.environment.coredata.compilers[for_machine])
@@ -63,6 +93,7 @@
         for (arg, match, rc_type) in [
                 ('/?', '^.*Microsoft.*Resource Compiler.*$', ResourceCompilerType.rc),
                 ('--version', '^.*GNU windres.*$', ResourceCompilerType.windres),
+                ('--version', '^.*Wine Resource Compiler.*$', ResourceCompilerType.wrc),
         ]:
             p, o, e = mesonlib.Popen_safe(rescomp.get_command() + [arg])
             m = re.search(match, o, re.MULTILINE)
@@ -75,20 +106,26 @@
 
         return self._rescomp
 
-    @FeatureNewKwargs('windows.compile_resources', '0.47.0', ['depend_files', 'depends'])
-    @permittedKwargs({'args', 'include_directories', 'depend_files', 'depends'})
-    def compile_resources(self, state, args, kwargs):
-        extra_args = mesonlib.stringlistify(flatten(kwargs.get('args', [])))
-        wrc_depend_files = extract_as_list(kwargs, 'depend_files', pop = True)
-        wrc_depends = extract_as_list(kwargs, 'depends', pop = True)
+    @typed_pos_args('windows.compile_resources', varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex), min_varargs=1)
+    @typed_kwargs(
+        'winddows.compile_resoures',
+        DEPEND_FILES_KW.evolve(since='0.47.0'),
+        DEPENDS_KW.evolve(since='0.47.0'),
+        INCLUDE_DIRECTORIES.evolve(name='include_directories'),
+        KwargInfo('args', ContainerTypeInfo(list, str), default=[], listify=True),
+    )
+    def compile_resources(self, state: 'ModuleState',
+                          args: T.Tuple[T.List[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]]],
+                          kwargs: 'CompileResources') -> ModuleReturnValue:
+        extra_args = kwargs['args'].copy()
+        wrc_depend_files = kwargs['depend_files']
+        wrc_depends = kwargs['depends']
         for d in wrc_depends:
-            if isinstance(d, CustomTargetHolder):
-                extra_args += get_include_args([d.outdir_include()])
-        inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True)
-        for incd in inc_dirs:
-            if not isinstance(incd.held_object, (str, build.IncludeDirs)):
-                raise MesonException('Resource include dirs should be include_directories().')
-        extra_args += get_include_args(inc_dirs)
+            if isinstance(d, build.CustomTarget):
+                extra_args += state.get_include_args([
+                    build.IncludeDirs('', [], False, [os.path.join('@BUILD_ROOT@', self.interpreter.backend.get_target_dir(d))])
+                ])
+        extra_args += state.get_include_args(kwargs['include_directories'])
 
         rescomp, rescomp_type = self._find_resource_compiler(state)
         if rescomp_type == ResourceCompilerType.rc:
@@ -97,7 +134,7 @@
             # CVTRES internally to convert this to a COFF object)
             suffix = 'res'
             res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@']
-        else:
+        elif rescomp_type == ResourceCompilerType.windres:
             # ld only supports object files, so windres is used to generate a
             # COFF object
             suffix = 'o'
@@ -107,55 +144,65 @@
                 'a MinGW bug: https://sourceware.org/bugzilla/show_bug.cgi?id=4933'
             for arg in extra_args:
                 if ' ' in arg:
-                    mlog.warning(m.format(arg))
-
-        res_targets = []
+                    mlog.warning(m.format(arg), fatal=False)
+        else:
+            suffix = 'o'
+            res_args = extra_args + ['@INPUT@', '-o', '@OUTPUT@']
 
-        def add_target(src):
-            if isinstance(src, list):
-                for subsrc in src:
-                    add_target(subsrc)
-                return
-
-            if hasattr(src, 'held_object'):
-                src = src.held_object
-
-            if isinstance(src, str):
-                name_format = 'file {!r}'
-                name = os.path.join(state.subdir, src)
-            elif isinstance(src, mesonlib.File):
-                name_format = 'file {!r}'
-                name = src.relative_name()
-            elif isinstance(src, build.CustomTarget):
-                if len(src.get_outputs()) > 1:
-                    raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.')
+        res_targets: T.List[build.CustomTarget] = []
 
-                name_format = 'target {!r}'
-                name = src.get_id()
-            else:
-                raise MesonException('Unexpected source type {!r}. windows.compile_resources accepts only strings, files, custom targets, and lists thereof.'.format(src))
+        def get_names() -> T.Iterable[T.Tuple[str, str, T.Union[str, mesonlib.File, build.CustomTargetIndex]]]:
+            for src in args[0]:
+                if isinstance(src, str):
+                    yield os.path.join(state.subdir, src), src, src
+                elif isinstance(src, mesonlib.File):
+                    yield src.relative_name(), src.fname, src
+                elif isinstance(src, build.CustomTargetIndex):
+                    FeatureNew.single_use('windows.compile_resource CustomTargetIndex in positional arguments', '0.61.0',
+                                          state.subproject, location=state.current_node)
+                    # This dance avoids a case where two indexs of the same
+                    # target are given as separate arguments.
+                    yield (f'{src.get_id()}_{src.target.get_outputs().index(src.output)}',
+                           f'windows_compile_resources_{src.get_filename()}', src)
+                else:
+                    if len(src.get_outputs()) > 1:
+                        FeatureNew.single_use('windows.compile_resource CustomTarget with multiple outputs in positional arguments',
+                                              '0.61.0', state.subproject, location=state.current_node)
+                    for i, out in enumerate(src.get_outputs()):
+                        # Chances are that src.get_filename() is already the name of that
+                        # target, add a prefix to avoid name clash.
+                        yield f'{src.get_id()}_{i}', f'windows_compile_resources_{i}_{out}', src[i]
 
+        for name, name_formatted, src in get_names():
             # Path separators are not allowed in target names
-            name = name.replace('/', '_').replace('\\', '_')
+            name = name.replace('/', '_').replace('\\', '_').replace(':', '_')
+            name_formatted = name_formatted.replace('/', '_').replace('\\', '_').replace(':', '_')
+            output = f'{name}_@BASENAME@.{suffix}'
+            command: T.List[T.Union[str, ExternalProgram]] = []
+            command.append(rescomp)
+            command.extend(res_args)
 
-            res_kwargs = {
-                'output': name + '_@BASENAME@.' + suffix,
+            res_kwargs: 'RcKwargs' = {
+                'output': output,
                 'input': [src],
-                'command': [rescomp] + res_args,
+                'depfile': None,
                 'depend_files': wrc_depend_files,
                 'depends': wrc_depends,
+                'command': [],
             }
 
             # instruct binutils windres to generate a preprocessor depfile
             if rescomp_type == ResourceCompilerType.windres:
-                res_kwargs['depfile'] = res_kwargs['output'] + '.d'
-                res_kwargs['command'] += ['--preprocessor-arg=-MD', '--preprocessor-arg=-MQ@OUTPUT@', '--preprocessor-arg=-MF@DEPFILE@']
+                res_kwargs['depfile'] = f'{output}.d'
+                command.extend(['--preprocessor-arg=-MD',
+                                '--preprocessor-arg=-MQ@OUTPUT@',
+                                '--preprocessor-arg=-MF@DEPFILE@'])
 
-            res_targets.append(build.CustomTarget('Windows resource for ' + name_format.format(name), state.subdir, state.subproject, res_kwargs))
+            res_kwargs['command'] = command
 
-        add_target(args)
+            res_targets.append(build.CustomTarget(name_formatted, state.subdir, state.subproject, res_kwargs))
 
         return ModuleReturnValue(res_targets, [res_targets])
 
-def initialize(*args, **kwargs):
-    return WindowsModule(*args, **kwargs)
+def initialize(interp: 'Interpreter') -> WindowsModule:
+    return WindowsModule(interp)
diff -Nru meson-0.53.2/mesonbuild/mparser.py meson-0.61.2/mesonbuild/mparser.py
--- meson-0.53.2/mesonbuild/mparser.py	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/mparser.py	2022-01-17 10:50:45.000000000 +0000
@@ -14,10 +14,15 @@
 
 import re
 import codecs
+import textwrap
 import types
+import typing as T
 from .mesonlib import MesonException
 from . import mlog
 
+if T.TYPE_CHECKING:
+    from .ast import AstVisitor
+
 # This is the regex for the supported escape sequences of a regular string
 # literal, like 'abc\x00'
 ESCAPE_SEQUENCE_SINGLE_RE = re.compile(r'''
@@ -30,25 +35,34 @@
     )''', re.UNICODE | re.VERBOSE)
 
 class MesonUnicodeDecodeError(MesonException):
-    def __init__(self, match):
-        super().__init__("%s" % match)
+    def __init__(self, match: str) -> None:
+        super().__init__(match)
         self.match = match
 
-def decode_match(match):
+def decode_match(match: T.Match[str]) -> str:
     try:
-        return codecs.decode(match.group(0), 'unicode_escape')
+        return codecs.decode(match.group(0).encode(), 'unicode_escape')
     except UnicodeDecodeError:
         raise MesonUnicodeDecodeError(match.group(0))
 
 class ParseException(MesonException):
-    def __init__(self, text, line, lineno, colno):
+    def __init__(self, text: str, line: str, lineno: int, colno: int) -> None:
         # Format as error message, followed by the line with the error, followed by a caret to show the error column.
-        super().__init__("%s\n%s\n%s" % (text, line, '%s^' % (' ' * colno)))
+        super().__init__("{}\n{}\n{}".format(text, line, '{}^'.format(' ' * colno)))
         self.lineno = lineno
         self.colno = colno
 
 class BlockParseException(MesonException):
-    def __init__(self, text, line, lineno, colno, start_line, start_lineno, start_colno):
+    def __init__(
+                self,
+                text: str,
+                line: str,
+                lineno: int,
+                colno: int,
+                start_line: str,
+                start_lineno: int,
+                start_colno: int,
+            ) -> None:
         # This can be formatted in two ways - one if the block start and end are on the same line, and a different way if they are on different lines.
 
         if lineno == start_lineno:
@@ -58,7 +72,7 @@
             # Followed by a caret to show the block start
             # Followed by underscores
             # Followed by a caret to show the block end.
-            super().__init__("%s\n%s\n%s" % (text, line, '%s^%s^' % (' ' * start_colno, '_' * (colno - start_colno - 1))))
+            super().__init__("{}\n{}\n{}".format(text, line, '{}^{}^'.format(' ' * start_colno, '_' * (colno - start_colno - 1))))
         else:
             # If block start and end are on different lines, it is formatted as:
             # Error message
@@ -71,23 +85,27 @@
         self.lineno = lineno
         self.colno = colno
 
-class Token:
-    def __init__(self, tid, subdir, line_start, lineno, colno, bytespan, value):
-        self.tid = tid
-        self.subdir = subdir
-        self.line_start = line_start
-        self.lineno = lineno
-        self.colno = colno
-        self.bytespan = bytespan
-        self.value = value
+TV_TokenTypes = T.TypeVar('TV_TokenTypes', int, str, bool)
+
+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
 
-    def __eq__(self, other):
+    def __eq__(self, other: object) -> bool:
         if isinstance(other, str):
             return self.tid == other
-        return self.tid == other.tid
+        elif isinstance(other, Token):
+            return self.tid == other.tid
+        return NotImplemented
 
 class Lexer:
-    def __init__(self, code):
+    def __init__(self, code: str):
         self.code = code
         self.keywords = {'true', 'false', 'if', 'else', 'elif',
                          'endif', 'and', 'or', 'not', 'foreach', 'endforeach',
@@ -96,6 +114,7 @@
         self.token_specification = [
             # Need to be sorted longest to shortest.
             ('ignore', re.compile(r'[ \t]')),
+            ('fstring', re.compile(r"f'([^'\\]|(\\.))*'")),
             ('id', re.compile('[_a-zA-Z][_0-9a-zA-Z]*')),
             ('number', re.compile(r'0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-fA-F]+|0|[1-9]\d*')),
             ('eol_cont', re.compile(r'\\\n')),
@@ -129,10 +148,10 @@
             ('questionmark', re.compile(r'\?')),
         ]
 
-    def getline(self, line_start):
+    def getline(self, line_start: int) -> str:
         return self.code[line_start:self.code.find('\n', line_start)]
 
-    def lex(self, subdir):
+    def lex(self, filename: str) -> T.Generator[Token, None, None]:
         line_start = 0
         lineno = 1
         loc = 0
@@ -142,7 +161,7 @@
         col = 0
         while loc < len(self.code):
             matched = False
-            value = None
+            value = None  # type: T.Union[str, bool, int]
             for (tid, reg) in self.token_specification:
                 mo = reg.match(self.code, loc)
                 if mo:
@@ -171,16 +190,22 @@
                         curl_count -= 1
                     elif tid == 'dblquote':
                         raise ParseException('Double quotes are not supported. Use single quotes.', self.getline(line_start), lineno, col)
-                    elif tid == 'string':
+                    elif tid in {'string', 'fstring'}:
                         # Handle here and not on the regexp to give a better error message.
                         if match_text.find("\n") != -1:
-                            mlog.warning("""Newline character in a string detected, use ''' (three single quotes) for multiline strings instead.
-This will become a hard error in a future Meson release.""", self.getline(line_start), lineno, col)
-                        value = match_text[1:-1]
+                            mlog.warning(textwrap.dedent("""\
+                                    Newline character in a string detected, use ''' (three single quotes) for multiline strings instead.
+                                    This will become a hard error in a future Meson release.\
+                                """),
+                                self.getline(line_start),
+                                str(lineno),
+                                str(col)
+                            )
+                        value = match_text[2 if tid == 'fstring' else 1:-1]
                         try:
                             value = ESCAPE_SEQUENCE_SINGLE_RE.sub(decode_match, value)
                         except MesonUnicodeDecodeError as err:
-                            raise MesonException("Failed to parse escape sequence: '{}' in string:\n  {}".format(err.match, match_text))
+                            raise MesonException(f"Failed to parse escape sequence: '{err.match}' in string:\n  {match_text}")
                     elif tid == 'multiline_string':
                         tid = 'string'
                         value = match_text[3:-3]
@@ -204,260 +229,237 @@
                             tid = match_text
                         else:
                             if match_text in self.future_keywords:
-                                mlog.warning("Identifier '{}' will become a reserved keyword in a future release. Please rename it.".format(match_text),
-                                             location=types.SimpleNamespace(subdir=subdir, lineno=lineno))
+                                mlog.warning(f"Identifier '{match_text}' will become a reserved keyword in a future release. Please rename it.",
+                                             location=types.SimpleNamespace(filename=filename, lineno=lineno))
                             value = match_text
-                    yield Token(tid, subdir, curline_start, curline, col, bytespan, value)
+                    yield Token(tid, filename, curline_start, curline, col, bytespan, value)
                     break
             if not matched:
                 raise ParseException('lexer', self.getline(line_start), lineno, col)
 
 class BaseNode:
-    def accept(self, visitor):
+    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
+
+        # Attributes for the visitors
+        self.level = 0            # type: int
+        self.ast_id = ''          # type: str
+        self.condition_level = 0  # type: int
+
+    def accept(self, visitor: 'AstVisitor') -> None:
         fname = 'visit_{}'.format(type(self).__name__)
         if hasattr(visitor, fname):
             func = getattr(visitor, fname)
             if callable(func):
                 func(self)
 
-class ElementaryNode(BaseNode):
-    def __init__(self, token):
-        self.lineno = token.lineno
-        self.subdir = token.subdir
-        self.colno = token.colno
-        self.value = token.value
-        self.bytespan = token.bytespan
+class ElementaryNode(T.Generic[TV_TokenTypes], BaseNode):
+    def __init__(self, token: Token[TV_TokenTypes]):
+        super().__init__(token.lineno, token.colno, token.filename)
+        self.value = token.value        # type: TV_TokenTypes
+        self.bytespan = token.bytespan  # type: T.Tuple[int, int]
 
-class BooleanNode(ElementaryNode):
-    def __init__(self, token, value):
+class BooleanNode(ElementaryNode[bool]):
+    def __init__(self, token: Token[bool]):
         super().__init__(token)
-        self.value = value
-        assert(isinstance(self.value, bool))
+        assert isinstance(self.value, bool)
 
-class IdNode(ElementaryNode):
-    def __init__(self, token):
+class IdNode(ElementaryNode[str]):
+    def __init__(self, token: Token[str]):
         super().__init__(token)
-        assert(isinstance(self.value, str))
+        assert isinstance(self.value, str)
 
-    def __str__(self):
+    def __str__(self) -> str:
         return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno)
 
-class NumberNode(ElementaryNode):
-    def __init__(self, token):
+class NumberNode(ElementaryNode[int]):
+    def __init__(self, token: Token[int]):
         super().__init__(token)
-        assert(isinstance(self.value, int))
+        assert isinstance(self.value, int)
 
-class StringNode(ElementaryNode):
-    def __init__(self, token):
+class StringNode(ElementaryNode[str]):
+    def __init__(self, token: Token[str]):
         super().__init__(token)
-        assert(isinstance(self.value, str))
+        assert isinstance(self.value, str)
 
-    def __str__(self):
+    def __str__(self) -> str:
         return "String node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno)
 
+class FormatStringNode(ElementaryNode[str]):
+    def __init__(self, token: Token[str]):
+        super().__init__(token)
+        assert isinstance(self.value, str)
+
+    def __str__(self) -> str:
+        return "Format string node: '{self.value}' ({self.lineno}, {self.colno})."
+
 class ContinueNode(ElementaryNode):
     pass
 
 class BreakNode(ElementaryNode):
     pass
 
+class ArgumentNode(BaseNode):
+    def __init__(self, token: Token[TV_TokenTypes]):
+        super().__init__(token.lineno, token.colno, token.filename)
+        self.arguments = []  # type: T.List[BaseNode]
+        self.commas = []     # type: T.List[Token[TV_TokenTypes]]
+        self.kwargs = {}     # type: T.Dict[BaseNode, BaseNode]
+        self.order_error = False
+
+    def prepend(self, statement: BaseNode) -> None:
+        if self.num_kwargs() > 0:
+            self.order_error = True
+        if not isinstance(statement, EmptyNode):
+            self.arguments = [statement] + self.arguments
+
+    def append(self, statement: BaseNode) -> None:
+        if self.num_kwargs() > 0:
+            self.order_error = True
+        if not isinstance(statement, EmptyNode):
+            self.arguments += [statement]
+
+    def set_kwarg(self, name: IdNode, value: BaseNode) -> None:
+        if any((isinstance(x, IdNode) and name.value == x.value) for x in self.kwargs):
+            mlog.warning(f'Keyword argument "{name.value}" defined multiple times.', location=self)
+            mlog.warning('This will be an error in future Meson releases.')
+        self.kwargs[name] = value
+
+    def set_kwarg_no_check(self, name: BaseNode, value: BaseNode) -> None:
+        self.kwargs[name] = value
+
+    def num_args(self) -> int:
+        return len(self.arguments)
+
+    def num_kwargs(self) -> int:
+        return len(self.kwargs)
+
+    def incorrect_order(self) -> bool:
+        return self.order_error
+
+    def __len__(self) -> int:
+        return self.num_args() # Fixme
+
 class ArrayNode(BaseNode):
-    def __init__(self, args, lineno, colno, end_lineno, end_colno):
-        self.subdir = args.subdir
-        self.lineno = lineno
-        self.colno = colno
-        self.end_lineno = end_lineno
-        self.end_colno = end_colno
-        self.args = args
+    def __init__(self, args: ArgumentNode, lineno: int, colno: int, end_lineno: int, end_colno: int):
+        super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno)
+        self.args = args              # type: ArgumentNode
 
 class DictNode(BaseNode):
-    def __init__(self, args, lineno, colno, end_lineno, end_colno):
-        self.subdir = args.subdir
-        self.lineno = lineno
-        self.colno = colno
-        self.end_lineno = end_lineno
-        self.end_colno = end_colno
+    def __init__(self, args: ArgumentNode, lineno: int, colno: int, end_lineno: int, end_colno: int):
+        super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno)
         self.args = args
 
 class EmptyNode(BaseNode):
-    def __init__(self, lineno, colno):
-        self.subdir = ''
-        self.lineno = lineno
-        self.colno = colno
+    def __init__(self, lineno: int, colno: int, filename: str):
+        super().__init__(lineno, colno, filename)
         self.value = None
 
 class OrNode(BaseNode):
-    def __init__(self, left, right):
-        self.subdir = left.subdir
-        self.lineno = left.lineno
-        self.colno = left.colno
-        self.left = left
-        self.right = right
+    def __init__(self, left: BaseNode, right: BaseNode):
+        super().__init__(left.lineno, left.colno, left.filename)
+        self.left = left    # type: BaseNode
+        self.right = right  # type: BaseNode
 
 class AndNode(BaseNode):
-    def __init__(self, left, right):
-        self.subdir = left.subdir
-        self.lineno = left.lineno
-        self.colno = left.colno
-        self.left = left
-        self.right = right
+    def __init__(self, left: BaseNode, right: BaseNode):
+        super().__init__(left.lineno, left.colno, left.filename)
+        self.left = left    # type: BaseNode
+        self.right = right  # type: BaseNode
 
 class ComparisonNode(BaseNode):
-    def __init__(self, ctype, left, right):
-        self.lineno = left.lineno
-        self.colno = left.colno
-        self.subdir = left.subdir
-        self.left = left
-        self.right = right
-        self.ctype = ctype
+    def __init__(self, ctype: str, left: BaseNode, right: BaseNode):
+        super().__init__(left.lineno, left.colno, left.filename)
+        self.left = left    # type: BaseNode
+        self.right = right  # type: BaseNode
+        self.ctype = ctype  # type: str
 
 class ArithmeticNode(BaseNode):
-    def __init__(self, operation, left, right):
-        self.subdir = left.subdir
-        self.lineno = left.lineno
-        self.colno = left.colno
-        self.left = left
-        self.right = right
-        self.operation = operation
+    def __init__(self, operation: str, left: BaseNode, right: BaseNode):
+        super().__init__(left.lineno, left.colno, left.filename)
+        self.left = left            # type: BaseNode
+        self.right = right          # type: BaseNode
+        self.operation = operation  # type: str
 
 class NotNode(BaseNode):
-    def __init__(self, location_node, value):
-        self.subdir = location_node.subdir
-        self.lineno = location_node.lineno
-        self.colno = location_node.colno
-        self.value = value
+    def __init__(self, token: Token[TV_TokenTypes], value: BaseNode):
+        super().__init__(token.lineno, token.colno, token.filename)
+        self.value = value  # type: BaseNode
 
 class CodeBlockNode(BaseNode):
-    def __init__(self, location_node):
-        self.subdir = location_node.subdir
-        self.lineno = location_node.lineno
-        self.colno = location_node.colno
-        self.lines = []
+    def __init__(self, token: Token[TV_TokenTypes]):
+        super().__init__(token.lineno, token.colno, token.filename)
+        self.lines = []  # type: T.List[BaseNode]
 
 class IndexNode(BaseNode):
-    def __init__(self, iobject, index):
-        self.iobject = iobject
-        self.index = index
-        self.subdir = iobject.subdir
-        self.lineno = iobject.lineno
-        self.colno = iobject.colno
+    def __init__(self, iobject: BaseNode, index: BaseNode):
+        super().__init__(iobject.lineno, iobject.colno, iobject.filename)
+        self.iobject = iobject  # type: BaseNode
+        self.index = index      # type: BaseNode
 
 class MethodNode(BaseNode):
-    def __init__(self, subdir, lineno, colno, source_object, name, args):
-        self.subdir = subdir
-        self.lineno = lineno
-        self.colno = colno
-        self.source_object = source_object
-        self.name = name
-        assert(isinstance(self.name, str))
-        self.args = args
+    def __init__(self, filename: str, lineno: int, colno: int, source_object: BaseNode, name: str, args: ArgumentNode):
+        super().__init__(lineno, colno, filename)
+        self.source_object = source_object  # type: BaseNode
+        self.name = name                    # type: str
+        assert isinstance(self.name, str)
+        self.args = args                    # type: ArgumentNode
 
 class FunctionNode(BaseNode):
-    def __init__(self, subdir, lineno, colno, end_lineno, end_colno, func_name, args):
-        self.subdir = subdir
-        self.lineno = lineno
-        self.colno = colno
-        self.end_lineno = end_lineno
-        self.end_colno = end_colno
-        self.func_name = func_name
-        assert(isinstance(func_name, str))
-        self.args = args
+    def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_colno: int, func_name: str, args: ArgumentNode):
+        super().__init__(lineno, colno, filename, end_lineno=end_lineno, end_colno=end_colno)
+        self.func_name = func_name  # type: str
+        assert isinstance(func_name, str)
+        self.args = args  # type: ArgumentNode
 
 class AssignmentNode(BaseNode):
-    def __init__(self, subdir, lineno, colno, var_name, value):
-        self.subdir = subdir
-        self.lineno = lineno
-        self.colno = colno
-        self.var_name = var_name
-        assert(isinstance(var_name, str))
-        self.value = value
+    def __init__(self, filename: str, lineno: int, colno: int, var_name: str, value: BaseNode):
+        super().__init__(lineno, colno, filename)
+        self.var_name = var_name  # type: str
+        assert isinstance(var_name, str)
+        self.value = value  # type: BaseNode
 
 class PlusAssignmentNode(BaseNode):
-    def __init__(self, subdir, lineno, colno, var_name, value):
-        self.subdir = subdir
-        self.lineno = lineno
-        self.colno = colno
-        self.var_name = var_name
-        assert(isinstance(var_name, str))
-        self.value = value
+    def __init__(self, filename: str, lineno: int, colno: int, var_name: str, value: BaseNode):
+        super().__init__(lineno, colno, filename)
+        self.var_name = var_name  # type: str
+        assert isinstance(var_name, str)
+        self.value = value  # type: BaseNode
 
 class ForeachClauseNode(BaseNode):
-    def __init__(self, lineno, colno, varnames, items, block):
-        self.lineno = lineno
-        self.colno = colno
-        self.varnames = varnames
-        self.items = items
-        self.block = block
+    def __init__(self, token: Token, varnames: T.List[str], items: BaseNode, block: CodeBlockNode):
+        super().__init__(token.lineno, token.colno, token.filename)
+        self.varnames = varnames  # type: T.List[str]
+        self.items = items        # type: BaseNode
+        self.block = block        # type: CodeBlockNode
+
+class IfNode(BaseNode):
+    def __init__(self, linenode: BaseNode, condition: BaseNode, block: CodeBlockNode):
+        super().__init__(linenode.lineno, linenode.colno, linenode.filename)
+        self.condition = condition  # type: BaseNode
+        self.block = block          # type: CodeBlockNode
 
 class IfClauseNode(BaseNode):
-    def __init__(self, lineno, colno):
-        self.lineno = lineno
-        self.colno = colno
-        self.ifs = []
-        self.elseblock = EmptyNode(lineno, colno)
+    def __init__(self, linenode: BaseNode):
+        super().__init__(linenode.lineno, linenode.colno, linenode.filename)
+        self.ifs = []          # type: T.List[IfNode]
+        self.elseblock = None  # type: T.Union[EmptyNode, CodeBlockNode]
 
 class UMinusNode(BaseNode):
-    def __init__(self, current_location, value):
-        self.subdir = current_location.subdir
-        self.lineno = current_location.lineno
-        self.colno = current_location.colno
-        self.value = value
-
-class IfNode(BaseNode):
-    def __init__(self, lineno, colno, condition, block):
-        self.lineno = lineno
-        self.colno = colno
-        self.condition = condition
-        self.block = block
+    def __init__(self, current_location: Token, value: BaseNode):
+        super().__init__(current_location.lineno, current_location.colno, current_location.filename)
+        self.value = value  # type: BaseNode
 
 class TernaryNode(BaseNode):
-    def __init__(self, subdir, lineno, colno, condition, trueblock, falseblock):
-        self.subdir = subdir
-        self.lineno = lineno
-        self.colno = colno
-        self.condition = condition
-        self.trueblock = trueblock
-        self.falseblock = falseblock
-
-class ArgumentNode(BaseNode):
-    def __init__(self, token):
-        self.lineno = token.lineno
-        self.colno = token.colno
-        self.subdir = token.subdir
-        self.arguments = []
-        self.commas = []
-        self.kwargs = {}
-        self.order_error = False
-
-    def prepend(self, statement):
-        if self.num_kwargs() > 0:
-            self.order_error = True
-        if not isinstance(statement, EmptyNode):
-            self.arguments = [statement] + self.arguments
-
-    def append(self, statement):
-        if self.num_kwargs() > 0:
-            self.order_error = True
-        if not isinstance(statement, EmptyNode):
-            self.arguments += [statement]
-
-    def set_kwarg(self, name, value):
-        if name in self.kwargs:
-            mlog.warning('Keyword argument "{}" defined multiple times.'.format(name), location=self)
-            mlog.warning('This will be an error in future Meson releases.')
-        self.kwargs[name] = value
-
-    def num_args(self):
-        return len(self.arguments)
-
-    def num_kwargs(self):
-        return len(self.kwargs)
-
-    def incorrect_order(self):
-        return self.order_error
-
-    def __len__(self):
-        return self.num_args() # Fixme
+    def __init__(self, condition: BaseNode, trueblock: BaseNode, falseblock: BaseNode):
+        super().__init__(condition.lineno, condition.colno, condition.filename)
+        self.condition = condition    # type: BaseNode
+        self.trueblock = trueblock    # type: BaseNode
+        self.falseblock = falseblock  # type: BaseNode
 
 comparison_map = {'equal': '==',
                   'nequal': '!=',
@@ -485,59 +487,68 @@
 # 9 plain token
 
 class Parser:
-    def __init__(self, code, subdir):
+    def __init__(self, code: str, filename: str):
         self.lexer = Lexer(code)
-        self.stream = self.lexer.lex(subdir)
-        self.current = Token('eof', '', 0, 0, 0, (0, 0), None)
+        self.stream = self.lexer.lex(filename)
+        self.current = Token('eof', '', 0, 0, 0, (0, 0), None)  # type: Token
         self.getsym()
         self.in_ternary = False
 
-    def getsym(self):
+    def getsym(self) -> None:
         try:
             self.current = next(self.stream)
         except StopIteration:
             self.current = Token('eof', '', self.current.line_start, self.current.lineno, self.current.colno + self.current.bytespan[1] - self.current.bytespan[0], (0, 0), None)
 
-    def getline(self):
+    def getline(self) -> str:
         return self.lexer.getline(self.current.line_start)
 
-    def accept(self, s):
+    def accept(self, s: str) -> bool:
         if self.current.tid == s:
             self.getsym()
             return True
         return False
 
-    def expect(self, s):
+    def accept_any(self, tids: T.Sequence[str]) -> str:
+        tid = self.current.tid
+        if tid in tids:
+            self.getsym()
+            return tid
+        return ''
+
+    def expect(self, s: str) -> bool:
         if self.accept(s):
             return True
-        raise ParseException('Expecting %s got %s.' % (s, self.current.tid), self.getline(), self.current.lineno, self.current.colno)
+        raise ParseException(f'Expecting {s} got {self.current.tid}.', self.getline(), self.current.lineno, self.current.colno)
 
-    def block_expect(self, s, block_start):
+    def block_expect(self, s: str, block_start: Token) -> bool:
         if self.accept(s):
             return True
-        raise BlockParseException('Expecting %s got %s.' % (s, self.current.tid), self.getline(), self.current.lineno, self.current.colno, self.lexer.getline(block_start.line_start), block_start.lineno, block_start.colno)
+        raise BlockParseException(f'Expecting {s} got {self.current.tid}.', self.getline(), self.current.lineno, self.current.colno, self.lexer.getline(block_start.line_start), block_start.lineno, block_start.colno)
 
-    def parse(self):
+    def parse(self) -> CodeBlockNode:
         block = self.codeblock()
         self.expect('eof')
         return block
 
-    def statement(self):
+    def statement(self) -> BaseNode:
         return self.e1()
 
-    def e1(self):
+    def e1(self) -> BaseNode:
         left = self.e2()
         if self.accept('plusassign'):
             value = self.e1()
             if not isinstance(left, IdNode):
                 raise ParseException('Plusassignment target must be an id.', self.getline(), left.lineno, left.colno)
-            return PlusAssignmentNode(left.subdir, left.lineno, left.colno, left.value, value)
+            assert isinstance(left.value, str)
+            return PlusAssignmentNode(left.filename, left.lineno, left.colno, left.value, value)
         elif self.accept('assign'):
             value = self.e1()
             if not isinstance(left, IdNode):
                 raise ParseException('Assignment target must be an id.',
                                      self.getline(), left.lineno, left.colno)
-            return AssignmentNode(left.subdir, left.lineno, left.colno, left.value, value)
+            assert isinstance(left.value, str)
+            return AssignmentNode(left.filename, left.lineno, left.colno, left.value, value)
         elif self.accept('questionmark'):
             if self.in_ternary:
                 raise ParseException('Nested ternary operators are not allowed.',
@@ -547,10 +558,10 @@
             self.expect('colon')
             falseblock = self.e1()
             self.in_ternary = False
-            return TernaryNode(left.subdir, left.lineno, left.colno, left, trueblock, falseblock)
+            return TernaryNode(left, trueblock, falseblock)
         return left
 
-    def e2(self):
+    def e2(self) -> BaseNode:
         left = self.e3()
         while self.accept('or'):
             if isinstance(left, EmptyNode):
@@ -559,7 +570,7 @@
             left = OrNode(left, self.e3())
         return left
 
-    def e3(self):
+    def e3(self) -> BaseNode:
         left = self.e4()
         while self.accept('and'):
             if isinstance(left, EmptyNode):
@@ -568,7 +579,7 @@
             left = AndNode(left, self.e4())
         return left
 
-    def e4(self):
+    def e4(self) -> BaseNode:
         left = self.e5()
         for nodename, operator_type in comparison_map.items():
             if self.accept(nodename):
@@ -577,47 +588,46 @@
             return ComparisonNode('notin', left, self.e5())
         return left
 
-    def e5(self):
-        return self.e5add()
+    def e5(self) -> BaseNode:
+        return self.e5addsub()
 
-    def e5add(self):
-        left = self.e5sub()
-        if self.accept('plus'):
-            return ArithmeticNode('add', left, self.e5add())
-        return left
-
-    def e5sub(self):
-        left = self.e5mod()
-        if self.accept('dash'):
-            return ArithmeticNode('sub', left, self.e5sub())
-        return left
-
-    def e5mod(self):
-        left = self.e5mul()
-        if self.accept('percent'):
-            return ArithmeticNode('mod', left, self.e5mod())
-        return left
-
-    def e5mul(self):
-        left = self.e5div()
-        if self.accept('star'):
-            return ArithmeticNode('mul', left, self.e5mul())
+    def e5addsub(self) -> BaseNode:
+        op_map = {
+            'plus': 'add',
+            'dash': 'sub',
+        }
+        left = self.e5muldiv()
+        while True:
+            op = self.accept_any(tuple(op_map.keys()))
+            if op:
+                left = ArithmeticNode(op_map[op], left, self.e5muldiv())
+            else:
+                break
         return left
 
-    def e5div(self):
+    def e5muldiv(self) -> BaseNode:
+        op_map = {
+            'percent': 'mod',
+            'star': 'mul',
+            'fslash': 'div',
+        }
         left = self.e6()
-        if self.accept('fslash'):
-            return ArithmeticNode('div', left, self.e5div())
+        while True:
+            op = self.accept_any(tuple(op_map.keys()))
+            if op:
+                left = ArithmeticNode(op_map[op], left, self.e6())
+            else:
+                break
         return left
 
-    def e6(self):
+    def e6(self) -> BaseNode:
         if self.accept('not'):
             return NotNode(self.current, self.e7())
         if self.accept('dash'):
             return UMinusNode(self.current, self.e7())
         return self.e7()
 
-    def e7(self):
+    def e7(self) -> BaseNode:
         left = self.e8()
         block_start = self.current
         if self.accept('lparen'):
@@ -626,7 +636,8 @@
             if not isinstance(left, IdNode):
                 raise ParseException('Function call must be applied to plain id',
                                      self.getline(), left.lineno, left.colno)
-            left = FunctionNode(left.subdir, left.lineno, left.colno, self.current.lineno, self.current.colno, left.value, args)
+            assert isinstance(left.value, str)
+            left = FunctionNode(left.filename, left.lineno, left.colno, self.current.lineno, self.current.colno, left.value, args)
         go_again = True
         while go_again:
             go_again = False
@@ -638,7 +649,7 @@
                 left = self.index_call(left)
         return left
 
-    def e8(self):
+    def e8(self) -> BaseNode:
         block_start = self.current
         if self.accept('lparen'):
             e = self.statement()
@@ -655,27 +666,31 @@
         else:
             return self.e9()
 
-    def e9(self):
+    def e9(self) -> BaseNode:
         t = self.current
         if self.accept('true'):
-            return BooleanNode(t, True)
+            t.value = True
+            return BooleanNode(t)
         if self.accept('false'):
-            return BooleanNode(t, False)
+            t.value = False
+            return BooleanNode(t)
         if self.accept('id'):
             return IdNode(t)
         if self.accept('number'):
             return NumberNode(t)
         if self.accept('string'):
             return StringNode(t)
-        return EmptyNode(self.current.lineno, self.current.colno)
-
-    def key_values(self):
-        s = self.statement()
-        a = ArgumentNode(s)
+        if self.accept('fstring'):
+            return FormatStringNode(t)
+        return EmptyNode(self.current.lineno, self.current.colno, self.current.filename)
+
+    def key_values(self) -> ArgumentNode:
+        s = self.statement()  # type: BaseNode
+        a = ArgumentNode(self.current)
 
         while not isinstance(s, EmptyNode):
             if self.accept('colon'):
-                a.set_kwarg(s, self.statement())
+                a.set_kwarg_no_check(s, self.statement())
                 potential = self.current
                 if not self.accept('comma'):
                     return a
@@ -686,9 +701,9 @@
             s = self.statement()
         return a
 
-    def args(self):
-        s = self.statement()
-        a = ArgumentNode(s)
+    def args(self) -> ArgumentNode:
+        s = self.statement()  # type: BaseNode
+        a = ArgumentNode(self.current)
 
         while not isinstance(s, EmptyNode):
             potential = self.current
@@ -699,7 +714,7 @@
                 if not isinstance(s, IdNode):
                     raise ParseException('Dictionary key must be a plain identifier.',
                                          self.getline(), s.lineno, s.colno)
-                a.set_kwarg(s.value, self.statement())
+                a.set_kwarg(s, self.statement())
                 potential = self.current
                 if not self.accept('comma'):
                     return a
@@ -710,81 +725,85 @@
             s = self.statement()
         return a
 
-    def method_call(self, source_object):
+    def method_call(self, source_object: BaseNode) -> MethodNode:
         methodname = self.e9()
-        if not(isinstance(methodname, IdNode)):
+        if not isinstance(methodname, IdNode):
             raise ParseException('Method name must be plain id',
                                  self.getline(), self.current.lineno, self.current.colno)
+        assert isinstance(methodname.value, str)
         self.expect('lparen')
         args = self.args()
         self.expect('rparen')
-        method = MethodNode(methodname.subdir, methodname.lineno, methodname.colno, source_object, methodname.value, args)
+        method = MethodNode(methodname.filename, methodname.lineno, methodname.colno, source_object, methodname.value, args)
         if self.accept('dot'):
             return self.method_call(method)
         return method
 
-    def index_call(self, source_object):
+    def index_call(self, source_object: BaseNode) -> IndexNode:
         index_statement = self.statement()
         self.expect('rbracket')
         return IndexNode(source_object, index_statement)
 
-    def foreachblock(self):
+    def foreachblock(self) -> ForeachClauseNode:
         t = self.current
         self.expect('id')
+        assert isinstance(t.value, str)
         varname = t
-        varnames = [t]
+        varnames = [t.value]  # type: T.List[str]
 
         if self.accept('comma'):
             t = self.current
             self.expect('id')
-            varnames.append(t)
+            assert isinstance(t.value, str)
+            varnames.append(t.value)
 
         self.expect('colon')
         items = self.statement()
         block = self.codeblock()
-        return ForeachClauseNode(varname.lineno, varname.colno, varnames, items, block)
+        return ForeachClauseNode(varname, varnames, items, block)
 
-    def ifblock(self):
+    def ifblock(self) -> IfClauseNode:
         condition = self.statement()
-        clause = IfClauseNode(condition.lineno, condition.colno)
+        clause = IfClauseNode(condition)
         self.expect('eol')
         block = self.codeblock()
-        clause.ifs.append(IfNode(clause.lineno, clause.colno, condition, block))
+        clause.ifs.append(IfNode(clause, condition, block))
         self.elseifblock(clause)
         clause.elseblock = self.elseblock()
         return clause
 
-    def elseifblock(self, clause):
+    def elseifblock(self, clause: IfClauseNode) -> None:
         while self.accept('elif'):
             s = self.statement()
             self.expect('eol')
             b = self.codeblock()
-            clause.ifs.append(IfNode(s.lineno, s.colno, s, b))
+            clause.ifs.append(IfNode(s, s, b))
 
-    def elseblock(self):
+    def elseblock(self) -> T.Union[CodeBlockNode, EmptyNode]:
         if self.accept('else'):
             self.expect('eol')
             return self.codeblock()
+        return EmptyNode(self.current.lineno, self.current.colno, self.current.filename)
 
-    def line(self):
+    def line(self) -> BaseNode:
         block_start = self.current
         if self.current == 'eol':
-            return EmptyNode(self.current.lineno, self.current.colno)
+            return EmptyNode(self.current.lineno, self.current.colno, self.current.filename)
         if self.accept('if'):
-            block = self.ifblock()
+            ifblock = self.ifblock()
             self.block_expect('endif', block_start)
-            return block
+            return ifblock
         if self.accept('foreach'):
-            block = self.foreachblock()
+            forblock = self.foreachblock()
             self.block_expect('endforeach', block_start)
-            return block
+            return forblock
         if self.accept('continue'):
             return ContinueNode(self.current)
         if self.accept('break'):
             return BreakNode(self.current)
         return self.statement()
 
-    def codeblock(self):
+    def codeblock(self) -> CodeBlockNode:
         block = CodeBlockNode(self.current)
         cond = True
         while cond:
diff -Nru meson-0.53.2/mesonbuild/msetup.py meson-0.61.2/mesonbuild/msetup.py
--- meson-0.53.2/mesonbuild/msetup.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/msetup.py	2021-11-02 19:58:07.000000000 +0000
@@ -28,10 +28,19 @@
 from . import build
 from . import mlog, coredata
 from . import mintro
-from .mconf import make_lower_case
 from .mesonlib import MesonException
 
-def add_arguments(parser):
+git_ignore_file = '''# This file is autogenerated by Meson. If you change or delete it, it won't be recreated.
+*
+'''
+
+hg_ignore_file = '''# This file is autogenerated by Meson. If you change or delete it, it won't be recreated.
+syntax: glob
+**/*
+'''
+
+
+def add_arguments(parser: argparse.ArgumentParser) -> None:
     coredata.register_builtin_arguments(parser)
     parser.add_argument('--native-file',
                         default=[],
@@ -41,6 +50,10 @@
                         default=[],
                         action='append',
                         help='File describing cross compilation environment.')
+    parser.add_argument('--vsenv', action='store_true',
+                        help='Setup Visual Studio environment even when other compilers are found, ' +
+                             'abort if Visual Studio is not found. This option has no effect on other ' +
+                             'platforms than Windows. Defaults to True when using "vs" backend.')
     parser.add_argument('-v', '--version', action='version',
                         version=coredata.version)
     parser.add_argument('--profile-self', action='store_true', dest='profile',
@@ -53,13 +66,13 @@
                              'is not working.')
     parser.add_argument('--wipe', action='store_true',
                         help='Wipe build directory and reconfigure using previous command line options. ' +
-                             'Userful when build directory got corrupted, or when rebuilding with a ' +
+                             'Useful when build directory got corrupted, or when rebuilding with a ' +
                              'newer version of meson.')
     parser.add_argument('builddir', nargs='?', default=None)
     parser.add_argument('sourcedir', nargs='?', default=None)
 
 class MesonApp:
-    def __init__(self, options):
+    def __init__(self, options: argparse.Namespace) -> None:
         (self.source_dir, self.build_dir) = self.validate_dirs(options.builddir,
                                                                options.sourcedir,
                                                                options.reconfigure,
@@ -86,11 +99,12 @@
                     # will cause a crash
                     for l in os.listdir(self.build_dir):
                         l = os.path.join(self.build_dir, l)
-                        if os.path.isdir(l):
+                        if os.path.isdir(l) and not os.path.islink(l):
                             mesonlib.windows_proof_rmtree(l)
                         else:
                             mesonlib.windows_proof_rm(l)
                 finally:
+                    self.add_vcs_ignore_files(self.build_dir)
                     for b, f in restore:
                         os.makedirs(os.path.dirname(f), exist_ok=True)
                         shutil.move(b, f)
@@ -118,21 +132,33 @@
         if not os.path.exists(ndir2):
             os.makedirs(ndir2)
         if not stat.S_ISDIR(os.stat(ndir1).st_mode):
-            raise MesonException('%s is not a directory' % dir1)
+            raise MesonException(f'{dir1} is not a directory')
         if not stat.S_ISDIR(os.stat(ndir2).st_mode):
-            raise MesonException('%s is not a directory' % dir2)
-        if os.path.samefile(dir1, dir2):
-            raise MesonException('Source and build directories must not be the same. Create a pristine build directory.')
+            raise MesonException(f'{dir2} is not a directory')
+        if os.path.samefile(ndir1, ndir2):
+            # Fallback to textual compare if undefined entries found
+            has_undefined = any((s.st_ino == 0 and s.st_dev == 0) for s in (os.stat(ndir1), os.stat(ndir2)))
+            if not has_undefined or ndir1 == ndir2:
+                raise MesonException('Source and build directories must not be the same. Create a pristine build directory.')
         if self.has_build_file(ndir1):
             if self.has_build_file(ndir2):
-                raise MesonException('Both directories contain a build file %s.' % environment.build_filename)
+                raise MesonException(f'Both directories contain a build file {environment.build_filename}.')
             return ndir1, ndir2
         if self.has_build_file(ndir2):
             return ndir2, ndir1
-        raise MesonException('Neither directory contains a build file %s.' % environment.build_filename)
+        raise MesonException(f'Neither directory contains a build file {environment.build_filename}.')
+
+    def add_vcs_ignore_files(self, build_dir: str) -> None:
+        if os.listdir(build_dir):
+            return
+        with open(os.path.join(build_dir, '.gitignore'), 'w', encoding='utf-8') as ofile:
+            ofile.write(git_ignore_file)
+        with open(os.path.join(build_dir, '.hgignore'), 'w', encoding='utf-8') as ofile:
+            ofile.write(hg_ignore_file)
 
     def validate_dirs(self, dir1: str, dir2: str, reconfigure: bool, wipe: bool) -> T.Tuple[str, str]:
         (src_dir, build_dir) = self.validate_core_dirs(dir1, dir2)
+        self.add_vcs_ignore_files(build_dir)
         priv_dir = os.path.join(build_dir, 'meson-private/coredata.dat')
         if os.path.exists(priv_dir):
             if not reconfigure and not wipe:
@@ -147,10 +173,10 @@
         else:
             has_cmd_line_file = os.path.exists(coredata.get_cmd_line_file(build_dir))
             if (wipe and not has_cmd_line_file) or (not wipe and reconfigure):
-                raise SystemExit('Directory does not contain a valid build tree:\n{}'.format(build_dir))
+                raise SystemExit(f'Directory does not contain a valid build tree:\n{build_dir}')
         return src_dir, build_dir
 
-    def generate(self):
+    def generate(self) -> None:
         env = environment.Environment(self.source_dir, self.build_dir, self.options)
         mlog.initialize(env.get_log_dir(), self.options.fatal_warnings)
         if self.options.profile:
@@ -158,10 +184,15 @@
         with mesonlib.BuildDirLock(self.build_dir):
             self._generate(env)
 
-    def _generate(self, env):
+    def _generate(self, env: environment.Environment) -> None:
+        # Get all user defined options, including options that have been defined
+        # during a previous invocation or using meson configure.
+        user_defined_options = argparse.Namespace(**vars(self.options))
+        coredata.read_cmd_line_file(self.build_dir, user_defined_options)
+
         mlog.debug('Build started at', datetime.datetime.now().isoformat())
         mlog.debug('Main binary:', sys.executable)
-        mlog.debug('Build Options:', coredata.get_cmd_line_options(self.build_dir, self.options))
+        mlog.debug('Build Options:', coredata.format_cmd_line_options(user_defined_options))
         mlog.debug('Python system:', platform.system())
         mlog.log(mlog.bold('The Meson build system'))
         mlog.log('Version:', coredata.version)
@@ -173,17 +204,23 @@
             mlog.log('Build type:', mlog.bold('native build'))
         b = build.Build(env)
 
-        intr = interpreter.Interpreter(b)
+        intr = interpreter.Interpreter(b, user_defined_options=user_defined_options)
         if env.is_cross_build():
             logger_fun = mlog.log
         else:
             logger_fun = mlog.debug
-        logger_fun('Build machine cpu family:', mlog.bold(intr.builtin['build_machine'].cpu_family_method([], {})))
-        logger_fun('Build machine cpu:', mlog.bold(intr.builtin['build_machine'].cpu_method([], {})))
-        mlog.log('Host machine cpu family:', mlog.bold(intr.builtin['host_machine'].cpu_family_method([], {})))
-        mlog.log('Host machine cpu:', mlog.bold(intr.builtin['host_machine'].cpu_method([], {})))
-        logger_fun('Target machine cpu family:', mlog.bold(intr.builtin['target_machine'].cpu_family_method([], {})))
-        logger_fun('Target machine cpu:', mlog.bold(intr.builtin['target_machine'].cpu_method([], {})))
+        build_machine = intr.builtin['build_machine']
+        host_machine = intr.builtin['host_machine']
+        target_machine = intr.builtin['target_machine']
+        assert isinstance(build_machine, interpreter.MachineHolder)
+        assert isinstance(host_machine, interpreter.MachineHolder)
+        assert isinstance(target_machine, interpreter.MachineHolder)
+        logger_fun('Build machine cpu family:', mlog.bold(build_machine.cpu_family_method([], {})))
+        logger_fun('Build machine cpu:', mlog.bold(build_machine.cpu_method([], {})))
+        mlog.log('Host machine cpu family:', mlog.bold(host_machine.cpu_family_method([], {})))
+        mlog.log('Host machine cpu:', mlog.bold(host_machine.cpu_method([], {})))
+        logger_fun('Target machine cpu family:', mlog.bold(target_machine.cpu_family_method([], {})))
+        logger_fun('Target machine cpu:', mlog.bold(target_machine.cpu_method([], {})))
         try:
             if self.options.profile:
                 fname = os.path.join(self.build_dir, 'meson-private', 'profile-interpreter.log')
@@ -193,11 +230,6 @@
         except Exception as e:
             mintro.write_meson_info_file(b, [e])
             raise
-        # Print all default option values that don't match the current value
-        for def_opt_name, def_opt_value, cur_opt_value in intr.get_non_matching_default_options():
-            mlog.log('Option', mlog.bold(def_opt_name), 'is:',
-                     mlog.bold('{}'.format(make_lower_case(cur_opt_value.printable_value()))),
-                     '[default: {}]'.format(make_lower_case(def_opt_value)))
         try:
             dumpfile = os.path.join(env.get_scratch_dir(), 'build.dat')
             # We would like to write coredata as late as possible since we use the existence of
@@ -208,13 +240,18 @@
             # possible, but before build files, and if any error occurs, delete it.
             cdf = env.dump_coredata()
             if self.options.profile:
-                fname = 'profile-{}-backend.log'.format(intr.backend.name)
+                fname = f'profile-{intr.backend.name}-backend.log'
                 fname = os.path.join(self.build_dir, 'meson-private', fname)
-                profile.runctx('intr.backend.generate(intr)', globals(), locals(), filename=fname)
+                profile.runctx('intr.backend.generate()', globals(), locals(), filename=fname)
             else:
-                intr.backend.generate(intr)
+                intr.backend.generate()
+            b.devenv.append(intr.backend.get_devenv())
             build.save(b, dumpfile)
             if env.first_invocation:
+                # Use path resolved by coredata because they could have been
+                # read from a pipe and wrote into a private file.
+                self.options.cross_file = env.coredata.cross_files
+                self.options.native_file = env.coredata.config_files
                 coredata.write_cmd_line_file(self.build_dir, self.options)
             else:
                 coredata.update_cmd_line_file(self.build_dir, self.options)
@@ -229,6 +266,18 @@
 
             # Post-conf scripts must be run after writing coredata or else introspection fails.
             intr.backend.run_postconf_scripts()
+
+            # collect warnings about unsupported build configurations; must be done after full arg processing
+            # by Interpreter() init, but this is most visible at the end
+            if env.coredata.options[mesonlib.OptionKey('backend')].value == 'xcode':
+                mlog.warning('xcode backend is currently unmaintained, patches welcome')
+            if env.coredata.options[mesonlib.OptionKey('layout')].value == 'flat':
+                mlog.warning('-Dlayout=flat is unsupported and probably broken. It was a failed experiment at '
+                             'making Windows build artifacts runnable while uninstalled, due to PATH considerations, '
+                             'but was untested by CI and anyways breaks reasonable use of conflicting targets in different subdirs. '
+                             'Please consider using `meson devenv` instead. See https://github.com/mesonbuild/meson/pull/9243 '
+                             'for details.')
+
         except Exception as e:
             mintro.write_meson_info_file(b, [e])
             if 'cdf' in locals():
@@ -239,7 +288,7 @@
                     os.unlink(cdf)
             raise
 
-def run(options) -> int:
+def run(options: argparse.Namespace) -> int:
     coredata.parse_cmd_line_options(options)
     app = MesonApp(options)
     app.generate()
diff -Nru meson-0.53.2/mesonbuild/msubprojects.py meson-0.61.2/mesonbuild/msubprojects.py
--- meson-0.53.2/mesonbuild/msubprojects.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/msubprojects.py	2022-01-17 10:50:45.000000000 +0000
@@ -1,206 +1,593 @@
 import os, subprocess
 import argparse
+import asyncio
+import threading
+import copy
+import shutil
+from concurrent.futures.thread import ThreadPoolExecutor
+from pathlib import Path
+import typing as T
+import tarfile
+import zipfile
 
 from . import mlog
-from .mesonlib import git, Popen_safe
-from .wrap.wrap import API_ROOT, PackageDefinition, Resolver, WrapException
+from .mesonlib import quiet_git, GitException, Popen_safe, MesonException, windows_proof_rmtree
+from .wrap.wrap import PackageDefinition, Resolver, WrapException, ALL_TYPES
 from .wrap import wraptool
 
-def update_wrapdb_file(wrap, repo_dir, options):
-    patch_url = wrap.get('patch_url')
-    branch, revision = wraptool.parse_patch_url(patch_url)
-    new_branch, new_revision = wraptool.get_latest_version(wrap.name)
-    if new_branch == branch and new_revision == revision:
-        mlog.log('  -> Up to date.')
-        return
-    wraptool.update_wrap_file(wrap.filename, wrap.name, new_branch, new_revision)
-    msg = ['  -> New wrap file downloaded.']
-    # Meson reconfigure won't use the new wrap file as long as the source
-    # directory exists. We don't delete it ourself to avoid data loss in case
-    # user has changes in their copy.
-    if os.path.isdir(repo_dir):
-        msg += ['To use it, delete', mlog.bold(repo_dir), 'and run', mlog.bold('meson --reconfigure')]
-    mlog.log(*msg)
-
-def update_file(wrap, repo_dir, options):
-    patch_url = wrap.values.get('patch_url', '')
-    if patch_url.startswith(API_ROOT):
-        update_wrapdb_file(wrap, repo_dir, options)
-    elif not os.path.isdir(repo_dir):
-        # The subproject is not needed, or it is a tarball extracted in
-        # 'libfoo-1.0' directory and the version has been bumped and the new
-        # directory is 'libfoo-2.0'. In that case forcing a meson
-        # reconfigure will download and use the new tarball.
-        mlog.log('  -> Subproject has not been checked out. Run', mlog.bold('meson --reconfigure'), 'to fetch it if needed.')
+if T.TYPE_CHECKING:
+    from typing_extensions import Protocol
+
+    class Arguments(Protocol):
+        sourcedir: str
+        num_processes: int
+        subprojects: T.List[str]
+        types: str
+        subprojects_func: T.Callable[[], bool]
+
+    class UpdateArguments(Arguments):
+        rebase: bool
+        reset: bool
+
+    class CheckoutArguments(Arguments):
+        b: bool
+        branch_name: str
+
+    class ForeachArguments(Arguments):
+        command: str
+        args: T.List[str]
+
+    class PurgeArguments(Arguments):
+        confirm: bool
+        include_cache: bool
+
+    class PackagefilesArguments(Arguments):
+        apply: bool
+        save: bool
+
+ALL_TYPES_STRING = ', '.join(ALL_TYPES)
+
+def read_archive_files(path: Path, base_path: Path) -> T.Set[Path]:
+    if path.suffix == '.zip':
+        with zipfile.ZipFile(path, 'r') as zip_archive:
+            archive_files = set(base_path / i.filename for i in zip_archive.infolist())
     else:
-        # The subproject has not changed, or the new source and/or patch
-        # tarballs should be extracted in the same directory than previous
-        # version.
-        mlog.log('  -> Subproject has not changed, or the new source/patch needs to be extracted on the same location.\n' +
-                 '     In that case, delete', mlog.bold(repo_dir), 'and run', mlog.bold('meson --reconfigure'))
-
-def git_output(cmd, workingdir):
-    return git(cmd, workingdir, check=True, universal_newlines=True,
-               stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
-
-def git_show(repo_dir):
-    commit_message = git_output(['show', '--quiet', '--pretty=format:%h%n%d%n%s%n[%an]'], repo_dir)
-    parts = [s.strip() for s in commit_message.split('\n')]
-    mlog.log('  ->', mlog.yellow(parts[0]), mlog.red(parts[1]), parts[2], mlog.blue(parts[3]))
-
-def update_git(wrap, repo_dir, options):
-    if not os.path.isdir(repo_dir):
-        mlog.log('  -> Not used.')
-        return
-    revision = wrap.get('revision')
-    ret = git_output(['rev-parse', '--abbrev-ref', 'HEAD'], repo_dir).strip()
-    if ret == 'HEAD':
-        try:
-            # We are currently in detached mode, just checkout the new revision
-            git_output(['fetch'], repo_dir)
-            git_output(['checkout', revision], repo_dir)
-        except subprocess.CalledProcessError as e:
-            out = e.output.decode().strip()
-            mlog.log('  -> Could not checkout revision', mlog.cyan(revision))
-            mlog.log(mlog.red(out))
-            mlog.log(mlog.red(str(e)))
-            return
-    elif ret == revision:
+        with tarfile.open(path) as tar_archive: # [ignore encoding]
+            archive_files = set(base_path / i.name for i in tar_archive)
+    return archive_files
+
+class Logger:
+    def __init__(self, total_tasks: int) -> None:
+        self.lock = threading.Lock()
+        self.total_tasks = total_tasks
+        self.completed_tasks = 0
+        self.running_tasks: T.Set[str] = set()
+        self.should_erase_line = ''
+
+    def flush(self) -> None:
+        if self.should_erase_line:
+            print(self.should_erase_line, end='\r')
+            self.should_erase_line = ''
+
+    def print_progress(self) -> None:
+        line = f'Progress: {self.completed_tasks} / {self.total_tasks}'
+        max_len = shutil.get_terminal_size().columns - len(line)
+        running = ', '.join(self.running_tasks)
+        if len(running) + 3 > max_len:
+            running = running[:max_len - 6] + '...'
+        line = line + f' ({running})'
+        print(self.should_erase_line, line, sep='', end='\r')
+        self.should_erase_line = '\x1b[K'
+
+    def start(self, wrap_name: str) -> None:
+        with self.lock:
+            self.running_tasks.add(wrap_name)
+            self.print_progress()
+
+    def done(self, wrap_name: str, log_queue: T.List[T.Tuple[mlog.TV_LoggableList, T.Any]]) -> None:
+        with self.lock:
+            self.flush()
+            for args, kwargs in log_queue:
+                mlog.log(*args, **kwargs)
+            self.running_tasks.remove(wrap_name)
+            self.completed_tasks += 1
+            self.print_progress()
+
+
+class Runner:
+    def __init__(self, logger: Logger, r: Resolver, wrap: PackageDefinition, repo_dir: str, options: 'Arguments') -> 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.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))
+
+    def run(self) -> bool:
+        self.logger.start(self.wrap.name)
         try:
-            # We are in the same branch, pull latest commits
-            git_output(['-c', 'rebase.autoStash=true', 'pull', '--rebase'], repo_dir)
-        except subprocess.CalledProcessError as e:
-            out = e.output.decode().strip()
-            mlog.log('  -> Could not rebase', mlog.bold(repo_dir), 'please fix and try again.')
-            mlog.log(mlog.red(out))
-            mlog.log(mlog.red(str(e)))
+            result = self.run_method()
+        except MesonException as e:
+            self.log(mlog.red('Error:'), str(e))
+            result = False
+        self.logger.done(self.wrap.name, self.log_queue)
+        return result
+
+    def update_wrapdb_file(self) -> None:
+        try:
+            patch_url = self.wrap.get('patch_url')
+            branch, revision = wraptool.parse_patch_url(patch_url)
+        except WrapException:
             return
-    else:
-        # We are in another branch, probably user created their own branch and
-        # we should rebase it on top of wrap's branch.
-        if options.rebase:
-            try:
-                git_output(['fetch'], repo_dir)
-                git_output(['-c', 'rebase.autoStash=true', 'rebase', revision], repo_dir)
-            except subprocess.CalledProcessError as e:
-                out = e.output.decode().strip()
-                mlog.log('  -> Could not rebase', mlog.bold(repo_dir), 'please fix and try again.')
-                mlog.log(mlog.red(out))
-                mlog.log(mlog.red(str(e)))
-                return
+        new_branch, new_revision = wraptool.get_latest_version(self.wrap.name)
+        if new_branch != branch or new_revision != revision:
+            wraptool.update_wrap_file(self.wrap.filename, self.wrap.name, new_branch, new_revision)
+            self.log('  -> New wrap file downloaded.')
+
+    def update_file(self) -> bool:
+        options = T.cast('UpdateArguments', self.options)
+
+        self.update_wrapdb_file()
+        if not os.path.isdir(self.repo_dir):
+            # The subproject is not needed, or it is a tarball extracted in
+            # 'libfoo-1.0' directory and the version has been bumped and the new
+            # directory is 'libfoo-2.0'. In that case forcing a meson
+            # reconfigure will download and use the new tarball.
+            self.log('  -> Not used.')
+            return True
+        elif options.reset:
+            # Delete existing directory and redownload. It is possible that nothing
+            # changed but we have no way to know. Hopefully tarballs are still
+            # cached.
+            windows_proof_rmtree(self.repo_dir)
+            try:
+                self.wrap_resolver.resolve(self.wrap.name, 'meson')
+                self.log('  -> New version extracted')
+                return True
+            except WrapException as e:
+                self.log('  ->', mlog.red(str(e)))
+                return False
         else:
-            mlog.log('  -> Target revision is', mlog.bold(revision), 'but currently in branch is', mlog.bold(ret), '\n' +
-                     '     To rebase your branch on top of', mlog.bold(revision), 'use', mlog.bold('--rebase'), 'option.')
-            return
+            # The subproject has not changed, or the new source and/or patch
+            # tarballs should be extracted in the same directory than previous
+            # version.
+            self.log('  -> Subproject has not changed, or the new source/patch needs to be extracted on the same location.')
+            self.log('     Pass --reset option to delete directory and redownload.')
+            return False
+
+    def git_output(self, cmd: T.List[str]) -> str:
+        return quiet_git(cmd, self.repo_dir, check=True)[1]
+
+    def git_verbose(self, cmd: T.List[str]) -> None:
+        self.log(self.git_output(cmd))
+
+    def git_stash(self) -> None:
+        # That git command return 1 (failure) when there is something to stash.
+        # We don't want to stash when there is nothing to stash because that would
+        # print spurious "No local changes to save".
+        if not quiet_git(['diff', '--quiet', 'HEAD'], self.repo_dir)[0]:
+            # Don't pipe stdout here because we want the user to see their changes have
+            # been saved.
+            self.git_verbose(['stash'])
+
+    def git_show(self) -> None:
+        commit_message = self.git_output(['show', '--quiet', '--pretty=format:%h%n%d%n%s%n[%an]'])
+        parts = [s.strip() for s in commit_message.split('\n')]
+        self.log('  ->', mlog.yellow(parts[0]), mlog.red(parts[1]), parts[2], mlog.blue(parts[3]))
 
-    git_output(['submodule', 'update', '--checkout', '--recursive'], repo_dir)
-    git_show(repo_dir)
+    def git_rebase(self, revision: str) -> bool:
+        try:
+            self.git_output(['-c', 'rebase.autoStash=true', 'rebase', 'FETCH_HEAD'])
+        except GitException as e:
+            self.log('  -> Could not rebase', mlog.bold(self.repo_dir), 'onto', mlog.bold(revision))
+            self.log(mlog.red(e.output))
+            self.log(mlog.red(str(e)))
+            return False
+        return True
 
-def update_hg(wrap, repo_dir, options):
-    if not os.path.isdir(repo_dir):
-        mlog.log('  -> Not used.')
-        return
-    revno = wrap.get('revision')
-    if revno.lower() == 'tip':
-        # Failure to do pull is not a fatal error,
-        # because otherwise you can't develop without
-        # a working net connection.
-        subprocess.call(['hg', 'pull'], cwd=repo_dir)
-    else:
-        if subprocess.call(['hg', 'checkout', revno], cwd=repo_dir) != 0:
-            subprocess.check_call(['hg', 'pull'], cwd=repo_dir)
-            subprocess.check_call(['hg', 'checkout', revno], cwd=repo_dir)
-
-def update_svn(wrap, repo_dir, options):
-    if not os.path.isdir(repo_dir):
-        mlog.log('  -> Not used.')
-        return
-    revno = wrap.get('revision')
-    p, out, _ = Popen_safe(['svn', 'info', '--show-item', 'revision', repo_dir])
-    current_revno = out
-    if current_revno == revno:
-        return
-    if revno.lower() == 'head':
-        # Failure to do pull is not a fatal error,
-        # because otherwise you can't develop without
-        # a working net connection.
-        subprocess.call(['svn', 'update'], cwd=repo_dir)
-    else:
-        subprocess.check_call(['svn', 'update', '-r', revno], cwd=repo_dir)
+    def git_reset(self, revision: str) -> bool:
+        try:
+            # Stash local changes, commits can always be found back in reflog, to
+            # avoid any data lost by mistake.
+            self.git_stash()
+            self.git_output(['reset', '--hard', 'FETCH_HEAD'])
+            self.wrap_resolver.apply_patch()
+        except GitException as e:
+            self.log('  -> Could not reset', mlog.bold(self.repo_dir), 'to', mlog.bold(revision))
+            self.log(mlog.red(e.output))
+            self.log(mlog.red(str(e)))
+            return False
+        return True
+
+    def git_checkout(self, revision: str, create: bool = False) -> bool:
+        cmd = ['checkout', '--ignore-other-worktrees', revision, '--']
+        if create:
+            cmd.insert(1, '-b')
+        try:
+            # Stash local changes, commits can always be found back in reflog, to
+            # avoid any data lost by mistake.
+            self.git_stash()
+            self.git_output(cmd)
+        except GitException as e:
+            self.log('  -> Could not checkout', mlog.bold(revision), 'in', mlog.bold(self.repo_dir))
+            self.log(mlog.red(e.output))
+            self.log(mlog.red(str(e)))
+            return False
+        return True
+
+    def git_checkout_and_reset(self, revision: str) -> bool:
+        # revision could be a branch that already exists but is outdated, so we still
+        # have to reset after the checkout.
+        success = self.git_checkout(revision)
+        if success:
+            success = self.git_reset(revision)
+        return success
+
+    def git_checkout_and_rebase(self, revision: str) -> bool:
+        # revision could be a branch that already exists but is outdated, so we still
+        # have to rebase after the checkout.
+        success = self.git_checkout(revision)
+        if success:
+            success = self.git_rebase(revision)
+        return success
+
+    def update_git(self) -> bool:
+        options = T.cast('UpdateArguments', self.options)
+
+        if not os.path.isdir(self.repo_dir):
+            self.log('  -> Not used.')
+            return True
+        if not os.path.exists(os.path.join(self.repo_dir, '.git')):
+            if options.reset:
+                # Delete existing directory and redownload
+                windows_proof_rmtree(self.repo_dir)
+                try:
+                    self.wrap_resolver.resolve(self.wrap.name, 'meson')
+                    self.update_git_done()
+                    return True
+                except WrapException as e:
+                    self.log('  ->', mlog.red(str(e)))
+                    return False
+            else:
+                self.log('  -> Not a git repository.')
+                self.log('Pass --reset option to delete directory and redownload.')
+                return False
+        revision = self.wrap.values.get('revision')
+        url = self.wrap.values.get('url')
+        push_url = self.wrap.values.get('push-url')
+        if not revision or not url:
+            # It could be a detached git submodule for example.
+            self.log('  -> No revision or URL specified.')
+            return True
+        try:
+            origin_url = self.git_output(['remote', 'get-url', 'origin']).strip()
+        except GitException as e:
+            self.log('  -> Failed to determine current origin URL in', mlog.bold(self.repo_dir))
+            self.log(mlog.red(e.output))
+            self.log(mlog.red(str(e)))
+            return False
+        if options.reset:
+            try:
+                self.git_output(['remote', 'set-url', 'origin', url])
+                if push_url:
+                    self.git_output(['remote', 'set-url', '--push', 'origin', push_url])
+            except GitException as e:
+                self.log('  -> Failed to reset origin URL in', mlog.bold(self.repo_dir))
+                self.log(mlog.red(e.output))
+                self.log(mlog.red(str(e)))
+                return False
+        elif url != origin_url:
+            self.log(f'  -> URL changed from {origin_url!r} to {url!r}')
+            return False
+        try:
+            # Same as `git branch --show-current` but compatible with older git version
+            branch = self.git_output(['rev-parse', '--abbrev-ref', 'HEAD']).strip()
+            branch = branch if branch != 'HEAD' else ''
+        except GitException as e:
+            self.log('  -> Failed to determine current branch in', mlog.bold(self.repo_dir))
+            self.log(mlog.red(e.output))
+            self.log(mlog.red(str(e)))
+            return False
+        if self.wrap_resolver.is_git_full_commit_id(revision) and \
+                quiet_git(['rev-parse', '--verify', revision + '^{commit}'], self.repo_dir)[0]:
+            # The revision we need is both a commit and available. So we do not
+            # need to fetch it because it cannot be updated.  Instead, trick
+            # git into setting FETCH_HEAD just in case, from the local commit.
+            self.git_output(['fetch', '.', revision])
+        else:
+            try:
+                # Fetch only the revision we need, this avoids fetching useless branches.
+                # revision can be either a branch, tag or commit id. In all cases we want
+                # FETCH_HEAD to be set to the desired commit and "git checkout "
+                # to to either switch to existing/new branch, or detach to tag/commit.
+                # It is more complicated than it first appear, see discussion there:
+                # https://github.com/mesonbuild/meson/pull/7723#discussion_r488816189.
+                heads_refmap = '+refs/heads/*:refs/remotes/origin/*'
+                tags_refmap = '+refs/tags/*:refs/tags/*'
+                self.git_output(['fetch', '--refmap', heads_refmap, '--refmap', tags_refmap, 'origin', revision])
+            except GitException as e:
+                self.log('  -> Could not fetch revision', mlog.bold(revision), 'in', mlog.bold(self.repo_dir))
+                self.log(mlog.red(e.output))
+                self.log(mlog.red(str(e)))
+                return False
+
+        if branch == '':
+            # We are currently in detached mode
+            if options.reset:
+                success = self.git_checkout_and_reset(revision)
+            else:
+                success = self.git_checkout_and_rebase(revision)
+        elif branch == revision:
+            # We are in the same branch. A reset could still be needed in the case
+            # a force push happened on remote repository.
+            if options.reset:
+                success = self.git_reset(revision)
+            else:
+                success = self.git_rebase(revision)
+        else:
+            # We are in another branch, either the user created their own branch and
+            # we should rebase it, or revision changed in the wrap file and we need
+            # to checkout the new branch.
+            if options.reset:
+                success = self.git_checkout_and_reset(revision)
+            else:
+                success = self.git_rebase(revision)
+        if success:
+            self.update_git_done()
+        return success
+
+    def update_git_done(self) -> None:
+        self.git_output(['submodule', 'update', '--checkout', '--recursive'])
+        self.git_show()
+
+    def update_hg(self) -> bool:
+        if not os.path.isdir(self.repo_dir):
+            self.log('  -> Not used.')
+            return True
+        revno = self.wrap.get('revision')
+        if revno.lower() == 'tip':
+            # Failure to do pull is not a fatal error,
+            # because otherwise you can't develop without
+            # a working net connection.
+            subprocess.call(['hg', 'pull'], cwd=self.repo_dir)
+        else:
+            if subprocess.call(['hg', 'checkout', revno], cwd=self.repo_dir) != 0:
+                subprocess.check_call(['hg', 'pull'], cwd=self.repo_dir)
+                subprocess.check_call(['hg', 'checkout', revno], cwd=self.repo_dir)
+        return True
+
+    def update_svn(self) -> bool:
+        if not os.path.isdir(self.repo_dir):
+            self.log('  -> Not used.')
+            return True
+        revno = self.wrap.get('revision')
+        _, out, _ = Popen_safe(['svn', 'info', '--show-item', 'revision', self.repo_dir])
+        current_revno = out
+        if current_revno == revno:
+            return True
+        if revno.lower() == 'head':
+            # Failure to do pull is not a fatal error,
+            # because otherwise you can't develop without
+            # a working net connection.
+            subprocess.call(['svn', 'update'], cwd=self.repo_dir)
+        else:
+            subprocess.check_call(['svn', 'update', '-r', revno], cwd=self.repo_dir)
+        return True
 
-def update(wrap, repo_dir, options):
-    mlog.log('Updating %s...' % wrap.name)
-    if wrap.type == 'file':
-        update_file(wrap, repo_dir, options)
-    elif wrap.type == 'git':
-        update_git(wrap, repo_dir, options)
-    elif wrap.type == 'hg':
-        update_hg(wrap, repo_dir, options)
-    elif wrap.type == 'svn':
-        update_svn(wrap, repo_dir, options)
-    else:
-        mlog.log('  -> Cannot update', wrap.type, 'subproject')
+    def update(self) -> bool:
+        self.log(f'Updating {self.wrap.name}...')
+        if self.wrap.type == 'file':
+            return self.update_file()
+        elif self.wrap.type == 'git':
+            return self.update_git()
+        elif self.wrap.type == 'hg':
+            return self.update_hg()
+        elif self.wrap.type == 'svn':
+            return self.update_svn()
+        elif self.wrap.type is None:
+            self.log('  -> Cannot update subproject with no wrap file')
+        else:
+            self.log('  -> Cannot update', self.wrap.type, 'subproject')
+        return True
+
+    def checkout(self) -> bool:
+        options = T.cast('CheckoutArguments', self.options)
+
+        if self.wrap.type != 'git' or not os.path.isdir(self.repo_dir):
+            return True
+        branch_name = options.branch_name if options.branch_name else self.wrap.get('revision')
+        if not branch_name:
+            # It could be a detached git submodule for example.
+            return True
+        self.log(f'Checkout {branch_name} in {self.wrap.name}...')
+        if self.git_checkout(branch_name, create=options.b):
+            self.git_show()
+            return True
+        return False
+
+    def download(self) -> bool:
+        self.log(f'Download {self.wrap.name}...')
+        if os.path.isdir(self.repo_dir):
+            self.log('  -> Already downloaded')
+            return True
+        try:
+            self.wrap_resolver.resolve(self.wrap.name, 'meson')
+            self.log('  -> done')
+        except WrapException as e:
+            self.log('  ->', mlog.red(str(e)))
+            return False
+        return True
+
+    def foreach(self) -> bool:
+        options = T.cast('ForeachArguments', self.options)
+
+        self.log(f'Executing command in {self.repo_dir}')
+        if not os.path.isdir(self.repo_dir):
+            self.log('  -> Not downloaded yet')
+            return True
+        cmd = [options.command] + options.args
+        p, out, _ = Popen_safe(cmd, stderr=subprocess.STDOUT, cwd=self.repo_dir)
+        if p.returncode != 0:
+            err_message = "Command '{}' returned non-zero exit status {}.".format(" ".join(cmd), p.returncode)
+            self.log('  -> ', mlog.red(err_message))
+            self.log(out, end='')
+            return False
+
+        self.log(out, end='')
+        return True
+
+    def purge(self) -> bool:
+        options = T.cast('PurgeArguments', self.options)
+
+        # if subproject is not wrap-based, then don't remove it
+        if not self.wrap.type:
+            return True
+
+        if self.wrap.redirected:
+            redirect_file = Path(self.wrap.original_filename).resolve()
+            if options.confirm:
+                redirect_file.unlink()
+            mlog.log(f'Deleting {redirect_file}')
+
+        if self.wrap.type == 'redirect':
+            redirect_file = Path(self.wrap.filename).resolve()
+            if options.confirm:
+                redirect_file.unlink()
+            self.log(f'Deleting {redirect_file}')
+
+        if options.include_cache:
+            packagecache = Path(self.wrap_resolver.cachedir).resolve()
+            try:
+                subproject_cache_file = packagecache / self.wrap.get("source_filename")
+                if subproject_cache_file.is_file():
+                    if options.confirm:
+                        subproject_cache_file.unlink()
+                    self.log(f'Deleting {subproject_cache_file}')
+            except WrapException:
+                pass
+
+            try:
+                subproject_patch_file = packagecache / self.wrap.get("patch_filename")
+                if subproject_patch_file.is_file():
+                    if options.confirm:
+                        subproject_patch_file.unlink()
+                    self.log(f'Deleting {subproject_patch_file}')
+            except WrapException:
+                pass
+
+            # Don't log that we will remove an empty directory. Since purge is
+            # parallelized, another thread could have deleted it already.
+            try:
+                if not any(packagecache.iterdir()):
+                    windows_proof_rmtree(str(packagecache))
+            except FileNotFoundError:
+                pass
+
+        # NOTE: Do not use .resolve() here; the subproject directory may be a symlink
+        subproject_source_dir = Path(self.repo_dir)
+        # Resolve just the parent, just to print out the full path
+        subproject_source_dir = subproject_source_dir.parent.resolve() / subproject_source_dir.name
+
+        # Don't follow symlink. This is covered by the next if statement, but why
+        # not be doubly sure.
+        if subproject_source_dir.is_symlink():
+            if options.confirm:
+                subproject_source_dir.unlink()
+            self.log(f'Deleting {subproject_source_dir}')
+            return True
+        if not subproject_source_dir.is_dir():
+            return True
+
+        try:
+            if options.confirm:
+                windows_proof_rmtree(str(subproject_source_dir))
+            self.log(f'Deleting {subproject_source_dir}')
+        except OSError as e:
+            mlog.error(f'Unable to remove: {subproject_source_dir}: {e}')
+            return False
+
+        return True
+
+    @staticmethod
+    def post_purge(options: 'PurgeArguments') -> None:
+        if not options.confirm:
+            mlog.log('')
+            mlog.log('Nothing has been deleted, run again with --confirm to apply.')
+
+    def packagefiles(self) -> bool:
+        options = T.cast('PackagefilesArguments', self.options)
+
+        if options.apply and options.save:
+            # not quite so nice as argparse failure
+            print('error: --apply and --save are mutually exclusive')
+            return False
+        if options.apply:
+            self.log(f'Re-applying patchfiles overlay for {self.wrap.name}...')
+            if not os.path.isdir(self.repo_dir):
+                self.log('  -> Not downloaded yet')
+                return True
+            self.wrap_resolver.apply_patch()
+            return True
+        if options.save:
+            if 'patch_directory' not in self.wrap.values:
+                mlog.error('can only save packagefiles to patch_directory')
+                return False
+            if 'source_filename' not in self.wrap.values:
+                mlog.error('can only save packagefiles from a [wrap-file]')
+                return False
+            archive_path = Path(self.wrap_resolver.cachedir, self.wrap.values['source_filename'])
+            lead_directory_missing = bool(self.wrap.values.get('lead_directory_missing', False))
+            directory = Path(self.repo_dir)
+            packagefiles = Path(self.wrap.filesdir, self.wrap.values['patch_directory'])
+
+            base_path = directory if lead_directory_missing else directory.parent
+            archive_files = read_archive_files(archive_path, base_path)
+            directory_files = set(directory.glob('**/*'))
+
+            self.log(f'Saving {self.wrap.name} to {packagefiles}...')
+            shutil.rmtree(packagefiles)
+            for src_path in directory_files - archive_files:
+                if not src_path.is_file():
+                    continue
+                rel_path = src_path.relative_to(directory)
+                dst_path = packagefiles / rel_path
+                dst_path.parent.mkdir(parents=True, exist_ok=True)
+                shutil.copyfile(src_path, dst_path)
+        return True
 
-def checkout(wrap, repo_dir, options):
-    if wrap.type != 'git' or not os.path.isdir(repo_dir):
-        return
-    branch_name = options.branch_name if options.branch_name else wrap.get('revision')
-    cmd = ['checkout', branch_name, '--']
-    if options.b:
-        cmd.insert(1, '-b')
-    mlog.log('Checkout %s in %s...' % (branch_name, wrap.name))
-    try:
-        git_output(cmd, repo_dir)
-        git_show(repo_dir)
-    except subprocess.CalledProcessError as e:
-        out = e.output.decode().strip()
-        mlog.log('  -> ', mlog.red(out))
-
-def download(wrap, repo_dir, options):
-    mlog.log('Download %s...' % wrap.name)
-    if os.path.isdir(repo_dir):
-        mlog.log('  -> Already downloaded')
-        return
-    try:
-        r = Resolver(os.path.dirname(repo_dir))
-        r.resolve(wrap.name, 'meson')
-        mlog.log('  -> done')
-    except WrapException as e:
-        mlog.log('  ->', mlog.red(str(e)))
-
-def foreach(wrap, repo_dir, options):
-    mlog.log('Executing command in %s' % repo_dir)
-    if not os.path.isdir(repo_dir):
-        mlog.log('  -> Not downloaded yet')
-        return
-    try:
-        out = subprocess.check_output([options.command] + options.args,
-                                      stderr=subprocess.STDOUT,
-                                      cwd=repo_dir).decode()
-        mlog.log(out, end='')
-    except subprocess.CalledProcessError as e:
-        err_message = "Command '%s' returned non-zero exit status %d." % (" ".join(e.cmd), e.returncode)
-        out = e.output.decode()
-        mlog.log('  -> ', mlog.red(err_message))
-        mlog.log(out, end='')
-    except Exception as e:
-        mlog.log('  -> ', mlog.red(str(e)))
 
-def add_common_arguments(p):
+def add_common_arguments(p: argparse.ArgumentParser) -> None:
     p.add_argument('--sourcedir', default='.',
                    help='Path to source directory')
+    p.add_argument('--types', default='',
+                   help=f'Comma-separated list of subproject types. Supported types are: {ALL_TYPES_STRING} (default: all)')
+    p.add_argument('--num-processes', default=None, type=int,
+                   help='How many parallel processes to use (Since 0.59.0).')
+
+def add_subprojects_argument(p: argparse.ArgumentParser) -> None:
     p.add_argument('subprojects', nargs='*',
                    help='List of subprojects (default: all)')
 
-def add_arguments(parser):
+def add_arguments(parser: argparse.ArgumentParser) -> None:
     subparsers = parser.add_subparsers(title='Commands', dest='command')
     subparsers.required = True
 
     p = subparsers.add_parser('update', help='Update all subprojects from wrap files')
-    p.add_argument('--rebase', default=False, action='store_true',
-                   help='Rebase your branch on top of wrap\'s revision (git only)')
+    p.add_argument('--rebase', default=True, action='store_true',
+                   help='Rebase your branch on top of wrap\'s revision. ' + \
+                        'Deprecated, it is now the default behaviour. (git only)')
+    p.add_argument('--reset', default=False, action='store_true',
+                   help='Checkout wrap\'s revision and hard reset to that commit. (git only)')
     add_common_arguments(p)
-    p.set_defaults(subprojects_func=update)
+    add_subprojects_argument(p)
+    p.set_defaults(subprojects_func=Runner.update)
 
     p = subparsers.add_parser('checkout', help='Checkout a branch (git only)')
     p.add_argument('-b', default=False, action='store_true',
@@ -208,24 +595,41 @@
     p.add_argument('branch_name', nargs='?',
                    help='Name of the branch to checkout or create (default: revision set in wrap file)')
     add_common_arguments(p)
-    p.set_defaults(subprojects_func=checkout)
+    add_subprojects_argument(p)
+    p.set_defaults(subprojects_func=Runner.checkout)
 
     p = subparsers.add_parser('download', help='Ensure subprojects are fetched, even if not in use. ' +
                                                'Already downloaded subprojects are not modified. ' +
                                                'This can be used to pre-fetch all subprojects and avoid downloads during configure.')
     add_common_arguments(p)
-    p.set_defaults(subprojects_func=download)
+    add_subprojects_argument(p)
+    p.set_defaults(subprojects_func=Runner.download)
 
     p = subparsers.add_parser('foreach', help='Execute a command in each subproject directory.')
     p.add_argument('command', metavar='command ...',
                    help='Command to execute in each subproject directory')
     p.add_argument('args', nargs=argparse.REMAINDER,
                    help=argparse.SUPPRESS)
-    p.add_argument('--sourcedir', default='.',
-                   help='Path to source directory')
-    p.set_defaults(subprojects_func=foreach)
+    add_common_arguments(p)
+    p.set_defaults(subprojects=[])
+    p.set_defaults(subprojects_func=Runner.foreach)
 
-def run(options):
+    p = subparsers.add_parser('purge', help='Remove all wrap-based subproject artifacts')
+    add_common_arguments(p)
+    add_subprojects_argument(p)
+    p.add_argument('--include-cache', action='store_true', default=False, help='Remove the package cache as well')
+    p.add_argument('--confirm', action='store_true', default=False, help='Confirm the removal of subproject artifacts')
+    p.set_defaults(subprojects_func=Runner.purge)
+    p.set_defaults(post_func=Runner.post_purge)
+
+    p = subparsers.add_parser('packagefiles', help='Manage the packagefiles overlay')
+    add_common_arguments(p)
+    add_subprojects_argument(p)
+    p.add_argument('--apply', action='store_true', default=False, help='Apply packagefiles to the subproject')
+    p.add_argument('--save', action='store_true', default=False, help='Save packagefiles from the subproject')
+    p.set_defaults(subprojects_func=Runner.packagefiles)
+
+def run(options: 'Arguments') -> int:
     src_dir = os.path.relpath(os.path.realpath(options.sourcedir))
     if not os.path.isfile(os.path.join(src_dir, 'meson.build')):
         mlog.error('Directory', mlog.bold(src_dir), 'does not seem to be a Meson source directory.')
@@ -234,22 +638,36 @@
     if not os.path.isdir(subprojects_dir):
         mlog.log('Directory', mlog.bold(src_dir), 'does not seem to have subprojects.')
         return 0
-    files = []
-    if hasattr(options, 'subprojects'):
-        for name in options.subprojects:
-            f = os.path.join(subprojects_dir, name + '.wrap')
-            if not os.path.isfile(f):
-                mlog.error('Subproject', mlog.bold(name), 'not found.')
-                return 1
-            else:
-                files.append(f)
-    if not files:
-        for f in os.listdir(subprojects_dir):
-            if f.endswith('.wrap'):
-                files.append(os.path.join(subprojects_dir, f))
-    for f in files:
-        wrap = PackageDefinition(f)
-        directory = wrap.values.get('directory', wrap.name)
-        repo_dir = os.path.join(subprojects_dir, directory)
-        options.subprojects_func(wrap, repo_dir, options)
-    return 0
+    r = Resolver(src_dir, 'subprojects')
+    if options.subprojects:
+        wraps = [wrap for name, wrap in r.wraps.items() if name in options.subprojects]
+    else:
+        wraps = list(r.wraps.values())
+    types = [t.strip() for t in options.types.split(',')] if options.types else []
+    for t in types:
+        if t not in ALL_TYPES:
+            raise MesonException(f'Unknown subproject type {t!r}, supported types are: {ALL_TYPES_STRING}')
+    tasks: T.List[T.Awaitable[bool]] = []
+    task_names: T.List[str] = []
+    loop = asyncio.get_event_loop()
+    executor = ThreadPoolExecutor(options.num_processes)
+    if types:
+        wraps = [wrap for wrap in wraps if wrap.type in types]
+    logger = Logger(len(wraps))
+    for wrap in wraps:
+        dirname = Path(subprojects_dir, wrap.directory).as_posix()
+        runner = Runner(logger, r, wrap, dirname, options)
+        task = loop.run_in_executor(executor, runner.run)
+        tasks.append(task)
+        task_names.append(wrap.name)
+    results = loop.run_until_complete(asyncio.gather(*tasks))
+    logger.flush()
+    post_func = getattr(options, 'post_func', None)
+    if post_func:
+        post_func(options)
+    failures = [name for name, success in zip(task_names, results) if not success]
+    if failures:
+        m = 'Please check logs above as command failed in some subprojects which could have been left in conflict state: '
+        m += ', '.join(failures)
+        mlog.warning(m)
+    return len(failures)
diff -Nru meson-0.53.2/mesonbuild/mtest.py meson-0.61.2/mesonbuild/mtest.py
--- meson-0.53.2/mesonbuild/mtest.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/mtest.py	2021-12-26 16:24:25.000000000 +0000
@@ -15,13 +15,12 @@
 # A tool to run tests in many different ways.
 
 from pathlib import Path
-from collections import namedtuple
+from collections import deque
 from copy import deepcopy
 import argparse
-import concurrent.futures as conc
+import asyncio
 import datetime
 import enum
-import io
 import json
 import multiprocessing
 import os
@@ -31,19 +30,24 @@
 import re
 import signal
 import subprocess
+import shlex
 import sys
-import tempfile
+import textwrap
 import time
 import typing as T
+import unicodedata
+import xml.etree.ElementTree as et
 
 from . import build
 from . import environment
 from . import mlog
-from .dependencies import ExternalProgram
-from .mesonlib import MesonException, get_wine_shortpath, split_args
-
-if T.TYPE_CHECKING:
-    from .backend.backends import TestSerialisation
+from .coredata import major_versions_differ, MesonVersionMismatchException
+from .coredata import version as coredata_version
+from .mesonlib import (MesonException, OrderedSet, RealPathAction,
+                       get_wine_shortpath, join_args, split_args, setup_vsenv)
+from .mintro import get_infodir, load_info_file
+from .programs import ExternalProgram
+from .backend.backends import TestProtocol, TestSerialisation
 
 # GNU autotools interprets a return code of 77 from tests it executes to
 # mean that the test should be skipped.
@@ -53,13 +57,23 @@
 # mean that the test failed even before testing what it is supposed to test.
 GNU_ERROR_RETURNCODE = 99
 
+# Exit if 3 Ctrl-C's are received within one second
+MAX_CTRLC = 3
+
 def is_windows() -> bool:
     platname = platform.system().lower()
-    return platname == 'windows' or 'mingw' in platname
+    return platname == 'windows'
 
 def is_cygwin() -> bool:
-    platname = platform.system().lower()
-    return 'cygwin' in platname
+    return sys.platform == 'cygwin'
+
+UNIWIDTH_MAPPING = {'F': 2, 'H': 1, 'W': 2, 'Na': 1, 'N': 1, 'A': 1}
+def uniwidth(s: str) -> int:
+    result = 0
+    for c in s:
+        w = unicodedata.east_asian_width(c)
+        result += UNIWIDTH_MAPPING[w]
+    return result
 
 def determine_worker_count() -> int:
     varname = 'MESON_TESTTHREADS'
@@ -67,7 +81,7 @@
         try:
             num_workers = int(os.environ[varname])
         except ValueError:
-            print('Invalid value in %s, using 1 thread.' % varname)
+            print(f'Invalid value in {varname}, using 1 thread.')
             num_workers = 1
     else:
         try:
@@ -91,7 +105,10 @@
                         help='List available tests.')
     parser.add_argument('--wrapper', default=None, dest='wrapper', type=split_args,
                         help='wrapper to run tests with (e.g. Valgrind)')
-    parser.add_argument('-C', default='.', dest='wd',
+    parser.add_argument('-C', dest='wd', action=RealPathAction,
+                        # https://github.com/python/typeshed/issues/3107
+                        # https://github.com/python/mypy/issues/7177
+                        type=os.path.abspath,  # type: ignore
                         help='directory to cd into before running')
     parser.add_argument('--suite', default=[], dest='include_suites', action='append', metavar='SUITE',
                         help='Only run tests belonging to the given suite.')
@@ -114,15 +131,41 @@
     parser.add_argument('-t', '--timeout-multiplier', type=float, default=None,
                         help='Define a multiplier for test timeout, for example '
                         ' when running tests in particular conditions they might take'
-                        ' more time to execute.')
+                        ' more time to execute. (<= 0 to disable timeout)')
     parser.add_argument('--setup', default=None, dest='setup',
                         help='Which test setup to use.')
     parser.add_argument('--test-args', default=[], type=split_args,
                         help='Arguments to pass to the specified test(s) or all tests')
     parser.add_argument('args', nargs='*',
-                        help='Optional list of tests to run')
+                        help='Optional list of test names to run. "testname" to run all tests with that name, '
+                        '"subprojname:testname" to specifically run "testname" from "subprojname", '
+                        '"subprojname:" to run all tests defined by "subprojname".')
 
 
+def print_safe(s: str) -> None:
+    end = '' if s[-1] == '\n' else '\n'
+    try:
+        print(s, end=end)
+    except UnicodeEncodeError:
+        s = s.encode('ascii', errors='backslashreplace').decode('ascii')
+        print(s, end=end)
+
+def join_lines(a: str, b: str) -> str:
+    if not a:
+        return b
+    if not b:
+        return a
+    return a + '\n' + b
+
+def dashes(s: str, dash: str, cols: int) -> str:
+    if not s:
+        return dash * cols
+    s = ' ' + s + ' '
+    width = uniwidth(s)
+    first = (cols - width) // 2
+    s = dash * first + s
+    return s + dash * (cols - first - width)
+
 def returncode_to_status(retcode: int) -> str:
     # Note: We can't use `os.WIFSIGNALED(result.returncode)` and the related
     # functions here because the status returned by subprocess is munged. It
@@ -136,20 +179,25 @@
             signame = signal.Signals(signum).name
         except ValueError:
             signame = 'SIGinvalid'
-        return '(killed by signal %d %s)' % (signum, signame)
+        return f'killed by signal {signum} {signame}'
 
     if retcode <= 128:
-        return '(exit status %d)' % (retcode,)
+        return f'exit status {retcode}'
 
     signum = retcode - 128
     try:
         signame = signal.Signals(signum).name
     except ValueError:
         signame = 'SIGinvalid'
-    return '(exit status %d or signal %d %s)' % (retcode, signum, signame)
+    return f'(exit status {retcode} or signal {signum} {signame})'
+
+# TODO for Windows
+sh_quote: T.Callable[[str], str] = lambda x: x
+if not is_windows():
+    sh_quote = shlex.quote
 
 def env_tuple_to_str(env: T.Iterable[T.Tuple[str, str]]) -> str:
-    return ''.join(["%s='%s' " % (k, v) for k, v in env])
+    return ''.join(["{}={} ".format(k, sh_quote(v)) for k, v in env])
 
 
 class TestException(MesonException):
@@ -157,23 +205,94 @@
 
 
 @enum.unique
+class ConsoleUser(enum.Enum):
+
+    # the logger can use the console
+    LOGGER = 0
+
+    # the console is used by gdb
+    GDB = 1
+
+    # the console is used to write stdout/stderr
+    STDOUT = 2
+
+
+@enum.unique
 class TestResult(enum.Enum):
 
+    PENDING = 'PENDING'
+    RUNNING = 'RUNNING'
     OK = 'OK'
     TIMEOUT = 'TIMEOUT'
+    INTERRUPT = 'INTERRUPT'
     SKIP = 'SKIP'
     FAIL = 'FAIL'
     EXPECTEDFAIL = 'EXPECTEDFAIL'
     UNEXPECTEDPASS = 'UNEXPECTEDPASS'
     ERROR = 'ERROR'
 
+    @staticmethod
+    def maxlen() -> int:
+        return 14 # len(UNEXPECTEDPASS)
+
+    def is_ok(self) -> bool:
+        return self in {TestResult.OK, TestResult.EXPECTEDFAIL}
+
+    def is_bad(self) -> bool:
+        return self in {TestResult.FAIL, TestResult.TIMEOUT, TestResult.INTERRUPT,
+                        TestResult.UNEXPECTEDPASS, TestResult.ERROR}
+
+    def is_finished(self) -> bool:
+        return self not in {TestResult.PENDING, TestResult.RUNNING}
+
+    def was_killed(self) -> bool:
+        return self in (TestResult.TIMEOUT, TestResult.INTERRUPT)
+
+    def colorize(self, s: str) -> mlog.AnsiDecorator:
+        if self.is_bad():
+            decorator = mlog.red
+        elif self in (TestResult.SKIP, TestResult.EXPECTEDFAIL):
+            decorator = mlog.yellow
+        elif self.is_finished():
+            decorator = mlog.green
+        else:
+            decorator = mlog.blue
+        return decorator(s)
+
+    def get_text(self, colorize: bool) -> str:
+        result_str = '{res:{reslen}}'.format(res=self.value, reslen=self.maxlen())
+        return self.colorize(result_str).get_text(colorize)
+
+    def get_command_marker(self) -> str:
+        return str(self.colorize('>>> '))
+
+
+TYPE_TAPResult = T.Union['TAPParser.Test', 'TAPParser.Error', 'TAPParser.Version', 'TAPParser.Plan', 'TAPParser.Bailout']
 
 class TAPParser:
-    Plan = namedtuple('Plan', ['count', 'late', 'skipped', 'explanation'])
-    Bailout = namedtuple('Bailout', ['message'])
-    Test = namedtuple('Test', ['number', 'name', 'result', 'explanation'])
-    Error = namedtuple('Error', ['message'])
-    Version = namedtuple('Version', ['version'])
+    class Plan(T.NamedTuple):
+        num_tests: int
+        late: bool
+        skipped: bool
+        explanation: T.Optional[str]
+
+    class Bailout(T.NamedTuple):
+        message: str
+
+    class Test(T.NamedTuple):
+        number: int
+        name: str
+        result: TestResult
+        explanation: T.Optional[str]
+
+        def __str__(self) -> str:
+            return f'{self.number} {self.name}'.strip()
+
+    class Error(T.NamedTuple):
+        message: str
+
+    class Version(T.NamedTuple):
+        version: int
 
     _MAIN = 1
     _AFTER_TEST = 2
@@ -187,8 +306,15 @@
     _RE_YAML_START = re.compile(r'(\s+)---.*')
     _RE_YAML_END = re.compile(r'\s+\.\.\.\s*')
 
-    def __init__(self, io: T.Iterator[str]):
-        self.io = io
+    found_late_test = False
+    bailed_out = False
+    plan: T.Optional[Plan] = None
+    lineno = 0
+    num_tests = 0
+    yaml_lineno: T.Optional[int] = None
+    yaml_indent = ''
+    state = _MAIN
+    version = 12
 
     def parse_test(self, ok: bool, num: int, name: str, directive: T.Optional[str], explanation: T.Optional[str]) -> \
             T.Generator[T.Union['TAPParser.Test', 'TAPParser.Error'], None, None]:
@@ -196,7 +322,7 @@
         explanation = explanation.strip() if explanation else None
         if directive is not None:
             directive = directive.upper()
-            if directive == 'SKIP':
+            if directive.startswith('SKIP'):
                 if ok:
                     yield self.Test(num, name, TestResult.SKIP, explanation)
                     return
@@ -204,211 +330,758 @@
                 yield self.Test(num, name, TestResult.UNEXPECTEDPASS if ok else TestResult.EXPECTEDFAIL, explanation)
                 return
             else:
-                yield self.Error('invalid directive "%s"' % (directive,))
+                yield self.Error(f'invalid directive "{directive}"')
 
         yield self.Test(num, name, TestResult.OK if ok else TestResult.FAIL, explanation)
 
-    def parse(self) -> T.Generator[T.Union['TAPParser.Test', 'TAPParser.Error', 'TAPParser.Version', 'TAPParser.Plan', 'TAPParser.Bailout'], None, None]:
-        found_late_test = False
-        bailed_out = False
-        plan = None
-        lineno = 0
-        num_tests = 0
-        yaml_lineno = None
-        yaml_indent = ''
-        state = self._MAIN
-        version = 12
-        while True:
-            lineno += 1
-            try:
-                line = next(self.io).rstrip()
-            except StopIteration:
-                break
+    async def parse_async(self, lines: T.AsyncIterator[str]) -> T.AsyncIterator[TYPE_TAPResult]:
+        async for line in lines:
+            for event in self.parse_line(line):
+                yield event
+        for event in self.parse_line(None):
+            yield event
+
+    def parse(self, io: T.Iterator[str]) -> T.Iterator[TYPE_TAPResult]:
+        for line in io:
+            yield from self.parse_line(line)
+        yield from self.parse_line(None)
+
+    def parse_line(self, line: T.Optional[str]) -> T.Iterator[TYPE_TAPResult]:
+        if line is not None:
+            self.lineno += 1
+            line = line.rstrip()
 
             # YAML blocks are only accepted after a test
-            if state == self._AFTER_TEST:
-                if version >= 13:
+            if self.state == self._AFTER_TEST:
+                if self.version >= 13:
                     m = self._RE_YAML_START.match(line)
                     if m:
-                        state = self._YAML
-                        yaml_lineno = lineno
-                        yaml_indent = m.group(1)
-                        continue
-                state = self._MAIN
+                        self.state = self._YAML
+                        self.yaml_lineno = self.lineno
+                        self.yaml_indent = m.group(1)
+                        return
+                self.state = self._MAIN
 
-            elif state == self._YAML:
+            elif self.state == self._YAML:
                 if self._RE_YAML_END.match(line):
-                    state = self._MAIN
-                    continue
-                if line.startswith(yaml_indent):
-                    continue
-                yield self.Error('YAML block not terminated (started on line {})'.format(yaml_lineno))
-                state = self._MAIN
+                    self.state = self._MAIN
+                    return
+                if line.startswith(self.yaml_indent):
+                    return
+                yield self.Error(f'YAML block not terminated (started on line {self.yaml_lineno})')
+                self.state = self._MAIN
 
-            assert state == self._MAIN
+            assert self.state == self._MAIN
             if line.startswith('#'):
-                continue
+                return
 
             m = self._RE_TEST.match(line)
             if m:
-                if plan and plan.late and not found_late_test:
+                if self.plan and self.plan.late and not self.found_late_test:
                     yield self.Error('unexpected test after late plan')
-                    found_late_test = True
-                num_tests += 1
-                num = num_tests if m.group(2) is None else int(m.group(2))
-                if num != num_tests:
+                    self.found_late_test = True
+                self.num_tests += 1
+                num = self.num_tests if m.group(2) is None else int(m.group(2))
+                if num != self.num_tests:
                     yield self.Error('out of order test numbers')
                 yield from self.parse_test(m.group(1) == 'ok', num,
                                            m.group(3), m.group(4), m.group(5))
-                state = self._AFTER_TEST
-                continue
+                self.state = self._AFTER_TEST
+                return
 
             m = self._RE_PLAN.match(line)
             if m:
-                if plan:
+                if self.plan:
                     yield self.Error('more than one plan found')
                 else:
-                    count = int(m.group(1))
-                    skipped = (count == 0)
+                    num_tests = int(m.group(1))
+                    skipped = (num_tests == 0)
                     if m.group(2):
                         if m.group(2).upper().startswith('SKIP'):
-                            if count > 0:
+                            if num_tests > 0:
                                 yield self.Error('invalid SKIP directive for plan')
                             skipped = True
                         else:
                             yield self.Error('invalid directive for plan')
-                    plan = self.Plan(count=count, late=(num_tests > 0),
-                                     skipped=skipped, explanation=m.group(3))
-                    yield plan
-                continue
+                    self.plan = self.Plan(num_tests=num_tests, late=(self.num_tests > 0),
+                                          skipped=skipped, explanation=m.group(3))
+                    yield self.plan
+                return
 
             m = self._RE_BAILOUT.match(line)
             if m:
                 yield self.Bailout(m.group(1))
-                bailed_out = True
-                continue
+                self.bailed_out = True
+                return
 
             m = self._RE_VERSION.match(line)
             if m:
                 # The TAP version is only accepted as the first line
-                if lineno != 1:
+                if self.lineno != 1:
                     yield self.Error('version number must be on the first line')
-                    continue
-                version = int(m.group(1))
-                if version < 13:
+                    return
+                self.version = int(m.group(1))
+                if self.version < 13:
                     yield self.Error('version number should be at least 13')
                 else:
-                    yield self.Version(version=version)
-                continue
+                    yield self.Version(version=self.version)
+                return
 
-            if len(line) == 0:
-                continue
+            if not line:
+                return
+
+            yield self.Error(f'unexpected input at line {self.lineno}')
+        else:
+            # end of file
+            if self.state == self._YAML:
+                yield self.Error(f'YAML block not terminated (started on line {self.yaml_lineno})')
+
+            if not self.bailed_out and self.plan and self.num_tests != self.plan.num_tests:
+                if self.num_tests < self.plan.num_tests:
+                    yield self.Error(f'Too few tests run (expected {self.plan.num_tests}, got {self.num_tests})')
+                else:
+                    yield self.Error(f'Too many tests run (expected {self.plan.num_tests}, got {self.num_tests})')
 
-            yield self.Error('unexpected input at line %d' % (lineno,))
+class TestLogger:
+    def flush(self) -> None:
+        pass
+
+    def start(self, harness: 'TestHarness') -> None:
+        pass
+
+    def start_test(self, harness: 'TestHarness', test: 'TestRun') -> None:
+        pass
+
+    def log_subtest(self, harness: 'TestHarness', test: 'TestRun', s: str, res: TestResult) -> None:
+        pass
+
+    def log(self, harness: 'TestHarness', result: 'TestRun') -> None:
+        pass
+
+    async def finish(self, harness: 'TestHarness') -> None:
+        pass
+
+    def close(self) -> None:
+        pass
+
+
+class TestFileLogger(TestLogger):
+    def __init__(self, filename: str, errors: str = 'replace') -> None:
+        self.filename = filename
+        self.file = open(filename, 'w', encoding='utf-8', errors=errors)
+
+    def close(self) -> None:
+        if self.file:
+            self.file.close()
+            self.file = None
+
+
+class ConsoleLogger(TestLogger):
+    ASCII_SPINNER = ['..', ':.', '.:']
+    SPINNER = ["\U0001f311", "\U0001f312", "\U0001f313", "\U0001f314",
+               "\U0001f315", "\U0001f316", "\U0001f317", "\U0001f318"]
+
+    SCISSORS = "\u2700 "
+    HLINE = "\u2015"
+    RTRI = "\u25B6 "
+
+    def __init__(self) -> None:
+        self.update = asyncio.Event()
+        self.running_tests = OrderedSet()  # type: OrderedSet['TestRun']
+        self.progress_test = None          # type: T.Optional['TestRun']
+        self.progress_task = None          # type: T.Optional[asyncio.Future]
+        self.max_left_width = 0            # type: int
+        self.stop = False
+        self.update = asyncio.Event()
+        self.should_erase_line = ''
+        self.test_count = 0
+        self.started_tests = 0
+        self.spinner_index = 0
+        try:
+            self.cols, _ = os.get_terminal_size(1)
+            self.is_tty = True
+        except OSError:
+            self.cols = 80
+            self.is_tty = False
+
+        self.output_start = dashes(self.SCISSORS, self.HLINE, self.cols - 2)
+        self.output_end = dashes('', self.HLINE, self.cols - 2)
+        self.sub = self.RTRI
+        self.spinner = self.SPINNER
+        try:
+            self.output_start.encode(sys.stdout.encoding or 'ascii')
+        except UnicodeEncodeError:
+            self.output_start = dashes('8<', '-', self.cols - 2)
+            self.output_end = dashes('', '-', self.cols - 2)
+            self.sub = '| '
+            self.spinner = self.ASCII_SPINNER
+
+    def flush(self) -> None:
+        if self.should_erase_line:
+            print(self.should_erase_line, end='')
+            self.should_erase_line = ''
+
+    def print_progress(self, line: str) -> None:
+        print(self.should_erase_line, line, sep='', end='\r')
+        self.should_erase_line = '\x1b[K'
+
+    def request_update(self) -> None:
+        self.update.set()
+
+    def emit_progress(self, harness: 'TestHarness') -> None:
+        if self.progress_test is None:
+            self.flush()
+            return
+
+        if len(self.running_tests) == 1:
+            count = f'{self.started_tests}/{self.test_count}'
+        else:
+            count = '{}-{}/{}'.format(self.started_tests - len(self.running_tests) + 1,
+                                      self.started_tests, self.test_count)
+
+        left = '[{}] {} '.format(count, self.spinner[self.spinner_index])
+        self.spinner_index = (self.spinner_index + 1) % len(self.spinner)
+
+        right = '{spaces} {dur:{durlen}}'.format(
+            spaces=' ' * TestResult.maxlen(),
+            dur=int(time.time() - self.progress_test.starttime),
+            durlen=harness.duration_max_len)
+        if self.progress_test.timeout:
+            right += '/{timeout:{durlen}}'.format(
+                timeout=self.progress_test.timeout,
+                durlen=harness.duration_max_len)
+        right += 's'
+        detail = self.progress_test.detail
+        if detail:
+            right += '   ' + detail
+
+        line = harness.format(self.progress_test, colorize=True,
+                              max_left_width=self.max_left_width,
+                              left=left, right=right)
+        self.print_progress(line)
+
+    def start(self, harness: 'TestHarness') -> None:
+        async def report_progress() -> None:
+            loop = asyncio.get_event_loop()
+            next_update = 0.0
+            self.request_update()
+            while not self.stop:
+                await self.update.wait()
+                self.update.clear()
+
+                # We may get here simply because the progress line has been
+                # overwritten, so do not always switch.  Only do so every
+                # second, or if the printed test has finished
+                if loop.time() >= next_update:
+                    self.progress_test = None
+                    next_update = loop.time() + 1
+                    loop.call_at(next_update, self.request_update)
+
+                if (self.progress_test and
+                        self.progress_test.res is not TestResult.RUNNING):
+                    self.progress_test = None
+
+                if not self.progress_test:
+                    if not self.running_tests:
+                        continue
+                    # Pick a test in round robin order
+                    self.progress_test = self.running_tests.pop(last=False)
+                    self.running_tests.add(self.progress_test)
+
+                self.emit_progress(harness)
+            self.flush()
+
+        self.test_count = harness.test_count
+        self.cols = max(self.cols, harness.max_left_width + 30)
+
+        if self.is_tty and not harness.need_console:
+            # Account for "[aa-bb/cc] OO " in the progress report
+            self.max_left_width = 3 * len(str(self.test_count)) + 8
+            self.progress_task = asyncio.ensure_future(report_progress())
+
+    def start_test(self, harness: 'TestHarness', test: 'TestRun') -> None:
+        if harness.options.verbose and test.cmdline:
+            self.flush()
+            print(harness.format(test, mlog.colorize_console(),
+                                 max_left_width=self.max_left_width,
+                                 right=test.res.get_text(mlog.colorize_console())))
+            print(test.res.get_command_marker() + test.cmdline)
+            if test.needs_parsing:
+                pass
+            elif not test.is_parallel:
+                print(self.output_start, flush=True)
+            else:
+                print(flush=True)
+
+        self.started_tests += 1
+        self.running_tests.add(test)
+        self.running_tests.move_to_end(test, last=False)
+        self.request_update()
+
+    def shorten_log(self, harness: 'TestHarness', result: 'TestRun') -> str:
+        if not harness.options.verbose and not harness.options.print_errorlogs:
+            return ''
+
+        log = result.get_log(mlog.colorize_console(),
+                             stderr_only=result.needs_parsing)
+        if harness.options.verbose:
+            return log
+
+        lines = log.splitlines()
+        if len(lines) < 100:
+            return log
+        else:
+            return str(mlog.bold('Listing only the last 100 lines from a long log.\n')) + '\n'.join(lines[-100:])
+
+    def print_log(self, harness: 'TestHarness', result: 'TestRun') -> None:
+        if not harness.options.verbose:
+            cmdline = result.cmdline
+            if not cmdline:
+                print(result.res.get_command_marker() + result.stdo)
+                return
+            print(result.res.get_command_marker() + cmdline)
+
+        log = self.shorten_log(harness, result)
+        if log:
+            print(self.output_start)
+            print_safe(log)
+            print(self.output_end)
+
+    def log_subtest(self, harness: 'TestHarness', test: 'TestRun', s: str, result: TestResult) -> None:
+        if harness.options.verbose or (harness.options.print_errorlogs and result.is_bad()):
+            self.flush()
+            print(harness.format(test, mlog.colorize_console(), max_left_width=self.max_left_width,
+                                 prefix=self.sub,
+                                 middle=s,
+                                 right=result.get_text(mlog.colorize_console())), flush=True)
+
+            self.request_update()
+
+    def log(self, harness: 'TestHarness', result: 'TestRun') -> None:
+        self.running_tests.remove(result)
+        if result.res is TestResult.TIMEOUT and harness.options.verbose:
+            self.flush()
+            print(f'{result.name} time out (After {result.timeout} seconds)')
+
+        if not harness.options.quiet or not result.res.is_ok():
+            self.flush()
+            if harness.options.verbose and not result.is_parallel and result.cmdline:
+                if not result.needs_parsing:
+                    print(self.output_end)
+                print(harness.format(result, mlog.colorize_console(), max_left_width=self.max_left_width))
+            else:
+                print(harness.format(result, mlog.colorize_console(), max_left_width=self.max_left_width),
+                      flush=True)
+                if harness.options.verbose or result.res.is_bad():
+                    self.print_log(harness, result)
+            if harness.options.verbose or result.res.is_bad():
+                print(flush=True)
+
+        self.request_update()
+
+    async def finish(self, harness: 'TestHarness') -> None:
+        self.stop = True
+        self.request_update()
+        if self.progress_task:
+            await self.progress_task
+
+        if harness.collected_failures and \
+                (harness.options.print_errorlogs or harness.options.verbose):
+            print("\nSummary of Failures:\n")
+            for i, result in enumerate(harness.collected_failures, 1):
+                print(harness.format(result, mlog.colorize_console()))
+
+        print(harness.summary())
+
+
+class TextLogfileBuilder(TestFileLogger):
+    def start(self, harness: 'TestHarness') -> None:
+        self.file.write(f'Log of Meson test suite run on {datetime.datetime.now().isoformat()}\n\n')
+        inherit_env = env_tuple_to_str(os.environ.items())
+        self.file.write(f'Inherited environment: {inherit_env}\n\n')
+
+    def log(self, harness: 'TestHarness', result: 'TestRun') -> None:
+        self.file.write(harness.format(result, False) + '\n')
+        cmdline = result.cmdline
+        if cmdline:
+            starttime_str = time.strftime("%H:%M:%S", time.gmtime(result.starttime))
+            self.file.write(starttime_str + ' ' + cmdline + '\n')
+            self.file.write(dashes('output', '-', 78) + '\n')
+            self.file.write(result.get_log())
+            self.file.write(dashes('', '-', 78) + '\n\n')
+
+    async def finish(self, harness: 'TestHarness') -> None:
+        if harness.collected_failures:
+            self.file.write("\nSummary of Failures:\n\n")
+            for i, result in enumerate(harness.collected_failures, 1):
+                self.file.write(harness.format(result, False) + '\n')
+        self.file.write(harness.summary())
+
+        print(f'Full log written to {self.filename}')
+
+
+class JsonLogfileBuilder(TestFileLogger):
+    def log(self, harness: 'TestHarness', result: 'TestRun') -> None:
+        jresult = {'name': result.name,
+                   'stdout': result.stdo,
+                   'result': result.res.value,
+                   'starttime': result.starttime,
+                   'duration': result.duration,
+                   'returncode': result.returncode,
+                   'env': result.env,
+                   'command': result.cmd}  # type: T.Dict[str, T.Any]
+        if result.stde:
+            jresult['stderr'] = result.stde
+        self.file.write(json.dumps(jresult) + '\n')
+
+
+class JunitBuilder(TestLogger):
+
+    """Builder for Junit test results.
+
+    Junit is impossible to stream out, it requires attributes counting the
+    total number of tests, failures, skips, and errors in the root element
+    and in each test suite. As such, we use a builder class to track each
+    test case, and calculate all metadata before writing it out.
+
+    For tests with multiple results (like from a TAP test), we record the
+    test as a suite with the project_name.test_name. This allows us to track
+    each result separately. For tests with only one result (such as exit-code
+    tests) we record each one into a suite with the name project_name. The use
+    of the project_name allows us to sort subproject tests separately from
+    the root project.
+    """
+
+    def __init__(self, filename: str) -> None:
+        self.filename = filename
+        self.root = et.Element(
+            'testsuites', tests='0', errors='0', failures='0')
+        self.suites = {}  # type: T.Dict[str, et.Element]
+
+    def log(self, harness: 'TestHarness', test: 'TestRun') -> None:
+        """Log a single test case."""
+        if test.junit is not None:
+            for suite in test.junit.findall('.//testsuite'):
+                # Assume that we don't need to merge anything here...
+                suite.attrib['name'] = '{}.{}.{}'.format(test.project, test.name, suite.attrib['name'])
+
+                # GTest can inject invalid attributes
+                for case in suite.findall('.//testcase[@result]'):
+                    del case.attrib['result']
+                for case in suite.findall('.//testcase[@timestamp]'):
+                    del case.attrib['timestamp']
+                self.root.append(suite)
+            return
 
-        if state == self._YAML:
-            yield self.Error('YAML block not terminated (started on line {})'.format(yaml_lineno))
+        # In this case we have a test binary with multiple results.
+        # We want to record this so that each result is recorded
+        # separately
+        if test.results:
+            suitename = f'{test.project}.{test.name}'
+            assert suitename not in self.suites or harness.options.repeat > 1, 'duplicate suite'
+
+            suite = self.suites[suitename] = et.Element(
+                'testsuite',
+                name=suitename,
+                tests=str(len(test.results)),
+                errors=str(sum(1 for r in test.results if r.result in
+                               {TestResult.INTERRUPT, TestResult.ERROR})),
+                failures=str(sum(1 for r in test.results if r.result in
+                                 {TestResult.FAIL, TestResult.UNEXPECTEDPASS, TestResult.TIMEOUT})),
+                skipped=str(sum(1 for r in test.results if r.result is TestResult.SKIP)),
+                time=str(test.duration),
+            )
 
-        if not bailed_out and plan and num_tests != plan.count:
-            if num_tests < plan.count:
-                yield self.Error('Too few tests run (expected %d, got %d)' % (plan.count, num_tests))
+            for subtest in test.results:
+                # Both name and classname are required. Use the suite name as
+                # the class name, so that e.g. GitLab groups testcases correctly.
+                testcase = et.SubElement(suite, 'testcase', name=str(subtest), classname=suitename)
+                if subtest.result is TestResult.SKIP:
+                    et.SubElement(testcase, 'skipped')
+                elif subtest.result is TestResult.ERROR:
+                    et.SubElement(testcase, 'error')
+                elif subtest.result is TestResult.FAIL:
+                    et.SubElement(testcase, 'failure')
+                elif subtest.result is TestResult.UNEXPECTEDPASS:
+                    fail = et.SubElement(testcase, 'failure')
+                    fail.text = 'Test unexpected passed.'
+                elif subtest.result is TestResult.INTERRUPT:
+                    fail = et.SubElement(testcase, 'error')
+                    fail.text = 'Test was interrupted by user.'
+                elif subtest.result is TestResult.TIMEOUT:
+                    fail = et.SubElement(testcase, 'error')
+                    fail.text = 'Test did not finish before configured timeout.'
+                if subtest.explanation:
+                    et.SubElement(testcase, 'system-out').text = subtest.explanation
+            if test.stdo:
+                out = et.SubElement(suite, 'system-out')
+                out.text = test.stdo.rstrip()
+            if test.stde:
+                err = et.SubElement(suite, 'system-err')
+                err.text = test.stde.rstrip()
+        else:
+            if test.project not in self.suites:
+                suite = self.suites[test.project] = et.Element(
+                    'testsuite', name=test.project, tests='1', errors='0',
+                    failures='0', skipped='0', time=str(test.duration))
             else:
-                yield self.Error('Too many tests run (expected %d, got %d)' % (plan.count, num_tests))
+                suite = self.suites[test.project]
+                suite.attrib['tests'] = str(int(suite.attrib['tests']) + 1)
+
+            testcase = et.SubElement(suite, 'testcase', name=test.name,
+                                     classname=test.project, time=str(test.duration))
+            if test.res is TestResult.SKIP:
+                et.SubElement(testcase, 'skipped')
+                suite.attrib['skipped'] = str(int(suite.attrib['skipped']) + 1)
+            elif test.res is TestResult.ERROR:
+                et.SubElement(testcase, 'error')
+                suite.attrib['errors'] = str(int(suite.attrib['errors']) + 1)
+            elif test.res is TestResult.FAIL:
+                et.SubElement(testcase, 'failure')
+                suite.attrib['failures'] = str(int(suite.attrib['failures']) + 1)
+            if test.stdo:
+                out = et.SubElement(testcase, 'system-out')
+                out.text = test.stdo.rstrip()
+            if test.stde:
+                err = et.SubElement(testcase, 'system-err')
+                err.text = test.stde.rstrip()
+
+    async def finish(self, harness: 'TestHarness') -> None:
+        """Calculate total test counts and write out the xml result."""
+        for suite in self.suites.values():
+            self.root.append(suite)
+            # Skipped is really not allowed in the "testsuits" element
+            for attr in ['tests', 'errors', 'failures']:
+                self.root.attrib[attr] = str(int(self.root.attrib[attr]) + int(suite.attrib[attr]))
+
+        tree = et.ElementTree(self.root)
+        with open(self.filename, 'wb') as f:
+            tree.write(f, encoding='utf-8', xml_declaration=True)
 
 
 class TestRun:
+    TEST_NUM = 0
+    PROTOCOL_TO_CLASS: T.Dict[TestProtocol, T.Type['TestRun']] = {}
 
-    @classmethod
-    def make_exitcode(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
-                      returncode: int, starttime: float, duration: float,
-                      stdo: T.Optional[str], stde: T.Optional[str],
-                      cmd: T.Optional[T.List[str]]) -> 'TestRun':
-        if returncode == GNU_SKIP_RETURNCODE:
+    def __new__(cls, test: TestSerialisation, *args: T.Any, **kwargs: T.Any) -> T.Any:
+        return super().__new__(TestRun.PROTOCOL_TO_CLASS[test.protocol])
+
+    def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str],
+                 name: str, timeout: T.Optional[int], is_parallel: bool):
+        self.res = TestResult.PENDING
+        self.test = test
+        self._num = None       # type: T.Optional[int]
+        self.name = name
+        self.timeout = timeout
+        self.results = list()  # type: T.List[TAPParser.Test]
+        self.returncode = 0
+        self.starttime = None  # type: T.Optional[float]
+        self.duration = None   # type: T.Optional[float]
+        self.stdo = None       # type: T.Optional[str]
+        self.stde = None       # type: T.Optional[str]
+        self.cmd = None        # type: T.Optional[T.List[str]]
+        self.env = test_env    # type: T.Dict[str, str]
+        self.should_fail = test.should_fail
+        self.project = test.project_name
+        self.junit = None      # type: T.Optional[et.ElementTree]
+        self.is_parallel = is_parallel
+
+    def start(self, cmd: T.List[str]) -> None:
+        self.res = TestResult.RUNNING
+        self.starttime = time.time()
+        self.cmd = cmd
+
+    @property
+    def num(self) -> int:
+        if self._num is None:
+            TestRun.TEST_NUM += 1
+            self._num = TestRun.TEST_NUM
+        return self._num
+
+    @property
+    def detail(self) -> str:
+        if self.res is TestResult.PENDING:
+            return ''
+        if self.returncode:
+            return returncode_to_status(self.returncode)
+        if self.results:
+            # running or succeeded
+            passed = sum(x.result.is_ok() for x in self.results)
+            ran = sum(x.result is not TestResult.SKIP for x in self.results)
+            if passed == ran:
+                return f'{passed} subtests passed'
+            else:
+                return f'{passed}/{ran} subtests passed'
+        return ''
+
+    def _complete(self, returncode: int, res: TestResult,
+                  stdo: T.Optional[str], stde: T.Optional[str]) -> None:
+        assert isinstance(res, TestResult)
+        if self.should_fail and res in (TestResult.OK, TestResult.FAIL):
+            res = TestResult.UNEXPECTEDPASS if res.is_ok() else TestResult.EXPECTEDFAIL
+
+        self.res = res
+        self.returncode = returncode
+        self.duration = time.time() - self.starttime
+        self.stdo = stdo
+        self.stde = stde
+
+    @property
+    def cmdline(self) -> T.Optional[str]:
+        if not self.cmd:
+            return None
+        test_only_env = set(self.env.items()) - set(os.environ.items())
+        return env_tuple_to_str(test_only_env) + \
+            ' '.join(sh_quote(x) for x in self.cmd)
+
+    def complete_skip(self, message: str) -> None:
+        self.starttime = time.time()
+        self._complete(GNU_SKIP_RETURNCODE, TestResult.SKIP, message, None)
+
+    def complete(self, returncode: int, res: TestResult,
+                 stdo: T.Optional[str], stde: T.Optional[str]) -> None:
+        self._complete(returncode, res, stdo, stde)
+
+    def get_log(self, colorize: bool = False, stderr_only: bool = False) -> str:
+        stdo = '' if stderr_only else self.stdo
+        if self.stde:
+            res = ''
+            if stdo:
+                res += mlog.cyan('stdout:').get_text(colorize) + '\n'
+                res += stdo
+                if res[-1:] != '\n':
+                    res += '\n'
+            res += mlog.cyan('stderr:').get_text(colorize) + '\n'
+            res += self.stde
+        else:
+            res = stdo
+        if res and res[-1:] != '\n':
+            res += '\n'
+        return res
+
+    @property
+    def needs_parsing(self) -> bool:
+        return False
+
+    async def parse(self, harness: 'TestHarness', lines: T.AsyncIterator[str]) -> T.Tuple[TestResult, str]:
+        async for l in lines:
+            pass
+        return TestResult.OK, ''
+
+
+class TestRunExitCode(TestRun):
+
+    def complete(self, returncode: int, res: TestResult,
+                 stdo: T.Optional[str], stde: T.Optional[str]) -> None:
+        if res:
+            pass
+        elif returncode == GNU_SKIP_RETURNCODE:
             res = TestResult.SKIP
         elif returncode == GNU_ERROR_RETURNCODE:
             res = TestResult.ERROR
-        elif test.should_fail:
-            res = TestResult.EXPECTEDFAIL if bool(returncode) else TestResult.UNEXPECTEDPASS
         else:
             res = TestResult.FAIL if bool(returncode) else TestResult.OK
-        return cls(test, test_env, res, returncode, starttime, duration, stdo, stde, cmd)
+        super().complete(returncode, res, stdo, stde)
+
+TestRun.PROTOCOL_TO_CLASS[TestProtocol.EXITCODE] = TestRunExitCode
+
+
+class TestRunGTest(TestRunExitCode):
+    def complete(self, returncode: int, res: TestResult,
+                 stdo: T.Optional[str], stde: T.Optional[str]) -> None:
+        filename = f'{self.test.name}.xml'
+        if self.test.workdir:
+            filename = os.path.join(self.test.workdir, filename)
+
+        try:
+            self.junit = et.parse(filename)
+        except FileNotFoundError:
+            # This can happen if the test fails to run or complete for some
+            # reason, like the rpath for libgtest isn't properly set. ExitCode
+            # will handle the failure, don't generate a stacktrace.
+            pass
+
+        super().complete(returncode, res, stdo, stde)
+
+TestRun.PROTOCOL_TO_CLASS[TestProtocol.GTEST] = TestRunGTest
+
+
+class TestRunTAP(TestRun):
+    @property
+    def needs_parsing(self) -> bool:
+        return True
+
+    def complete(self, returncode: int, res: TestResult,
+                 stdo: str, stde: str) -> None:
+        if returncode != 0 and not res.was_killed():
+            res = TestResult.ERROR
+            stde = stde or ''
+            stde += f'\n(test program exited with status code {returncode})'
+
+        super().complete(returncode, res, stdo, stde)
 
-    @classmethod
-    def make_tap(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
-                 returncode: int, starttime: float, duration: float,
-                 stdo: str, stde: str,
-                 cmd: T.Optional[T.List[str]]) -> 'TestRun':
-        res = None
-        num_tests = 0
-        failed = False
-        num_skipped = 0
+    async def parse(self, harness: 'TestHarness', lines: T.AsyncIterator[str]) -> T.Tuple[TestResult, str]:
+        res = TestResult.OK
+        error = ''
 
-        for i in TAPParser(io.StringIO(stdo)).parse():
+        async for i in TAPParser().parse_async(lines):
             if isinstance(i, TAPParser.Bailout):
                 res = TestResult.ERROR
+                harness.log_subtest(self, i.message, res)
             elif isinstance(i, TAPParser.Test):
-                if i.result == TestResult.SKIP:
-                    num_skipped += 1
-                elif i.result in (TestResult.FAIL, TestResult.UNEXPECTEDPASS):
-                    failed = True
-                num_tests += 1
+                self.results.append(i)
+                if i.result.is_bad():
+                    res = TestResult.FAIL
+                harness.log_subtest(self, i.name or f'subtest {i.number}', i.result)
             elif isinstance(i, TAPParser.Error):
+                error = '\nTAP parsing error: ' + i.message
                 res = TestResult.ERROR
-                stde += '\nTAP parsing error: ' + i.message
 
-        if returncode != 0:
-            res = TestResult.ERROR
-            stde += '\n(test program exited with status code %d)' % (returncode,)
+        if all(t.result is TestResult.SKIP for t in self.results):
+            # This includes the case where self.results is empty
+            res = TestResult.SKIP
+        return res, error
 
-        if res is None:
-            # Now determine the overall result of the test based on the outcome of the subcases
-            if num_skipped == num_tests:
-                # This includes the case where num_tests is zero
-                res = TestResult.SKIP
-            elif test.should_fail:
-                res = TestResult.EXPECTEDFAIL if failed else TestResult.UNEXPECTEDPASS
-            else:
-                res = TestResult.FAIL if failed else TestResult.OK
+TestRun.PROTOCOL_TO_CLASS[TestProtocol.TAP] = TestRunTAP
 
-        return cls(test, test_env, res, returncode, starttime, duration, stdo, stde, cmd)
 
-    def __init__(self, test: 'TestSerialisation', test_env: T.Dict[str, str],
-                 res: TestResult, returncode: int, starttime: float, duration: float,
-                 stdo: T.Optional[str], stde: T.Optional[str],
-                 cmd: T.Optional[T.List[str]]):
-        assert isinstance(res, TestResult)
-        self.res = res
-        self.returncode = returncode
-        self.starttime = starttime
-        self.duration = duration
-        self.stdo = stdo
-        self.stde = stde
-        self.cmd = cmd
-        self.env = test_env
-        self.should_fail = test.should_fail
+class TestRunRust(TestRun):
+    @property
+    def needs_parsing(self) -> bool:
+        return True
+
+    async def parse(self, harness: 'TestHarness', lines: T.AsyncIterator[str]) -> T.Tuple[TestResult, str]:
+        def parse_res(n: int, name: str, result: str) -> TAPParser.Test:
+            if result == 'ok':
+                return TAPParser.Test(n, name, TestResult.OK, None)
+            elif result == 'ignored':
+                return TAPParser.Test(n, name, TestResult.SKIP, None)
+            elif result == 'FAILED':
+                return TAPParser.Test(n, name, TestResult.FAIL, None)
+            return TAPParser.Test(n, name, TestResult.ERROR,
+                                  f'Unsupported output from rust test: {result}')
+
+        n = 1
+        async for line in lines:
+            if line.startswith('test ') and not line.startswith('test result'):
+                _, name, _, result = line.rstrip().split(' ')
+                name = name.replace('::', '.')
+                t = parse_res(n, name, result)
+                self.results.append(t)
+                harness.log_subtest(self, name, t.result)
+                n += 1
+
+        if all(t.result is TestResult.SKIP for t in self.results):
+            # This includes the case where self.results is empty
+            return TestResult.SKIP, ''
+        elif any(t.result is TestResult.ERROR for t in self.results):
+            return TestResult.ERROR, ''
+        elif any(t.result is TestResult.FAIL for t in self.results):
+            return TestResult.FAIL, ''
+        return TestResult.OK, ''
+
+TestRun.PROTOCOL_TO_CLASS[TestProtocol.RUST] = TestRunRust
 
-    def get_log(self) -> str:
-        res = '--- command ---\n'
-        if self.cmd is None:
-            res += 'NONE\n'
-        else:
-            test_only_env = set(self.env.items()) - set(os.environ.items())
-            starttime_str = time.strftime("%H:%M:%S", time.gmtime(self.starttime))
-            res += '{} {}{}\n'.format(
-                starttime_str, env_tuple_to_str(test_only_env), ' '.join(self.cmd)
-            )
-        if self.stdo:
-            res += '--- stdout ---\n'
-            res += self.stdo
-        if self.stde:
-            if res[-1:] != '\n':
-                res += '\n'
-            res += '--- stderr ---\n'
-            res += self.stde
-        if res[-1:] != '\n':
-            res += '\n'
-        res += '-------\n\n'
-        return res
 
 def decode(stream: T.Union[None, bytes]) -> str:
     if stream is None:
@@ -418,93 +1091,229 @@
     except UnicodeDecodeError:
         return stream.decode('iso-8859-1', errors='ignore')
 
-def write_json_log(jsonlogfile: T.TextIO, test_name: str, result: TestRun) -> None:
-    jresult = {'name': test_name,
-               'stdout': result.stdo,
-               'result': result.res.value,
-               'starttime': result.starttime,
-               'duration': result.duration,
-               'returncode': result.returncode,
-               'env': result.env,
-               'command': result.cmd}  # type: T.Dict[str, T.Any]
-    if result.stde:
-        jresult['stderr'] = result.stde
-    jsonlogfile.write(json.dumps(jresult) + '\n')
+async def read_decode(reader: asyncio.StreamReader, console_mode: ConsoleUser) -> str:
+    stdo_lines = []
+    try:
+        while not reader.at_eof():
+            # Prefer splitting by line, as that produces nicer output
+            try:
+                line_bytes = await reader.readuntil(b'\n')
+            except asyncio.IncompleteReadError as e:
+                line_bytes = e.partial
+            except asyncio.LimitOverrunError as e:
+                line_bytes = await reader.readexactly(e.consumed)
+            line = decode(line_bytes)
+            stdo_lines.append(line)
+            if console_mode is ConsoleUser.STDOUT:
+                print(line, end='', flush=True)
+        return ''.join(stdo_lines)
+    except asyncio.CancelledError:
+        return ''.join(stdo_lines)
+
+# Extract lines out of the StreamReader.  Print them
+# along the way if requested, and at the end collect
+# them all into a future.
+async def read_decode_lines(reader: asyncio.StreamReader, q: 'asyncio.Queue[T.Optional[str]]',
+                            console_mode: ConsoleUser) -> str:
+    stdo_lines = []
+    try:
+        while not reader.at_eof():
+            line = decode(await reader.readline())
+            stdo_lines.append(line)
+            if console_mode is ConsoleUser.STDOUT:
+                print(line, end='', flush=True)
+            await q.put(line)
+        return ''.join(stdo_lines)
+    except asyncio.CancelledError:
+        return ''.join(stdo_lines)
+    finally:
+        await q.put(None)
 
 def run_with_mono(fname: str) -> bool:
-    if fname.endswith('.exe') and not (is_windows() or is_cygwin()):
-        return True
-    return False
+    return fname.endswith('.exe') and not (is_windows() or is_cygwin())
 
-def load_benchmarks(build_dir: str) -> T.List['TestSerialisation']:
-    datafile = Path(build_dir) / 'meson-private' / 'meson_benchmark_setup.dat'
-    if not datafile.is_file():
-        raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
-    with datafile.open('rb') as f:
-        obj = T.cast(T.List['TestSerialisation'], pickle.load(f))
-    return obj
-
-def load_tests(build_dir: str) -> T.List['TestSerialisation']:
-    datafile = Path(build_dir) / 'meson-private' / 'meson_test_setup.dat'
-    if not datafile.is_file():
-        raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
-    with datafile.open('rb') as f:
-        obj = T.cast(T.List['TestSerialisation'], pickle.load(f))
-    return obj
+def check_testdata(objs: T.List[TestSerialisation]) -> T.List[TestSerialisation]:
+    if not isinstance(objs, list):
+        raise MesonVersionMismatchException('', coredata_version)
+    for obj in objs:
+        if not isinstance(obj, TestSerialisation):
+            raise MesonVersionMismatchException('', coredata_version)
+        if not hasattr(obj, 'version'):
+            raise MesonVersionMismatchException('', coredata_version)
+        if major_versions_differ(obj.version, coredata_version):
+            raise MesonVersionMismatchException(obj.version, coredata_version)
+    return objs
+
+# Custom waiting primitives for asyncio
+
+async def try_wait_one(*awaitables: T.Any, timeout: T.Optional[T.Union[int, float]]) -> None:
+    """Wait for completion of one of the given futures, ignoring timeouts."""
+    await asyncio.wait(awaitables,
+                       timeout=timeout, return_when=asyncio.FIRST_COMPLETED)
+
+async def queue_iter(q: 'asyncio.Queue[T.Optional[str]]') -> T.AsyncIterator[str]:
+    while True:
+        item = await q.get()
+        q.task_done()
+        if item is None:
+            break
+        yield item
 
+async def complete(future: asyncio.Future) -> None:
+    """Wait for completion of the given future, ignoring cancellation."""
+    try:
+        await future
+    except asyncio.CancelledError:
+        pass
+
+async def complete_all(futures: T.Iterable[asyncio.Future],
+                       timeout: T.Optional[T.Union[int, float]] = None) -> None:
+    """Wait for completion of all the given futures, ignoring cancellation.
+       If timeout is not None, raise an asyncio.TimeoutError after the given
+       time has passed.  asyncio.TimeoutError is only raised if some futures
+       have not completed and none have raised exceptions, even if timeout
+       is zero."""
+
+    def check_futures(futures: T.Iterable[asyncio.Future]) -> None:
+        # Raise exceptions if needed
+        left = False
+        for f in futures:
+            if not f.done():
+                left = True
+            elif not f.cancelled():
+                f.result()
+        if left:
+            raise asyncio.TimeoutError
+
+    # Python is silly and does not have a variant of asyncio.wait with an
+    # absolute time as deadline.
+    deadline = None if timeout is None else asyncio.get_event_loop().time() + timeout
+    while futures and (timeout is None or timeout > 0):
+        done, futures = await asyncio.wait(futures, timeout=timeout,
+                                           return_when=asyncio.FIRST_EXCEPTION)
+        check_futures(done)
+        if deadline:
+            timeout = deadline - asyncio.get_event_loop().time()
+
+    check_futures(futures)
+
+
+class TestSubprocess:
+    def __init__(self, p: asyncio.subprocess.Process,
+                 stdout: T.Optional[int], stderr: T.Optional[int],
+                 postwait_fn: T.Callable[[], None] = None):
+        self._process = p
+        self.stdout = stdout
+        self.stderr = stderr
+        self.stdo_task = None            # type: T.Optional[asyncio.Future[str]]
+        self.stde_task = None            # type: T.Optional[asyncio.Future[str]]
+        self.postwait_fn = postwait_fn   # type: T.Callable[[], None]
+        self.all_futures = []            # type: T.List[asyncio.Future]
+
+    def stdout_lines(self, console_mode: ConsoleUser) -> T.AsyncIterator[str]:
+        q = asyncio.Queue()              # type: asyncio.Queue[T.Optional[str]]
+        decode_coro = read_decode_lines(self._process.stdout, q, console_mode)
+        self.stdo_task = asyncio.ensure_future(decode_coro)
+        return queue_iter(q)
+
+    def communicate(self, console_mode: ConsoleUser) -> T.Tuple[T.Optional[T.Awaitable[str]],
+                                                                T.Optional[T.Awaitable[str]]]:
+        # asyncio.ensure_future ensures that printing can
+        # run in the background, even before it is awaited
+        if self.stdo_task is None and self.stdout is not None:
+            decode_coro = read_decode(self._process.stdout, console_mode)
+            self.stdo_task = asyncio.ensure_future(decode_coro)
+            self.all_futures.append(self.stdo_task)
+        if self.stderr is not None and self.stderr != asyncio.subprocess.STDOUT:
+            decode_coro = read_decode(self._process.stderr, console_mode)
+            self.stde_task = asyncio.ensure_future(decode_coro)
+            self.all_futures.append(self.stde_task)
+
+        return self.stdo_task, self.stde_task
+
+    async def _kill(self) -> T.Optional[str]:
+        # Python does not provide multiplatform support for
+        # killing a process and all its children so we need
+        # to roll our own.
+        p = self._process
+        try:
+            if is_windows():
+                subprocess.run(['taskkill', '/F', '/T', '/PID', str(p.pid)])
+            else:
+                # Send a termination signal to the process group that setsid()
+                # created - giving it a chance to perform any cleanup.
+                os.killpg(p.pid, signal.SIGTERM)
+
+                # Make sure the termination signal actually kills the process
+                # group, otherwise retry with a SIGKILL.
+                await try_wait_one(p.wait(), timeout=0.5)
+                if p.returncode is not None:
+                    return None
 
-class SingleTestRunner:
+                os.killpg(p.pid, signal.SIGKILL)
 
-    def __init__(self, test: 'TestSerialisation', test_env: T.Dict[str, str],
-                 env: T.Dict[str, str], options: argparse.Namespace):
-        self.test = test
-        self.test_env = test_env
-        self.env = env
-        self.options = options
+            await try_wait_one(p.wait(), timeout=1)
+            if p.returncode is not None:
+                return None
+
+            # An earlier kill attempt has not worked for whatever reason.
+            # Try to kill it one last time with a direct call.
+            # If the process has spawned children, they will remain around.
+            p.kill()
+            await try_wait_one(p.wait(), timeout=1)
+            if p.returncode is not None:
+                return None
+            return 'Test process could not be killed.'
+        except ProcessLookupError:
+            # Sometimes (e.g. with Wine) this happens.  There's nothing
+            # we can do, probably the process already died so just wait
+            # for the event loop to pick that up.
+            await p.wait()
+            return None
+        finally:
+            if self.stdo_task:
+                self.stdo_task.cancel()
+            if self.stde_task:
+                self.stde_task.cancel()
+
+    async def wait(self, timeout: T.Optional[int]) -> T.Tuple[int, TestResult, T.Optional[str]]:
+        p = self._process
+        result = None
+        additional_error = None
 
-    def _get_cmd(self) -> T.Optional[T.List[str]]:
-        if self.test.fname[0].endswith('.jar'):
-            return ['java', '-jar'] + self.test.fname
-        elif not self.test.is_cross_built and run_with_mono(self.test.fname[0]):
-            return ['mono'] + self.test.fname
-        else:
-            if self.test.is_cross_built and self.test.needs_exe_wrapper:
-                if self.test.exe_runner is None:
-                    # Can not run test on cross compiled executable
-                    # because there is no execute wrapper.
-                    return None
-                else:
-                    if not self.test.exe_runner.found():
-                        msg = 'The exe_wrapper defined in the cross file {!r} was not ' \
-                              'found. Please check the command and/or add it to PATH.'
-                        raise TestException(msg.format(self.test.exe_runner.name))
-                    return self.test.exe_runner.get_command() + self.test.fname
-            else:
-                return self.test.fname
+        self.all_futures.append(asyncio.ensure_future(p.wait()))
+        try:
+            await complete_all(self.all_futures, timeout=timeout)
+        except asyncio.TimeoutError:
+            additional_error = await self._kill()
+            result = TestResult.TIMEOUT
+        except asyncio.CancelledError:
+            # The main loop must have seen Ctrl-C.
+            additional_error = await self._kill()
+            result = TestResult.INTERRUPT
+        finally:
+            if self.postwait_fn:
+                self.postwait_fn()
 
-    def run(self) -> TestRun:
-        cmd = self._get_cmd()
-        if cmd is None:
-            skip_stdout = 'Not run because can not execute cross compiled binaries.'
-            return TestRun(self.test, self.test_env, TestResult.SKIP, GNU_SKIP_RETURNCODE, time.time(), 0.0, skip_stdout, None, None)
-        else:
-            wrap = TestHarness.get_wrapper(self.options)
-            if self.options.gdb:
-                self.test.timeout = None
-            return self._run_cmd(wrap + cmd + self.test.cmd_args + self.options.test_args)
+        return p.returncode or 0, result, additional_error
 
-    def _run_cmd(self, cmd: T.List[str]) -> TestRun:
-        starttime = time.time()
+class SingleTestRunner:
+
+    def __init__(self, test: TestSerialisation, env: T.Dict[str, str], name: str,
+                 options: argparse.Namespace):
+        self.test = test
+        self.options = options
+        self.cmd = self._get_cmd()
 
-        if len(self.test.extra_paths) > 0:
-            self.env['PATH'] = os.pathsep.join(self.test.extra_paths + ['']) + self.env['PATH']
+        if self.cmd and self.test.extra_paths:
+            env['PATH'] = os.pathsep.join(self.test.extra_paths + ['']) + env['PATH']
             winecmd = []
-            for c in cmd:
+            for c in self.cmd:
                 winecmd.append(c)
                 if os.path.basename(c).startswith('wine'):
-                    self.env['WINEPATH'] = get_wine_shortpath(
+                    env['WINEPATH'] = get_wine_shortpath(
                         winecmd,
-                        ['Z:' + p for p in self.test.extra_paths] + self.env.get('WINEPATH', '').split(';')
+                        ['Z:' + p for p in self.test.extra_paths] + env.get('WINEPATH', '').split(';')
                     )
                     break
 
@@ -513,17 +1322,81 @@
         # it ourselves. We do this unconditionally for regular tests
         # because it is extremely useful to have.
         # Setting MALLOC_PERTURB_="0" will completely disable this feature.
-        if ('MALLOC_PERTURB_' not in self.env or not self.env['MALLOC_PERTURB_']) and not self.options.benchmark:
-            self.env['MALLOC_PERTURB_'] = str(random.randint(1, 255))
+        if ('MALLOC_PERTURB_' not in env or not env['MALLOC_PERTURB_']) and not options.benchmark:
+            env['MALLOC_PERTURB_'] = str(random.randint(1, 255))
+
+        if self.options.gdb or self.test.timeout is None or self.test.timeout <= 0:
+            timeout = None
+        elif self.options.timeout_multiplier is None:
+            timeout = self.test.timeout
+        elif self.options.timeout_multiplier <= 0:
+            timeout = None
+        else:
+            timeout = self.test.timeout * self.options.timeout_multiplier
+
+        is_parallel = test.is_parallel and self.options.num_processes > 1 and not self.options.gdb
+        self.runobj = TestRun(test, env, name, timeout, is_parallel)
 
-        stdout = None
-        stderr = None
-        if not self.options.verbose:
-            stdout = tempfile.TemporaryFile("wb+")
-            stderr = tempfile.TemporaryFile("wb+") if self.options.split else stdout
-        if self.test.protocol == 'tap' and stderr is stdout:
-            stdout = tempfile.TemporaryFile("wb+")
+        if self.options.gdb:
+            self.console_mode = ConsoleUser.GDB
+        elif self.options.verbose and not is_parallel and not self.runobj.needs_parsing:
+            self.console_mode = ConsoleUser.STDOUT
+        else:
+            self.console_mode = ConsoleUser.LOGGER
 
+    def _get_test_cmd(self) -> T.Optional[T.List[str]]:
+        if self.test.fname[0].endswith('.jar'):
+            return ['java', '-jar'] + self.test.fname
+        elif not self.test.is_cross_built and run_with_mono(self.test.fname[0]):
+            return ['mono'] + self.test.fname
+        elif self.test.cmd_is_built and self.test.is_cross_built and self.test.needs_exe_wrapper:
+            if self.test.exe_wrapper is None:
+                # Can not run test on cross compiled executable
+                # because there is no execute wrapper.
+                return None
+            elif self.test.cmd_is_built:
+                # If the command is not built (ie, its a python script),
+                # then we don't check for the exe-wrapper
+                if not self.test.exe_wrapper.found():
+                    msg = ('The exe_wrapper defined in the cross file {!r} was not '
+                           'found. Please check the command and/or add it to PATH.')
+                    raise TestException(msg.format(self.test.exe_wrapper.name))
+                return self.test.exe_wrapper.get_command() + self.test.fname
+        return self.test.fname
+
+    def _get_cmd(self) -> T.Optional[T.List[str]]:
+        test_cmd = self._get_test_cmd()
+        if not test_cmd:
+            return None
+        return TestHarness.get_wrapper(self.options) + test_cmd
+
+    @property
+    def is_parallel(self) -> bool:
+        return self.runobj.is_parallel
+
+    @property
+    def visible_name(self) -> str:
+        return self.runobj.name
+
+    @property
+    def timeout(self) -> T.Optional[int]:
+        return self.runobj.timeout
+
+    async def run(self, harness: 'TestHarness') -> TestRun:
+        if self.cmd is None:
+            skip_stdout = 'Not run because can not execute cross compiled binaries.'
+            harness.log_start_test(self.runobj)
+            self.runobj.complete_skip(skip_stdout)
+        else:
+            cmd = self.cmd + self.test.cmd_args + self.options.test_args
+            self.runobj.start(cmd)
+            harness.log_start_test(self.runobj)
+            await self._run_cmd(harness, cmd)
+        return self.runobj
+
+    async def _run_subprocess(self, args: T.List[str], *,
+                              stdout: int, stderr: int,
+                              env: T.Dict[str, str], cwd: T.Optional[str]) -> TestSubprocess:
         # Let gdb handle ^C instead of us
         if self.options.gdb:
             previous_sigint_handler = signal.getsignal(signal.SIGINT)
@@ -539,145 +1412,145 @@
                 # We don't want setsid() in gdb because gdb needs the
                 # terminal in order to handle ^C and not show tcsetpgrp()
                 # errors avoid not being able to use the terminal.
-                os.setsid()  # type: ignore
+                os.setsid()
 
-        p = subprocess.Popen(cmd,
-                             stdout=stdout,
-                             stderr=stderr,
-                             env=self.env,
-                             cwd=self.test.workdir,
-                             preexec_fn=preexec_fn if not is_windows() else None)
-        timed_out = False
-        kill_test = False
-        if self.test.timeout is None:
-            timeout = None
-        elif self.options.timeout_multiplier is not None:
-            timeout = self.test.timeout * self.options.timeout_multiplier
-        else:
-            timeout = self.test.timeout
-        try:
-            p.communicate(timeout=timeout)
-        except subprocess.TimeoutExpired:
-            if self.options.verbose:
-                print('{} time out (After {} seconds)'.format(self.test.name, timeout))
-            timed_out = True
-        except KeyboardInterrupt:
-            mlog.warning('CTRL-C detected while running %s' % (self.test.name))
-            kill_test = True
-        finally:
+        def postwait_fn() -> None:
             if self.options.gdb:
                 # Let us accept ^C again
                 signal.signal(signal.SIGINT, previous_sigint_handler)
 
-        additional_error = None
-
-        if kill_test or timed_out:
-            # Python does not provide multiplatform support for
-            # killing a process and all its children so we need
-            # to roll our own.
-            if is_windows():
-                subprocess.run(['taskkill', '/F', '/T', '/PID', str(p.pid)])
-            else:
-                try:
-                    # Kill the process group that setsid() created.
-                    os.killpg(p.pid, signal.SIGKILL)  # type: ignore
-                except ProcessLookupError:
-                    # Sometimes (e.g. with Wine) this happens.
-                    # There's nothing we can do (maybe the process
-                    # already died) so carry on.
-                    pass
-            try:
-                p.communicate(timeout=1)
-            except subprocess.TimeoutExpired:
-                # An earlier kill attempt has not worked for whatever reason.
-                # Try to kill it one last time with a direct call.
-                # If the process has spawned children, they will remain around.
-                p.kill()
-                try:
-                    p.communicate(timeout=1)
-                except subprocess.TimeoutExpired:
-                    additional_error = 'Test process could not be killed.'
-            except ValueError:
-                additional_error = 'Could not read output. Maybe the process has redirected its stdout/stderr?'
-        endtime = time.time()
-        duration = endtime - starttime
-        if additional_error is None:
-            if stdout is None:
-                stdo = ''
-            else:
-                stdout.seek(0)
-                stdo = decode(stdout.read())
-            if stderr is None or stderr is stdout:
-                stde = ''
-            else:
-                stderr.seek(0)
-                stde = decode(stderr.read())
+        p = await asyncio.create_subprocess_exec(*args,
+                                                 stdout=stdout,
+                                                 stderr=stderr,
+                                                 env=env,
+                                                 cwd=cwd,
+                                                 preexec_fn=preexec_fn if not is_windows() else None)
+        return TestSubprocess(p, stdout=stdout, stderr=stderr,
+                              postwait_fn=postwait_fn if not is_windows() else None)
+
+    async def _run_cmd(self, harness: 'TestHarness', cmd: T.List[str]) -> None:
+        if self.console_mode is ConsoleUser.GDB:
+            stdout = None
+            stderr = None
         else:
-            stdo = ""
-            stde = additional_error
-        if timed_out:
-            return TestRun(self.test, self.test_env, TestResult.TIMEOUT, p.returncode, starttime, duration, stdo, stde, cmd)
-        else:
-            if self.test.protocol == 'exitcode':
-                return TestRun.make_exitcode(self.test, self.test_env, p.returncode, starttime, duration, stdo, stde, cmd)
-            else:
-                if self.options.verbose:
-                    print(stdo, end='')
-                return TestRun.make_tap(self.test, self.test_env, p.returncode, starttime, duration, stdo, stde, cmd)
+            stdout = asyncio.subprocess.PIPE
+            stderr = asyncio.subprocess.STDOUT \
+                if not self.options.split and not self.runobj.needs_parsing \
+                else asyncio.subprocess.PIPE
+
+        extra_cmd = []  # type: T.List[str]
+        if self.test.protocol is TestProtocol.GTEST:
+            gtestname = self.test.name
+            if self.test.workdir:
+                gtestname = os.path.join(self.test.workdir, self.test.name)
+            extra_cmd.append(f'--gtest_output=xml:{gtestname}.xml')
+
+        p = await self._run_subprocess(cmd + extra_cmd,
+                                       stdout=stdout,
+                                       stderr=stderr,
+                                       env=self.runobj.env,
+                                       cwd=self.test.workdir)
+
+        parse_task = None
+        if self.runobj.needs_parsing:
+            parse_coro = self.runobj.parse(harness, p.stdout_lines(self.console_mode))
+            parse_task = asyncio.ensure_future(parse_coro)
+
+        stdo_task, stde_task = p.communicate(self.console_mode)
+        returncode, result, additional_error = await p.wait(self.runobj.timeout)
+
+        if parse_task is not None:
+            res, error = await parse_task
+            if error:
+                additional_error = join_lines(additional_error, error)
+            result = result or res
+
+        stdo = await stdo_task if stdo_task else ''
+        stde = await stde_task if stde_task else ''
+        stde = join_lines(stde, additional_error)
+        self.runobj.complete(returncode, result, stdo, stde)
 
 
 class TestHarness:
     def __init__(self, options: argparse.Namespace):
         self.options = options
-        self.collected_logs = []  # type: T.List[str]
+        self.collected_failures = []  # type: T.List[TestRun]
         self.fail_count = 0
         self.expectedfail_count = 0
         self.unexpectedpass_count = 0
         self.success_count = 0
         self.skip_count = 0
         self.timeout_count = 0
+        self.test_count = 0
+        self.name_max_len = 0
         self.is_run = False
-        self.tests = None
-        self.logfilename = None   # type: T.Optional[str]
-        self.logfile = None       # type: T.Optional[T.TextIO]
-        self.jsonlogfile = None   # type: T.Optional[T.TextIO]
-        if self.options.benchmark:
-            self.tests = load_benchmarks(options.wd)
-        else:
-            self.tests = load_tests(options.wd)
+        self.loggers = []         # type: T.List[TestLogger]
+        self.loggers.append(ConsoleLogger())
+        self.need_console = False
+
+        self.logfile_base = None  # type: T.Optional[str]
+        if self.options.logbase and not self.options.gdb:
+            namebase = None
+            self.logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase)
+
+            if self.options.wrapper:
+                namebase = os.path.basename(self.get_wrapper(self.options)[0])
+            elif self.options.setup:
+                namebase = self.options.setup.replace(":", "_")
+
+            if namebase:
+                self.logfile_base += '-' + namebase.replace(' ', '_')
+
+        startdir = os.getcwd()
+        try:
+            os.chdir(self.options.wd)
+            self.build_data = build.load(os.getcwd())
+            if not self.options.setup:
+                self.options.setup = self.build_data.test_setup_default_name
+            if self.options.benchmark:
+                self.tests = self.load_tests('meson_benchmark_setup.dat')
+            else:
+                self.tests = self.load_tests('meson_test_setup.dat')
+        finally:
+            os.chdir(startdir)
+
         ss = set()
         for t in self.tests:
             for s in t.suite:
                 ss.add(s)
         self.suites = list(ss)
 
-    def __del__(self) -> None:
-        self.close_logfiles()
+    def load_tests(self, file_name: str) -> T.List[TestSerialisation]:
+        datafile = Path('meson-private') / file_name
+        if not datafile.is_file():
+            raise TestException(f'Directory {self.options.wd!r} does not seem to be a Meson build directory.')
+        with datafile.open('rb') as f:
+            objs = check_testdata(pickle.load(f))
+        return objs
 
-    def __enter__(self):
+    def __enter__(self) -> 'TestHarness':
         return self
 
-    def __exit__(self, exc_type, exc_value, traceback) -> None:
+    def __exit__(self, exc_type: T.Any, exc_value: T.Any, traceback: T.Any) -> None:
         self.close_logfiles()
 
     def close_logfiles(self) -> None:
-        if self.logfile:
-            self.logfile.close()
-            self.logfile = None
-        if self.jsonlogfile:
-            self.jsonlogfile.close()
-            self.jsonlogfile = None
-
-    def merge_suite_options(self, options: argparse.Namespace, test: 'TestSerialisation') -> T.Dict[str, str]:
-        if ':' in options.setup:
-            if options.setup not in self.build_data.test_setups:
-                sys.exit("Unknown test setup '%s'." % options.setup)
-            current = self.build_data.test_setups[options.setup]
+        for l in self.loggers:
+            l.close()
+
+    def get_test_setup(self, test: T.Optional[TestSerialisation]) -> build.TestSetup:
+        if ':' in self.options.setup:
+            if self.options.setup not in self.build_data.test_setups:
+                sys.exit(f"Unknown test setup '{self.options.setup}'.")
+            return self.build_data.test_setups[self.options.setup]
         else:
-            full_name = test.project_name + ":" + options.setup
+            full_name = test.project_name + ":" + self.options.setup
             if full_name not in self.build_data.test_setups:
-                sys.exit("Test setup '%s' not found from project '%s'." % (options.setup, test.project_name))
-            current = self.build_data.test_setups[full_name]
+                sys.exit(f"Test setup '{self.options.setup}' not found from project '{test.project_name}'.")
+            return self.build_data.test_setups[full_name]
+
+    def merge_setup_options(self, options: argparse.Namespace, test: TestSerialisation) -> T.Dict[str, str]:
+        current = self.get_test_setup(test)
         if not options.gdb:
             options.gdb = current.gdb
         if options.gdb:
@@ -686,23 +1559,25 @@
             options.timeout_multiplier = current.timeout_multiplier
     #    if options.env is None:
     #        options.env = current.env # FIXME, should probably merge options here.
-        if options.wrapper is not None and current.exe_wrapper is not None:
-            sys.exit('Conflict: both test setup and command line specify an exe wrapper.')
         if options.wrapper is None:
             options.wrapper = current.exe_wrapper
+        elif current.exe_wrapper:
+            sys.exit('Conflict: both test setup and command line specify an exe wrapper.')
         return current.env.get_env(os.environ.copy())
 
-    def get_test_runner(self, test: 'TestSerialisation') -> SingleTestRunner:
+    def get_test_runner(self, test: TestSerialisation) -> SingleTestRunner:
+        name = self.get_pretty_suite(test)
         options = deepcopy(self.options)
-        if not options.setup:
-            options.setup = self.build_data.test_setup_default_name
-        if options.setup:
-            env = self.merge_suite_options(options, test)
+        if self.options.setup:
+            env = self.merge_setup_options(options, test)
         else:
             env = os.environ.copy()
         test_env = test.env.get_env(env)
         env.update(test_env)
-        return SingleTestRunner(test, test_env, env, options)
+        if (test.is_cross_built and test.needs_exe_wrapper and
+                test.exe_wrapper and test.exe_wrapper.found()):
+            env['MESON_EXE_WRAPPER'] = join_args(test.exe_wrapper.get_command())
+        return SingleTestRunner(test, env, name, options)
 
     def process_test_result(self, result: TestRun) -> None:
         if result.res is TestResult.TIMEOUT:
@@ -711,83 +1586,71 @@
             self.skip_count += 1
         elif result.res is TestResult.OK:
             self.success_count += 1
-        elif result.res is TestResult.FAIL or result.res is TestResult.ERROR:
+        elif result.res in {TestResult.FAIL, TestResult.ERROR, TestResult.INTERRUPT}:
             self.fail_count += 1
         elif result.res is TestResult.EXPECTEDFAIL:
             self.expectedfail_count += 1
         elif result.res is TestResult.UNEXPECTEDPASS:
             self.unexpectedpass_count += 1
         else:
-            sys.exit('Unknown test result encountered: {}'.format(result.res))
+            sys.exit(f'Unknown test result encountered: {result.res}')
 
-    def print_stats(self, numlen: int, tests: T.List['TestSerialisation'],
-                    name: str, result: TestRun, i: int) -> None:
-        startpad = ' ' * (numlen - len('%d' % (i + 1)))
-        num = '%s%d/%d' % (startpad, i + 1, len(tests))
-        padding1 = ' ' * (38 - len(name))
-        padding2 = ' ' * (8 - len(result.res.value))
-        status = ''
-
-        if result.res is TestResult.FAIL:
-            status = returncode_to_status(result.returncode)
-        result_str = '%s %s  %s%s%s%5.2f s %s' % \
-            (num, name, padding1, result.res.value, padding2, result.duration,
-             status)
-        ok_statuses = (TestResult.OK, TestResult.EXPECTEDFAIL)
-        bad_statuses = (TestResult.FAIL, TestResult.TIMEOUT, TestResult.UNEXPECTEDPASS,
-                        TestResult.ERROR)
-        if not self.options.quiet or result.res not in ok_statuses:
-            if result.res not in ok_statuses and mlog.colorize_console:
-                if result.res in bad_statuses:
-                    decorator = mlog.red
-                elif result.res is TestResult.SKIP:
-                    decorator = mlog.yellow
-                else:
-                    sys.exit('Unreachable code was ... well ... reached.')
-                print(decorator(result_str).get_text(True))
-            else:
-                print(result_str)
-        result_str += "\n\n" + result.get_log()
-        if result.res in bad_statuses:
-            if self.options.print_errorlogs:
-                self.collected_logs.append(result_str)
-        if self.logfile:
-            self.logfile.write(result_str)
-        if self.jsonlogfile:
-            write_json_log(self.jsonlogfile, name, result)
-
-    def print_summary(self) -> None:
-        msg = '''
-Ok:                 %4d
-Expected Fail:      %4d
-Fail:               %4d
-Unexpected Pass:    %4d
-Skipped:            %4d
-Timeout:            %4d
-''' % (self.success_count, self.expectedfail_count, self.fail_count,
-            self.unexpectedpass_count, self.skip_count, self.timeout_count)
-        print(msg)
-        if self.logfile:
-            self.logfile.write(msg)
-
-    def print_collected_logs(self) -> None:
-        if len(self.collected_logs) > 0:
-            if len(self.collected_logs) > 10:
-                print('\nThe output from 10 first failed tests:\n')
-            else:
-                print('\nThe output from the failed tests:\n')
-            for log in self.collected_logs[:10]:
-                lines = log.splitlines()
-                if len(lines) > 104:
-                    print('\n'.join(lines[0:4]))
-                    print('--- Listing only the last 100 lines from a long log. ---')
-                    lines = lines[-100:]
-                for line in lines:
-                    try:
-                        print(line)
-                    except UnicodeEncodeError:
-                        line = line.encode('ascii', errors='replace').decode()
-                        print(line)
+        if result.res.is_bad():
+            self.collected_failures.append(result)
+        for l in self.loggers:
+            l.log(self, result)
+
+    @property
+    def numlen(self) -> int:
+        return len(str(self.test_count))
+
+    @property
+    def max_left_width(self) -> int:
+        return 2 * self.numlen + 2
+
+    def format(self, result: TestRun, colorize: bool,
+               max_left_width: int = 0,
+               prefix: str = '',
+               left: T.Optional[str] = None,
+               middle: T.Optional[str] = None,
+               right: T.Optional[str] = None) -> str:
+
+        if left is None:
+            left = '{num:{numlen}}/{testcount} '.format(
+                numlen=self.numlen,
+                num=result.num,
+                testcount=self.test_count)
+
+        # A non-default max_left_width lets the logger print more stuff before the
+        # name, while ensuring that the rightmost columns remain aligned.
+        max_left_width = max(max_left_width, self.max_left_width)
+
+        if middle is None:
+            middle = result.name
+        extra_mid_width = max_left_width + self.name_max_len + 1 - uniwidth(middle) - uniwidth(left) - uniwidth(prefix)
+        middle += ' ' * max(1, extra_mid_width)
+
+        if right is None:
+            right = '{res} {dur:{durlen}.2f}s'.format(
+                res=result.res.get_text(colorize),
+                dur=result.duration,
+                durlen=self.duration_max_len + 3)
+            detail = result.detail
+            if detail:
+                right += '   ' + detail
+        return prefix + left + middle + right
+
+    def summary(self) -> str:
+        return textwrap.dedent('''
+
+            Ok:                 {:<4}
+            Expected Fail:      {:<4}
+            Fail:               {:<4}
+            Unexpected Pass:    {:<4}
+            Skipped:            {:<4}
+            Timeout:            {:<4}
+            ''').format(self.success_count, self.expectedfail_count, self.fail_count,
+                        self.unexpectedpass_count, self.skip_count, self.timeout_count)
 
     def total_failure_count(self) -> int:
         return self.fail_count + self.unexpectedpass_count + self.timeout_count
@@ -799,20 +1662,45 @@
         tests = self.get_tests()
         if not tests:
             return 0
-        self.run_tests(tests)
+        if not self.options.no_rebuild and not rebuild_deps(self.options.wd, tests):
+            # We return 125 here in case the build failed.
+            # The reason is that exit code 125 tells `git bisect run` that the current
+            # commit should be skipped.  Thus users can directly use `meson test` to
+            # bisect without needing to handle the does-not-build case separately in a
+            # wrapper script.
+            sys.exit(125)
+
+        self.name_max_len = max(uniwidth(self.get_pretty_suite(test)) for test in tests)
+        startdir = os.getcwd()
+        try:
+            os.chdir(self.options.wd)
+            runners = []             # type: T.List[SingleTestRunner]
+            for i in range(self.options.repeat):
+                runners.extend(self.get_test_runner(test) for test in tests)
+                if i == 0:
+                    self.duration_max_len = max(len(str(int(runner.timeout or 99)))
+                                                for runner in runners)
+                    # Disable the progress report if it gets in the way
+                    self.need_console = any(runner.console_mode is not ConsoleUser.LOGGER
+                                            for runner in runners)
+
+            self.test_count = len(runners)
+            self.run_tests(runners)
+        finally:
+            os.chdir(startdir)
         return self.total_failure_count()
 
     @staticmethod
     def split_suite_string(suite: str) -> T.Tuple[str, str]:
         if ':' in suite:
-            # mypy can't figure out that str.split(n, 1) will return a list of
-            # length 2, so we have to help it.
-            return T.cast(T.Tuple[str, str], tuple(suite.split(':', 1)))
+            split = suite.split(':', 1)
+            assert len(split) == 2
+            return split[0], split[1]
         else:
             return suite, ""
 
     @staticmethod
-    def test_in_suites(test: 'TestSerialisation', suites: T.List[str]) -> bool:
+    def test_in_suites(test: TestSerialisation, suites: T.List[str]) -> bool:
         for suite in suites:
             (prj_match, st_match) = TestHarness.split_suite_string(suite)
             for prjst in test.suite:
@@ -843,27 +1731,52 @@
                 return True
         return False
 
-    def test_suitable(self, test: 'TestSerialisation') -> bool:
-        return ((not self.options.include_suites or
-                TestHarness.test_in_suites(test, self.options.include_suites)) and not
-                TestHarness.test_in_suites(test, self.options.exclude_suites))
+    def test_suitable(self, test: TestSerialisation) -> bool:
+        if TestHarness.test_in_suites(test, self.options.exclude_suites):
+            return False
+
+        if self.options.include_suites:
+            # Both force inclusion (overriding add_test_setup) and exclude
+            # everything else
+            return TestHarness.test_in_suites(test, self.options.include_suites)
+
+        if self.options.setup:
+            setup = self.get_test_setup(test)
+            if TestHarness.test_in_suites(test, setup.exclude_suites):
+                return False
+
+        return True
+
+    def tests_from_args(self, tests: T.List[TestSerialisation]) -> T.Generator[TestSerialisation, None, None]:
+        '''
+        Allow specifying test names like "meson test foo1 foo2", where test('foo1', ...)
+
+        Also support specifying the subproject to run tests from like
+        "meson test subproj:" (all tests inside subproj) or "meson test subproj:foo1"
+        to run foo1 inside subproj. Coincidentally also "meson test :foo1" to
+        run all tests with that name across all subprojects, which is
+        identical to "meson test foo1"
+        '''
+        for arg in self.options.args:
+            if ':' in arg:
+                subproj, name = arg.split(':', maxsplit=1)
+            else:
+                subproj, name = '', arg
+            for t in tests:
+                if subproj and t.project_name != subproj:
+                    continue
+                if name and t.name != name:
+                    continue
+                yield t
 
-    def get_tests(self) -> T.List['TestSerialisation']:
+    def get_tests(self) -> T.List[TestSerialisation]:
         if not self.tests:
             print('No tests defined.')
             return []
 
-        if len(self.options.include_suites) or len(self.options.exclude_suites):
-            tests = []
-            for tst in self.tests:
-                if self.test_suitable(tst):
-                    tests.append(tst)
-        else:
-            tests = self.tests
-
-        # allow specifying test names like "meson test foo1 foo2", where test('foo1', ...)
+        tests = [t for t in self.tests if self.test_suitable(t)]
         if self.options.args:
-            tests = [t for t in tests if t.name in self.options.args]
+            tests = list(self.tests_from_args(tests))
 
         if not tests:
             print('No suitable tests defined.')
@@ -871,30 +1784,17 @@
 
         return tests
 
-    def open_log_files(self) -> None:
-        if not self.options.logbase or self.options.verbose:
-            return
+    def flush_logfiles(self) -> None:
+        for l in self.loggers:
+            l.flush()
 
-        namebase = None
-        logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase)
-
-        if self.options.wrapper:
-            namebase = os.path.basename(self.get_wrapper(self.options)[0])
-        elif self.options.setup:
-            namebase = self.options.setup.replace(":", "_")
-
-        if namebase:
-            logfile_base += '-' + namebase.replace(' ', '_')
-        self.logfilename = logfile_base + '.txt'
-        self.jsonlogfilename = logfile_base + '.json'
-
-        self.jsonlogfile = open(self.jsonlogfilename, 'w', encoding='utf-8', errors='replace')
-        self.logfile = open(self.logfilename, 'w', encoding='utf-8', errors='surrogateescape')
+    def open_logfiles(self) -> None:
+        if not self.logfile_base:
+            return
 
-        self.logfile.write('Log of Meson test suite run on %s\n\n'
-                           % datetime.datetime.now().isoformat())
-        inherit_env = env_tuple_to_str(os.environ.items())
-        self.logfile.write('Inherited environment: {}\n\n'.format(inherit_env))
+        self.loggers.append(JunitBuilder(self.logfile_base + '.junit.xml'))
+        self.loggers.append(JsonLogfileBuilder(self.logfile_base + '.json'))
+        self.loggers.append(TextLogfileBuilder(self.logfile_base + '.txt', errors='surrogateescape'))
 
     @staticmethod
     def get_wrapper(options: argparse.Namespace) -> T.List[str]:
@@ -909,77 +1809,125 @@
             wrap += options.wrapper
         return wrap
 
-    def get_pretty_suite(self, test: 'TestSerialisation') -> str:
+    def get_pretty_suite(self, test: TestSerialisation) -> str:
         if len(self.suites) > 1 and test.suite:
             rv = TestHarness.split_suite_string(test.suite[0])[0]
             s = "+".join(TestHarness.split_suite_string(s)[1] for s in test.suite)
-            if len(s):
+            if s:
                 rv += ":"
             return rv + s + " / " + test.name
         else:
             return test.name
 
-    def run_tests(self, tests: T.List['TestSerialisation']) -> None:
-        executor = None
-        futures = []  # type: T.List[T.Tuple[conc.Future[TestRun], int, T.List[TestSerialisation], str, int]]
-        numlen = len('%d' % len(tests))
-        self.open_log_files()
-        startdir = os.getcwd()
-        if self.options.wd:
-            os.chdir(self.options.wd)
-        self.build_data = build.load(os.getcwd())
+    def run_tests(self, runners: T.List[SingleTestRunner]) -> None:
+        try:
+            self.open_logfiles()
+            # Replace with asyncio.run once we can require Python 3.7
+            loop = asyncio.get_event_loop()
+            loop.run_until_complete(self._run_tests(runners))
+        finally:
+            self.close_logfiles()
 
+    def log_subtest(self, test: TestRun, s: str, res: TestResult) -> None:
+        for l in self.loggers:
+            l.log_subtest(self, test, s, res)
+
+    def log_start_test(self, test: TestRun) -> None:
+        for l in self.loggers:
+            l.start_test(self, test)
+
+    async def _run_tests(self, runners: T.List[SingleTestRunner]) -> None:
+        semaphore = asyncio.Semaphore(self.options.num_processes)
+        futures = deque()  # type: T.Deque[asyncio.Future]
+        running_tests = dict() # type: T.Dict[asyncio.Future, str]
+        interrupted = False
+        ctrlc_times = deque(maxlen=MAX_CTRLC) # type: T.Deque[float]
+
+        async def run_test(test: SingleTestRunner) -> None:
+            async with semaphore:
+                if interrupted or (self.options.repeat > 1 and self.fail_count):
+                    return
+                res = await test.run(self)
+                self.process_test_result(res)
+
+        def test_done(f: asyncio.Future) -> None:
+            if not f.cancelled():
+                f.result()
+            futures.remove(f)
+            try:
+                del running_tests[f]
+            except KeyError:
+                pass
+
+        def cancel_one_test(warn: bool) -> None:
+            future = futures.popleft()
+            futures.append(future)
+            if warn:
+                self.flush_logfiles()
+                mlog.warning('CTRL-C detected, interrupting {}'.format(running_tests[future]))
+            del running_tests[future]
+            future.cancel()
+
+        def cancel_all_tests() -> None:
+            nonlocal interrupted
+            interrupted = True
+            while running_tests:
+                cancel_one_test(False)
+
+        def sigterm_handler() -> None:
+            if interrupted:
+                return
+            self.flush_logfiles()
+            mlog.warning('Received SIGTERM, exiting')
+            cancel_all_tests()
+
+        def sigint_handler() -> None:
+            # We always pick the longest-running future that has not been cancelled
+            # If all the tests have been CTRL-C'ed, just stop
+            nonlocal interrupted
+            if interrupted:
+                return
+            ctrlc_times.append(asyncio.get_event_loop().time())
+            if len(ctrlc_times) == MAX_CTRLC and ctrlc_times[-1] - ctrlc_times[0] < 1:
+                self.flush_logfiles()
+                mlog.warning('CTRL-C detected, exiting')
+                cancel_all_tests()
+            elif running_tests:
+                cancel_one_test(True)
+            else:
+                self.flush_logfiles()
+                mlog.warning('CTRL-C detected, exiting')
+                interrupted = True
+
+        for l in self.loggers:
+            l.start(self)
+
+        if sys.platform != 'win32':
+            if os.getpgid(0) == os.getpid():
+                asyncio.get_event_loop().add_signal_handler(signal.SIGINT, sigint_handler)
+            else:
+                asyncio.get_event_loop().add_signal_handler(signal.SIGINT, sigterm_handler)
+            asyncio.get_event_loop().add_signal_handler(signal.SIGTERM, sigterm_handler)
         try:
-            for _ in range(self.options.repeat):
-                for i, test in enumerate(tests):
-                    visible_name = self.get_pretty_suite(test)
-                    single_test = self.get_test_runner(test)
-
-                    if not test.is_parallel or self.options.num_processes == 1 or single_test.options.gdb:
-                        self.drain_futures(futures)
-                        futures = []
-                        res = single_test.run()
-                        self.process_test_result(res)
-                        self.print_stats(numlen, tests, visible_name, res, i)
-                    else:
-                        if not executor:
-                            executor = conc.ThreadPoolExecutor(max_workers=self.options.num_processes)
-                        f = executor.submit(single_test.run)
-                        futures.append((f, numlen, tests, visible_name, i))
-                    if self.options.repeat > 1 and self.fail_count:
-                        break
+            for runner in runners:
+                if not runner.is_parallel:
+                    await complete_all(futures)
+                future = asyncio.ensure_future(run_test(runner))
+                futures.append(future)
+                running_tests[future] = runner.visible_name
+                future.add_done_callback(test_done)
+                if not runner.is_parallel:
+                    await complete(future)
                 if self.options.repeat > 1 and self.fail_count:
                     break
 
-            self.drain_futures(futures)
-            self.print_summary()
-            self.print_collected_logs()
-
-            if self.logfilename:
-                print('Full log written to %s' % self.logfilename)
+            await complete_all(futures)
         finally:
-            os.chdir(startdir)
-
-    def drain_futures(self, futures: T.List[T.Tuple['conc.Future[TestRun]', int, T.List['TestSerialisation'], str, int]]) -> None:
-        for x in futures:
-            (result, numlen, tests, name, i) = x
-            if self.options.repeat > 1 and self.fail_count:
-                result.cancel()
-            if self.options.verbose:
-                result.result()
-            self.process_test_result(result.result())
-            self.print_stats(numlen, tests, name, result.result(), i)
-
-    def run_special(self) -> int:
-        '''Tests run by the user, usually something like "under gdb 1000 times".'''
-        if self.is_run:
-            raise RuntimeError('Can not use run_special after a full run.')
-        tests = self.get_tests()
-        if not tests:
-            return 0
-        self.run_tests(tests)
-        return self.total_failure_count()
-
+            if sys.platform != 'win32':
+                asyncio.get_event_loop().remove_signal_handler(signal.SIGINT)
+                asyncio.get_event_loop().remove_signal_handler(signal.SIGTERM)
+            for l in self.loggers:
+                await l.finish(self)
 
 def list_tests(th: TestHarness) -> bool:
     tests = th.get_tests()
@@ -987,7 +1935,13 @@
         print(th.get_pretty_suite(t))
     return not tests
 
-def rebuild_all(wd: str) -> bool:
+def rebuild_deps(wd: str, tests: T.List[TestSerialisation]) -> bool:
+    def convert_path_to_target(path: str) -> str:
+        path = os.path.relpath(path, wd)
+        if os.sep != '/':
+            path = path.replace(os.sep, '/')
+        return path
+
     if not (Path(wd) / 'build.ninja').is_file():
         print('Only ninja backend is supported to rebuild tests before running them.')
         return True
@@ -997,9 +1951,23 @@
         print("Can't find ninja, can't rebuild test.")
         return False
 
-    ret = subprocess.run([ninja, '-C', wd]).returncode
+    depends = set()            # type: T.Set[str]
+    targets = set()            # type: T.Set[str]
+    intro_targets = dict()     # type: T.Dict[str, T.List[str]]
+    for target in load_info_file(get_infodir(wd), kind='targets'):
+        intro_targets[target['id']] = [
+            convert_path_to_target(f)
+            for f in target['filename']]
+    for t in tests:
+        for d in t.depends:
+            if d in depends:
+                continue
+            depends.update(d)
+            targets.update(intro_targets[d])
+
+    ret = subprocess.run(ninja + ['-C', wd] + sorted(targets)).returncode
     if ret != 0:
-        print('Could not rebuild {}'.format(wd))
+        print(f'Could not rebuild {wd}')
         return False
 
     return True
@@ -1023,27 +1991,24 @@
     if options.wrapper:
         check_bin = options.wrapper[0]
 
+    if sys.platform == 'win32':
+        loop = asyncio.ProactorEventLoop()
+        asyncio.set_event_loop(loop)
+
     if check_bin is not None:
         exe = ExternalProgram(check_bin, silent=True)
         if not exe.found():
-            print('Could not find requested program: {!r}'.format(check_bin))
+            print(f'Could not find requested program: {check_bin!r}')
             return 1
-    options.wd = os.path.abspath(options.wd)
 
-    if not options.list and not options.no_rebuild:
-        if not rebuild_all(options.wd):
-            # We return 125 here in case the build failed.
-            # The reason is that exit code 125 tells `git bisect run` that the current commit should be skipped.
-            # Thus users can directly use `meson test` to bisect without needing to handle the does-not-build case separately in a wrapper script.
-            return 125
+    b = build.load(options.wd)
+    setup_vsenv(b.need_vsenv)
 
     with TestHarness(options) as th:
         try:
             if options.list:
                 return list_tests(th)
-            if not options.args:
-                return th.doit()
-            return th.run_special()
+            return th.doit()
         except TestException as e:
             print('Meson test encountered an error:\n')
             if os.environ.get('MESON_FORCE_BACKTRACE'):
diff -Nru meson-0.53.2/mesonbuild/munstable_coredata.py meson-0.61.2/mesonbuild/munstable_coredata.py
--- meson-0.53.2/mesonbuild/munstable_coredata.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/munstable_coredata.py	2021-11-02 19:58:07.000000000 +0000
@@ -14,7 +14,7 @@
 
 
 from . import coredata as cdata
-from .mesonlib import MachineChoice
+from .mesonlib import MachineChoice, OptionKey
 
 import os.path
 import pprint
@@ -59,7 +59,7 @@
     print('')
 
     coredata = cdata.load(options.builddir)
-    backend = coredata.get_builtin_option('backend')
+    backend = coredata.get_option(OptionKey('backend'))
     for k, v in sorted(coredata.__dict__.items()):
         if k in ('backend_options', 'base_options', 'builtins', 'compiler_options', 'user_options'):
             # use `meson configure` to view these
@@ -95,7 +95,7 @@
                 dump_compilers(v[for_machine])
         elif k == 'deps':
             def print_dep(dep_key, dep):
-                print('  ' + dep_key[0] + ": ")
+                print('  ' + dep_key[0][1] + ": ")
                 print('      compile args: ' + repr(dep.get_compile_args()))
                 print('      link args: ' + repr(dep.get_link_args()))
                 if dep.get_sources():
@@ -105,7 +105,7 @@
             for for_machine in iter(MachineChoice):
                 items_list = list(sorted(v[for_machine].items()))
                 if items_list:
-                    print('Cached dependencies for {} machine' % for_machine.get_lower_case_name())
+                    print(f'Cached dependencies for {for_machine.get_lower_case_name()} machine')
                     for dep_key, deps in items_list:
                         for dep in deps:
                             print_dep(dep_key, dep)
diff -Nru meson-0.53.2/mesonbuild/optinterpreter.py meson-0.61.2/mesonbuild/optinterpreter.py
--- meson-0.53.2/mesonbuild/optinterpreter.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/optinterpreter.py	2021-11-02 19:58:07.000000000 +0000
@@ -12,153 +12,81 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os, re
-import functools
+import re
 import typing as T
 
-from . import mparser
 from . import coredata
 from . import mesonlib
-from . import compilers
+from . import mparser
+from . import mlog
+from .interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo, permittedKwargs
+if T.TYPE_CHECKING:
+    from .interpreterbase import TV_func, TYPE_var, TYPE_kwargs
+    from typing_extensions import TypedDict
+    FuncOptionArgs = TypedDict('FuncOptionArgs', {
+        'type': str,
+        'description': str,
+        'yield': bool,
+        'choices': T.Optional[T.List[str]],
+        'value': object,
+        'min': T.Optional[int],
+        'max': T.Optional[int],
+        'deprecated': T.Union[bool, T.Dict[str, str], T.List[str]],
+        })
+    ParserArgs = TypedDict('ParserArgs', {
+        'yield': bool,
+        'choices': T.Optional[T.List[str]],
+        'value': object,
+        'min': T.Optional[int],
+        'max': T.Optional[int],
+        })
 
-forbidden_option_names = set(coredata.builtin_options.keys())
-forbidden_prefixes = [lang + '_' for lang in compilers.all_languages] + ['b_', 'backend_']
-reserved_prefixes = ['cross_']
-
-def is_invalid_name(name: str, *, log: bool = True) -> bool:
-    if name in forbidden_option_names:
-        return True
-    pref = name.split('_')[0] + '_'
-    if pref in forbidden_prefixes:
-        return True
-    if pref in reserved_prefixes:
-        if log:
-            from . import mlog
-            mlog.deprecation('Option uses prefix "%s", which is reserved for Meson. This will become an error in the future.' % pref)
-    return False
 
 class OptionException(mesonlib.MesonException):
     pass
 
 
-def permitted_kwargs(permitted):
-    """Function that validates kwargs for options."""
-    def _wraps(func):
-        @functools.wraps(func)
-        def _inner(name, description, kwargs):
-            bad = [a for a in kwargs.keys() if a not in permitted]
-            if bad:
-                raise OptionException('Invalid kwargs for option "{}": "{}"'.format(
-                    name, ' '.join(bad)))
-            return func(description, kwargs)
-        return _inner
-    return _wraps
-
-
 optname_regex = re.compile('[^a-zA-Z0-9_-]')
 
-@permitted_kwargs({'value', 'yield'})
-def StringParser(description, kwargs):
-    return coredata.UserStringOption(description,
-                                     kwargs.get('value', ''),
-                                     kwargs.get('choices', []),
-                                     kwargs.get('yield', coredata.default_yielding))
-
-@permitted_kwargs({'value', 'yield'})
-def BooleanParser(description, kwargs):
-    return coredata.UserBooleanOption(description,
-                                      kwargs.get('value', True),
-                                      kwargs.get('yield', coredata.default_yielding))
-
-@permitted_kwargs({'value', 'yield', 'choices'})
-def ComboParser(description, kwargs):
-    if 'choices' not in kwargs:
-        raise OptionException('Combo option missing "choices" keyword.')
-    choices = kwargs['choices']
-    if not isinstance(choices, list):
-        raise OptionException('Combo choices must be an array.')
-    for i in choices:
-        if not isinstance(i, str):
-            raise OptionException('Combo choice elements must be strings.')
-    return coredata.UserComboOption(description,
-                                    choices,
-                                    kwargs.get('value', choices[0]),
-                                    kwargs.get('yield', coredata.default_yielding),)
-
-
-@permitted_kwargs({'value', 'min', 'max', 'yield'})
-def IntegerParser(description, kwargs):
-    if 'value' not in kwargs:
-        raise OptionException('Integer option must contain value argument.')
-    return coredata.UserIntegerOption(description,
-                                      kwargs.get('min', None),
-                                      kwargs.get('max', None),
-                                      kwargs['value'],
-                                      kwargs.get('yield', coredata.default_yielding))
-
-# FIXME: Cannot use FeatureNew while parsing options because we parse it before
-# reading options in project(). See func_project() in interpreter.py
-#@FeatureNew('array type option()', '0.44.0')
-@permitted_kwargs({'value', 'yield', 'choices'})
-def string_array_parser(description, kwargs):
-    if 'choices' in kwargs:
-        choices = kwargs['choices']
-        if not isinstance(choices, list):
-            raise OptionException('Array choices must be an array.')
-        for i in choices:
-            if not isinstance(i, str):
-                raise OptionException('Array choice elements must be strings.')
-            value = kwargs.get('value', choices)
-    else:
-        choices = None
-        value = kwargs.get('value', [])
-    if not isinstance(value, list):
-        raise OptionException('Array choices must be passed as an array.')
-    return coredata.UserArrayOption(description,
-                                    value,
-                                    choices=choices,
-                                    yielding=kwargs.get('yield', coredata.default_yielding))
-
-@permitted_kwargs({'value', 'yield'})
-def FeatureParser(description, kwargs):
-    return coredata.UserFeatureOption(description,
-                                      kwargs.get('value', 'auto'),
-                                      yielding=kwargs.get('yield', coredata.default_yielding))
-
-option_types = {'string': StringParser,
-                'boolean': BooleanParser,
-                'combo': ComboParser,
-                'integer': IntegerParser,
-                'array': string_array_parser,
-                'feature': FeatureParser,
-                } # type: T.Dict[str, T.Callable[[str, T.Dict], coredata.UserOption]]
 
 class OptionInterpreter:
-    def __init__(self, subproject):
-        self.options = {}
+    def __init__(self, subproject: str) -> None:
+        self.options: 'coredata.KeyedOptionDictType' = {}
         self.subproject = subproject
+        self.option_types = {'string': self.string_parser,
+                             'boolean': self.boolean_parser,
+                             'combo': self.combo_parser,
+                             'integer': self.integer_parser,
+                             'array': self.string_array_parser,
+                             'feature': self.feature_parser,
+                             }
 
-    def process(self, option_file):
+    def process(self, option_file: str) -> None:
         try:
-            with open(option_file, 'r', encoding='utf8') as f:
-                ast = mparser.Parser(f.read(), '').parse()
+            with open(option_file, encoding='utf-8') as f:
+                ast = mparser.Parser(f.read(), option_file).parse()
         except mesonlib.MesonException as me:
             me.file = option_file
             raise me
         if not isinstance(ast, mparser.CodeBlockNode):
             e = OptionException('Option file is malformed.')
             e.lineno = ast.lineno()
+            e.file = option_file
             raise e
         for cur in ast.lines:
             try:
+                self.current_node = cur
                 self.evaluate_statement(cur)
-            except Exception as e:
+            except mesonlib.MesonException as e:
                 e.lineno = cur.lineno
                 e.colno = cur.colno
-                e.file = os.path.join('meson_options.txt')
+                e.file = option_file
                 raise e
+            except Exception as e:
+                raise mesonlib.MesonException(
+                    str(e), lineno=cur.lineno, colno=cur.colno, file=option_file)
 
-    def reduce_single(self, arg):
+    def reduce_single(self, arg: T.Union[str, mparser.BaseNode]) -> 'TYPE_var':
         if isinstance(arg, str):
             return arg
         elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode,
@@ -166,53 +94,130 @@
             return arg.value
         elif isinstance(arg, mparser.ArrayNode):
             return [self.reduce_single(curarg) for curarg in arg.args.arguments]
+        elif isinstance(arg, mparser.DictNode):
+            d = {}
+            for k, v in arg.args.kwargs.items():
+                if not isinstance(k, mparser.StringNode):
+                    raise OptionException('Dictionary keys must be a string literal')
+                d[k.value] = self.reduce_single(v)
+            return d
+        elif isinstance(arg, mparser.UMinusNode):
+            res = self.reduce_single(arg.value)
+            if not isinstance(res, (int, float)):
+                raise OptionException('Token after "-" is not a number')
+            FeatureNew.single_use('negative numbers in meson_options.txt', '0.54.1', self.subproject)
+            return -res
+        elif isinstance(arg, mparser.NotNode):
+            res = self.reduce_single(arg.value)
+            if not isinstance(res, bool):
+                raise OptionException('Token after "not" is not a a boolean')
+            FeatureNew.single_use('negation ("not") in meson_options.txt', '0.54.1', self.subproject)
+            return not res
+        elif isinstance(arg, mparser.ArithmeticNode):
+            l = self.reduce_single(arg.left)
+            r = self.reduce_single(arg.right)
+            if not (arg.operation == 'add' and isinstance(l, str) and isinstance(r, str)):
+                raise OptionException('Only string concatenation with the "+" operator is allowed')
+            FeatureNew.single_use('string concatenation in meson_options.txt', '0.55.0', self.subproject)
+            return l + r
         else:
             raise OptionException('Arguments may only be string, int, bool, or array of those.')
 
-    def reduce_arguments(self, args):
-        assert(isinstance(args, mparser.ArgumentNode))
+    def reduce_arguments(self, args: mparser.ArgumentNode) -> T.Tuple['TYPE_var', 'TYPE_kwargs']:
         if args.incorrect_order():
             raise OptionException('All keyword arguments must be after positional arguments.')
         reduced_pos = [self.reduce_single(arg) for arg in args.arguments]
         reduced_kw = {}
         for key in args.kwargs.keys():
-            if not isinstance(key, str):
+            if not isinstance(key, mparser.IdNode):
                 raise OptionException('Keyword argument name is not a string.')
             a = args.kwargs[key]
-            reduced_kw[key] = self.reduce_single(a)
+            reduced_kw[key.value] = self.reduce_single(a)
         return reduced_pos, reduced_kw
 
-    def evaluate_statement(self, node):
+    def evaluate_statement(self, node: mparser.BaseNode) -> None:
         if not isinstance(node, mparser.FunctionNode):
             raise OptionException('Option file may only contain option definitions')
         func_name = node.func_name
         if func_name != 'option':
             raise OptionException('Only calls to option() are allowed in option files.')
         (posargs, kwargs) = self.reduce_arguments(node.args)
+        self.func_option(posargs, kwargs)
 
-        # FIXME: Cannot use FeatureNew while parsing options because we parse
-        # it before reading options in project(). See func_project() in
-        # interpreter.py
-        #if 'yield' in kwargs:
-        #    FeatureNew('option yield', '0.45.0').use(self.subproject)
-
-        if 'type' not in kwargs:
-            raise OptionException('Option call missing mandatory "type" keyword argument')
-        opt_type = kwargs.pop('type')
-        if opt_type not in option_types:
-            raise OptionException('Unknown type %s.' % opt_type)
-        if len(posargs) != 1:
-            raise OptionException('Option() must have one (and only one) positional argument')
-        opt_name = posargs[0]
-        if not isinstance(opt_name, str):
-            raise OptionException('Positional argument must be a string.')
+    @typed_kwargs('option',
+                  KwargInfo('type', str, required=True),
+                  KwargInfo('description', str, default=''),
+                  KwargInfo('yield', bool, default=coredata.default_yielding, since='0.45.0'),
+                  KwargInfo('choices', (ContainerTypeInfo(list, str), type(None))),
+                  KwargInfo('value', object),
+                  KwargInfo('min', (int, type(None))),
+                  KwargInfo('max', (int, type(None))),
+                  KwargInfo('deprecated', (bool, ContainerTypeInfo(dict, str), ContainerTypeInfo(list, str)),
+                            default=False, since='0.60.0')
+                  )
+    @typed_pos_args('option', str)
+    def func_option(self, args: T.Tuple[str], kwargs: 'FuncOptionArgs') -> None:
+        opt_name = args[0]
         if optname_regex.search(opt_name) is not None:
             raise OptionException('Option names can only contain letters, numbers or dashes.')
-        if is_invalid_name(opt_name):
+        key = mesonlib.OptionKey.from_string(opt_name).evolve(subproject=self.subproject)
+        if not key.is_project():
             raise OptionException('Option name %s is reserved.' % opt_name)
-        if self.subproject != '':
-            opt_name = self.subproject + ':' + opt_name
-        opt = option_types[opt_type](opt_name, kwargs.pop('description', ''), kwargs)
-        if opt.description == '':
-            opt.description = opt_name
-        self.options[opt_name] = opt
+
+        opt_type = kwargs['type']
+        parser = self.option_types.get(opt_type)
+        if not parser:
+            raise OptionException(f'Unknown type {opt_type}.')
+        description = kwargs['description'] or opt_name
+
+        # Only keep in kwargs arguments that are used by option type's parser
+        # because they use @permittedKwargs().
+        known_parser_kwargs = {'value', 'choices', 'yield', 'min', 'max'}
+        parser_kwargs = {k: v for k, v in kwargs.items() if k in known_parser_kwargs and v is not None}
+        opt = parser(description, T.cast('ParserArgs', parser_kwargs))
+        opt.deprecated = kwargs['deprecated']
+
+        if key in self.options:
+            mlog.deprecation(f'Option {opt_name} already exists.')
+        self.options[key] = opt
+
+    @permittedKwargs({'value', 'yield'})
+    def string_parser(self, description: str, kwargs: 'ParserArgs') -> coredata.UserOption:
+        value = kwargs.get('value', '')
+        return coredata.UserStringOption(description, value, kwargs['yield'])
+
+    @permittedKwargs({'value', 'yield'})
+    def boolean_parser(self, description: str, kwargs: 'ParserArgs') -> coredata.UserOption:
+        value = kwargs.get('value', True)
+        return coredata.UserBooleanOption(description, value, kwargs['yield'])
+
+    @permittedKwargs({'value', 'yield', 'choices'})
+    def combo_parser(self, description: str, kwargs: 'ParserArgs') -> coredata.UserOption:
+        choices = kwargs.get('choices')
+        if not choices:
+            raise OptionException('Combo option missing "choices" keyword.')
+        value = kwargs.get('value', choices[0])
+        return coredata.UserComboOption(description, choices, value, kwargs['yield'])
+
+    @permittedKwargs({'value', 'min', 'max', 'yield'})
+    def integer_parser(self, description: str, kwargs: 'ParserArgs') -> coredata.UserOption:
+        value = kwargs.get('value')
+        if value is None:
+            raise OptionException('Integer option must contain value argument.')
+        inttuple = (kwargs.get('min'), kwargs.get('max'), value)
+        return coredata.UserIntegerOption(description, inttuple, kwargs['yield'])
+
+    @permittedKwargs({'value', 'yield', 'choices'})
+    def string_array_parser(self, description: str, kwargs: 'ParserArgs') -> coredata.UserOption:
+        choices = kwargs.get('choices', [])
+        value = kwargs.get('value', choices)
+        if not isinstance(value, list):
+            raise OptionException('Array choices must be passed as an array.')
+        return coredata.UserArrayOption(description, value,
+                                        choices=choices,
+                                        yielding=kwargs['yield'])
+
+    @permittedKwargs({'value', 'yield'})
+    def feature_parser(self, description: str, kwargs: 'ParserArgs') -> coredata.UserOption:
+        value = kwargs.get('value', 'auto')
+        return coredata.UserFeatureOption(description, value, kwargs['yield'])
diff -Nru meson-0.53.2/mesonbuild/_pathlib.py meson-0.61.2/mesonbuild/_pathlib.py
--- meson-0.53.2/mesonbuild/_pathlib.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/_pathlib.py	2021-07-20 08:56:20.000000000 +0000
@@ -0,0 +1,73 @@
+# Copyright 2021 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 soly exists to work around a pathlib.resolve bug on
+    certain Windows systems:
+
+    https://github.com/mesonbuild/meson/issues/7295
+    https://bugs.python.org/issue31842
+
+    It should **never** be used directly. Instead, it is automatically
+    used when `import pathlib` is used. This is achieved by messing with
+    `sys.modules['pathlib']` in mesonmain.
+
+    Additionally, the sole purpose of this module is to work around a
+    python bug. This only bugfixes to pathlib functions and classes are
+    allowed here. Finally, this file should be removed once all upstream
+    python bugs are fixed and it is OK to tell our users to "just upgrade
+    python".
+'''
+
+import pathlib
+import os
+import platform
+
+__all__ = [
+    'PurePath',
+    'PurePosixPath',
+    'PureWindowsPath',
+    'Path',
+]
+
+PurePath = pathlib.PurePath
+PurePosixPath = pathlib.PurePosixPath
+PureWindowsPath = pathlib.PureWindowsPath
+
+# Only patch on platforms where the bug occurs
+if platform.system().lower() in {'windows'}:
+    # Can not directly inherit from pathlib.Path because the __new__
+    # operator of pathlib.Path() returns a {Posix,Windows}Path object.
+    class Path(type(pathlib.Path())):
+        def resolve(self, strict: bool = False) -> 'Path':
+            '''
+                Work around a resolve bug on certain Windows systems:
+
+                https://github.com/mesonbuild/meson/issues/7295
+                https://bugs.python.org/issue31842
+            '''
+
+            try:
+                return super().resolve(strict=strict)
+            except OSError:
+                return Path(os.path.normpath(self))
+else:
+    Path = pathlib.Path
+    PosixPath = pathlib.PosixPath
+    WindowsPath = pathlib.WindowsPath
+
+    __all__ += [
+        'PosixPath',
+        'WindowsPath',
+    ]
diff -Nru meson-0.53.2/mesonbuild/programs.py meson-0.61.2/mesonbuild/programs.py
--- meson-0.53.2/mesonbuild/programs.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/programs.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,384 @@
+# Copyright 2013-2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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.
+
+"""Representations and logic for External and Internal Programs."""
+
+import functools
+import os
+import shutil
+import stat
+import sys
+import re
+import typing as T
+from pathlib import Path
+
+from . import mesonlib
+from . import mlog
+from .mesonlib import MachineChoice
+
+if T.TYPE_CHECKING:
+    from .environment import Environment
+    from .interpreter import Interpreter
+
+
+class ExternalProgram(mesonlib.HoldableObject):
+
+    """A program that is found on the system."""
+
+    windows_exts = ('exe', 'msc', 'com', 'bat', 'cmd')
+    for_machine = MachineChoice.BUILD
+
+    def __init__(self, name: str, command: T.Optional[T.List[str]] = None,
+                 silent: bool = False, search_dir: T.Optional[str] = None,
+                 extra_search_dirs: T.Optional[T.List[str]] = None):
+        self.name = name
+        self.path: T.Optional[str] = None
+        self.cached_version: T.Optional[str] = None
+        if command is not None:
+            self.command = mesonlib.listify(command)
+            if mesonlib.is_windows():
+                cmd = self.command[0]
+                args = self.command[1:]
+                # Check whether the specified cmd is a path to a script, in
+                # which case we need to insert the interpreter. If not, try to
+                # use it as-is.
+                ret = self._shebang_to_cmd(cmd)
+                if ret:
+                    self.command = ret + args
+                else:
+                    self.command = [cmd] + args
+        else:
+            all_search_dirs = [search_dir]
+            if extra_search_dirs:
+                all_search_dirs += extra_search_dirs
+            for d in all_search_dirs:
+                self.command = self._search(name, d)
+                if self.found():
+                    break
+
+        if self.found():
+            # Set path to be the last item that is actually a file (in order to
+            # skip options in something like ['python', '-u', 'file.py']. If we
+            # can't find any components, default to the last component of the path.
+            for arg in reversed(self.command):
+                if arg is not None and os.path.isfile(arg):
+                    self.path = arg
+                    break
+            else:
+                self.path = self.command[-1]
+
+        if not silent:
+            # ignore the warning because derived classes never call this __init__
+            # method, and thus only the found() method of this class is ever executed
+            if self.found():  # lgtm [py/init-calls-subclass]
+                mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'),
+                         '(%s)' % ' '.join(self.command))
+            else:
+                mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO'))
+
+    def summary_value(self) -> T.Union[str, mlog.AnsiDecorator]:
+        if not self.found():
+            return mlog.red('NO')
+        return self.path
+
+    def __repr__(self) -> str:
+        r = '<{} {!r} -> {!r}>'
+        return r.format(self.__class__.__name__, self.name, self.command)
+
+    def description(self) -> str:
+        '''Human friendly description of the command'''
+        return ' '.join(self.command)
+
+    def get_version(self, interpreter: 'Interpreter') -> str:
+        if not self.cached_version:
+            from . import build
+            raw_cmd = self.get_command() + ['--version']
+            res = interpreter.run_command_impl(interpreter.current_node, (self, ['--version']),
+                                               {'capture': True, 'check': True, 'env': build.EnvironmentVariables()},
+                                               True)
+            output = res.stdout.strip()
+            if not output:
+                output = res.stderr.strip()
+            match = re.search(r'([0-9][0-9\.]+)', output)
+            if not match:
+                raise mesonlib.MesonException(f'Could not find a version number in output of {raw_cmd!r}')
+            self.cached_version = match.group(1)
+        return self.cached_version
+
+    @classmethod
+    def from_bin_list(cls, env: 'Environment', for_machine: MachineChoice, name: str) -> 'ExternalProgram':
+        # There is a static `for_machine` for this class because the binary
+        # always runs on the build platform. (It's host platform is our build
+        # platform.) But some external programs have a target platform, so this
+        # is what we are specifying here.
+        command = env.lookup_binary_entry(for_machine, name)
+        if command is None:
+            return NonExistingExternalProgram()
+        return cls.from_entry(name, command)
+
+    @staticmethod
+    @functools.lru_cache(maxsize=None)
+    def _windows_sanitize_path(path: str) -> str:
+        # Ensure that we use USERPROFILE even when inside MSYS, MSYS2, Cygwin, etc.
+        if 'USERPROFILE' not in os.environ:
+            return path
+        # The WindowsApps directory is a bit of a problem. It contains
+        # some zero-sized .exe files which have "reparse points", that
+        # might either launch an installed application, or might open
+        # a page in the Windows Store to download the application.
+        #
+        # To handle the case where the python interpreter we're
+        # running on came from the Windows Store, if we see the
+        # WindowsApps path in the search path, replace it with
+        # dirname(sys.executable).
+        appstore_dir = Path(os.environ['USERPROFILE']) / 'AppData' / 'Local' / 'Microsoft' / 'WindowsApps'
+        paths = []
+        for each in path.split(os.pathsep):
+            if Path(each) != appstore_dir:
+                paths.append(each)
+            elif 'WindowsApps' in sys.executable:
+                paths.append(os.path.dirname(sys.executable))
+        return os.pathsep.join(paths)
+
+    @staticmethod
+    def from_entry(name: str, command: T.Union[str, T.List[str]]) -> 'ExternalProgram':
+        if isinstance(command, list):
+            if len(command) == 1:
+                command = command[0]
+        # We cannot do any searching if the command is a list, and we don't
+        # need to search if the path is an absolute path.
+        if isinstance(command, list) or os.path.isabs(command):
+            if isinstance(command, str):
+                command = [command]
+            return ExternalProgram(name, command=command, silent=True)
+        assert isinstance(command, str)
+        # Search for the command using the specified string!
+        return ExternalProgram(command, silent=True)
+
+    @staticmethod
+    def _shebang_to_cmd(script: str) -> T.Optional[T.List[str]]:
+        """
+        Check if the file has a shebang and manually parse it to figure out
+        the interpreter to use. This is useful if the script is not executable
+        or if we're on Windows (which does not understand shebangs).
+        """
+        try:
+            with open(script, encoding='utf-8') as f:
+                first_line = f.readline().strip()
+            if first_line.startswith('#!'):
+                # In a shebang, everything before the first space is assumed to
+                # be the command to run and everything after the first space is
+                # the single argument to pass to that command. So we must split
+                # exactly once.
+                commands = first_line[2:].split('#')[0].strip().split(maxsplit=1)
+                if mesonlib.is_windows():
+                    # Windows does not have UNIX paths so remove them,
+                    # but don't remove Windows paths
+                    if commands[0].startswith('/'):
+                        commands[0] = commands[0].split('/')[-1]
+                    if len(commands) > 0 and commands[0] == 'env':
+                        commands = commands[1:]
+                    # Windows does not ship python3.exe, but we know the path to it
+                    if len(commands) > 0 and commands[0] == 'python3':
+                        commands = mesonlib.python_command + commands[1:]
+                elif mesonlib.is_haiku():
+                    # Haiku does not have /usr, but a lot of scripts assume that
+                    # /usr/bin/env always exists. Detect that case and run the
+                    # script with the interpreter after it.
+                    if commands[0] == '/usr/bin/env':
+                        commands = commands[1:]
+                    # We know what python3 is, we're running on it
+                    if len(commands) > 0 and commands[0] == 'python3':
+                        commands = mesonlib.python_command + commands[1:]
+                else:
+                    # Replace python3 with the actual python3 that we are using
+                    if commands[0] == '/usr/bin/env' and commands[1] == 'python3':
+                        commands = mesonlib.python_command + commands[2:]
+                    elif commands[0].split('/')[-1] == 'python3':
+                        commands = mesonlib.python_command + commands[1:]
+                return commands + [script]
+        except Exception as e:
+            mlog.debug(str(e))
+        mlog.debug(f'Unusable script {script!r}')
+        return None
+
+    def _is_executable(self, path: str) -> bool:
+        suffix = os.path.splitext(path)[-1].lower()[1:]
+        execmask = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+        if mesonlib.is_windows():
+            if suffix in self.windows_exts:
+                return True
+        elif os.stat(path).st_mode & execmask:
+            return not os.path.isdir(path)
+        return False
+
+    def _search_dir(self, name: str, search_dir: T.Optional[str]) -> T.Optional[list]:
+        if search_dir is None:
+            return None
+        trial = os.path.join(search_dir, name)
+        if os.path.exists(trial):
+            if self._is_executable(trial):
+                return [trial]
+            # Now getting desperate. Maybe it is a script file that is
+            # a) not chmodded executable, or
+            # b) we are on windows so they can't be directly executed.
+            return self._shebang_to_cmd(trial)
+        else:
+            if mesonlib.is_windows():
+                for ext in self.windows_exts:
+                    trial_ext = f'{trial}.{ext}'
+                    if os.path.exists(trial_ext):
+                        return [trial_ext]
+        return None
+
+    def _search_windows_special_cases(self, name: str, command: str) -> T.List[T.Optional[str]]:
+        '''
+        Lots of weird Windows quirks:
+        1. PATH search for @name returns files with extensions from PATHEXT,
+           but only self.windows_exts are executable without an interpreter.
+        2. @name might be an absolute path to an executable, but without the
+           extension. This works inside MinGW so people use it a lot.
+        3. The script is specified without an extension, in which case we have
+           to manually search in PATH.
+        4. More special-casing for the shebang inside the script.
+        '''
+        if command:
+            # On Windows, even if the PATH search returned a full path, we can't be
+            # sure that it can be run directly if it's not a native executable.
+            # For instance, interpreted scripts sometimes need to be run explicitly
+            # with an interpreter if the file association is not done properly.
+            name_ext = os.path.splitext(command)[1]
+            if name_ext[1:].lower() in self.windows_exts:
+                # Good, it can be directly executed
+                return [command]
+            # Try to extract the interpreter from the shebang
+            commands = self._shebang_to_cmd(command)
+            if commands:
+                return commands
+            return [None]
+        # Maybe the name is an absolute path to a native Windows
+        # executable, but without the extension. This is technically wrong,
+        # but many people do it because it works in the MinGW shell.
+        if os.path.isabs(name):
+            for ext in self.windows_exts:
+                command = f'{name}.{ext}'
+                if os.path.exists(command):
+                    return [command]
+        # On Windows, interpreted scripts must have an extension otherwise they
+        # cannot be found by a standard PATH search. So we do a custom search
+        # where we manually search for a script with a shebang in PATH.
+        search_dirs = self._windows_sanitize_path(os.environ.get('PATH', '')).split(';')
+        for search_dir in search_dirs:
+            commands = self._search_dir(name, search_dir)
+            if commands:
+                return commands
+        return [None]
+
+    def _search(self, name: str, search_dir: T.Optional[str]) -> T.List[T.Optional[str]]:
+        '''
+        Search in the specified dir for the specified executable by name
+        and if not found search in PATH
+        '''
+        commands = self._search_dir(name, search_dir)
+        if commands:
+            return commands
+        # If there is a directory component, do not look in PATH
+        if os.path.dirname(name) and not os.path.isabs(name):
+            return [None]
+        # Do a standard search in PATH
+        path = os.environ.get('PATH', None)
+        if mesonlib.is_windows() and path:
+            path = self._windows_sanitize_path(path)
+        command = shutil.which(name, path=path)
+        if mesonlib.is_windows():
+            return self._search_windows_special_cases(name, command)
+        # On UNIX-like platforms, shutil.which() is enough to find
+        # all executables whether in PATH or with an absolute path
+        return [command]
+
+    def found(self) -> bool:
+        return self.command[0] is not None
+
+    def get_command(self) -> T.List[str]:
+        return self.command[:]
+
+    def get_path(self) -> T.Optional[str]:
+        return self.path
+
+    def get_name(self) -> str:
+        return self.name
+
+
+class NonExistingExternalProgram(ExternalProgram):  # lgtm [py/missing-call-to-init]
+    "A program that will never exist"
+
+    def __init__(self, name: str = 'nonexistingprogram') -> None:
+        self.name = name
+        self.command = [None]
+        self.path = None
+
+    def __repr__(self) -> str:
+        r = '<{} {!r} -> {!r}>'
+        return r.format(self.__class__.__name__, self.name, self.command)
+
+    def found(self) -> bool:
+        return False
+
+
+class EmptyExternalProgram(ExternalProgram):  # lgtm [py/missing-call-to-init]
+    '''
+    A program object that returns an empty list of commands. Used for cases
+    such as a cross file exe_wrapper to represent that it's not required.
+    '''
+
+    def __init__(self) -> None:
+        self.name = None
+        self.command = []
+        self.path = None
+
+    def __repr__(self) -> str:
+        r = '<{} {!r} -> {!r}>'
+        return r.format(self.__class__.__name__, self.name, self.command)
+
+    def found(self) -> bool:
+        return True
+
+
+class OverrideProgram(ExternalProgram):
+
+    """A script overriding a program."""
+
+
+def find_external_program(env: 'Environment', for_machine: MachineChoice, name: str,
+                          display_name: str, default_names: T.List[str],
+                          allow_default_for_cross: bool = True) -> T.Generator['ExternalProgram', None, None]:
+    """Find an external program, chcking the cross file plus any default options."""
+    # Lookup in cross or machine file.
+    potential_cmd = env.lookup_binary_entry(for_machine, name)
+    if potential_cmd is not None:
+        mlog.debug(f'{display_name} binary for {for_machine} specified from cross file, native file, '
+                   f'or env var as {potential_cmd}')
+        yield ExternalProgram.from_entry(name, potential_cmd)
+        # We never fallback if the user-specified option is no good, so
+        # stop returning options.
+        return
+    mlog.debug(f'{display_name} binary missing from cross or native file, or env var undefined.')
+    # Fallback on hard-coded defaults, if a default binary is allowed for use
+    # with cross targets, or if this is not a cross target
+    if allow_default_for_cross or not (for_machine is MachineChoice.HOST and env.is_cross_build(for_machine)):
+        for potential_path in default_names:
+            mlog.debug(f'Trying a default {display_name} fallback at', potential_path)
+            yield ExternalProgram(potential_path, silent=True)
+    else:
+        mlog.debug('Default target is not allowed for cross use')
diff -Nru meson-0.53.2/mesonbuild/rewriter.py meson-0.61.2/mesonbuild/rewriter.py
--- meson-0.53.2/mesonbuild/rewriter.py	2020-01-23 12:51:19.000000000 +0000
+++ meson-0.61.2/mesonbuild/rewriter.py	2021-12-26 16:24:25.000000000 +0000
@@ -46,7 +46,7 @@
     tgt_parser.add_argument('--type', dest='tgt_type', choices=rewriter_keys['target']['target_type'][2], default='executable',
                             help='Type of the target to add (only for the "add_target" action)')
     tgt_parser.add_argument('target', help='Name or ID of the target')
-    tgt_parser.add_argument('operation', choices=['add', 'rm', 'add_target', 'rm_target', 'info'],
+    tgt_parser.add_argument('operation', choices=['add', 'rm', 'add_target', 'rm_target', 'add_extra_files', 'rm_extra_files', 'info'],
                             help='Action to execute')
     tgt_parser.add_argument('sources', nargs='*', help='Sources to add/remove')
 
@@ -76,7 +76,7 @@
     def __call__(self, f):
         @wraps(f)
         def wrapped(*wrapped_args, **wrapped_kwargs):
-            assert(len(wrapped_args) >= 2)
+            assert len(wrapped_args) >= 2
             cmd = wrapped_args[1]
             for key, val in self.keys.items():
                 typ = val[0] # The type of the value
@@ -92,7 +92,7 @@
                     raise RewriterException('Invalid type of "{}". Required is {} but provided was {}'
                                             .format(key, typ.__name__, type(cmd[key]).__name__))
                 if choices is not None:
-                    assert(isinstance(choices, list))
+                    assert isinstance(choices, list)
                     if cmd[key] not in choices:
                         raise RewriterException('Invalid value of "{}": Possible values are {} but provided was "{}"'
                                                 .format(key, choices, cmd[key]))
@@ -113,7 +113,7 @@
 
     def _new_node(self):
         # Overwrite in derived class
-        return BaseNode()
+        raise RewriterException('Internal error: _new_node of MTypeBase was called')
 
     def can_modify(self):
         return self.node_type is not None
@@ -159,7 +159,7 @@
         super().__init__(node)
 
     def _new_node(self):
-        return StringNode(Token('', '', 0, 0, 0, None, False))
+        return BooleanNode(Token('', '', 0, 0, 0, None, False))
 
     def supported_nodes(self):
         return [BooleanNode]
@@ -172,7 +172,7 @@
         super().__init__(node)
 
     def _new_node(self):
-        return StringNode(Token('', '', 0, 0, 0, None, ''))
+        return IdNode(Token('', '', 0, 0, 0, None, ''))
 
     def supported_nodes(self):
         return [IdNode]
@@ -189,7 +189,7 @@
 
     def _new_element_node(self, value):
         # Overwrite in derived class
-        return BaseNode()
+        raise RewriterException('Internal error: _new_element_node of MTypeList was called')
 
     def _ensure_array_node(self):
         if not isinstance(self.node, ArrayNode):
@@ -308,7 +308,7 @@
     },
     'target': {
         'target': (str, None, None),
-        'operation': (str, None, ['src_add', 'src_rm', 'target_rm', 'target_add', 'info']),
+        'operation': (str, None, ['src_add', 'src_rm', 'target_rm', 'target_add', 'extra_files_add', 'extra_files_rm', 'info']),
         'sources': (list, [], None),
         'subdir': (str, '', None),
         'target_type': (str, 'executable', ['both_libraries', 'executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library']),
@@ -353,7 +353,7 @@
         self.sourcedir = sourcedir
         self.interpreter = IntrospectionInterpreter(sourcedir, '', generator, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()])
         self.skip_errors = skip_errors
-        self.modefied_nodes = []
+        self.modified_nodes = []
         self.to_remove_nodes = []
         self.to_add_nodes = []
         self.functions = {
@@ -414,10 +414,10 @@
         # Check the assignments
         tgt = None
         if target in self.interpreter.assignments:
-            node = self.interpreter.assignments[target][0]
+            node = self.interpreter.assignments[target]
             if isinstance(node, FunctionNode):
                 if node.func_name in ['executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries']:
-                    tgt = self.interpreter.assign_vals[target][0]
+                    tgt = self.interpreter.assign_vals[target]
 
         return tgt
 
@@ -434,7 +434,7 @@
 
         # Check the assignments
         if dependency in self.interpreter.assignments:
-            node = self.interpreter.assignments[dependency][0]
+            node = self.interpreter.assignments[dependency]
             if isinstance(node, FunctionNode):
                 if node.func_name in ['dependency']:
                     name = self.interpreter.flatten_args(node.args)[0]
@@ -450,7 +450,7 @@
             'id': "/",
             'operation': 'remove_regex',
             'kwargs': {
-                'default_options': ['{}=.*'.format(x) for x in cmd['options'].keys()]
+                'default_options': [f'{x}=.*' for x in cmd['options'].keys()]
             }
         }
         self.process_kwargs(kwargs_cmd)
@@ -464,14 +464,11 @@
 
         cdata = self.interpreter.coredata
         options = {
-            **cdata.builtins,
-            **cdata.builtins_per_machine.host,
-            **{'build.' + k: o for k, o in cdata.builtins_per_machine.build.items()},
-            **cdata.backend_options,
-            **cdata.base_options,
-            **cdata.compiler_options.host,
-            **{'build.' + k: o for k, o in cdata.compiler_options.build.items()},
-            **cdata.user_options,
+            **{str(k): v for k, v in cdata.options.items()},
+            **{str(k): v for k, v in cdata.options.items()},
+            **{str(k): v for k, v in cdata.options.items()},
+            **{str(k): v for k, v in cdata.options.items()},
+            **{str(k): v for k, v in cdata.options.items()},
         }
 
         for key, val in sorted(cmd['options'].items()):
@@ -487,7 +484,7 @@
                 self.handle_error()
                 continue
 
-            kwargs_cmd['kwargs']['default_options'] += ['{}={}'.format(key, val)]
+            kwargs_cmd['kwargs']['default_options'] += [f'{key}={val}']
 
         self.process_kwargs(kwargs_cmd)
 
@@ -503,8 +500,12 @@
         node = None
         arg_node = None
         if cmd['function'] == 'project':
-            if cmd['id'] != '/':
-                mlog.error('The ID for the function type project must be "/"', *self.on_error())
+            # msys bash may expand '/' to a path. It will mangle '//' to '/'
+            # but in order to keep usage shell-agnostic, also allow `//` as
+            # the function ID such that it will work in both msys bash and
+            # other shells.
+            if {'/', '//'}.isdisjoint({cmd['id']}):
+                mlog.error('The ID for the function type project must be "/" or "//" not "' + cmd['id'] + '"', *self.on_error())
                 return self.handle_error()
             node = self.interpreter.project_node
             arg_node = node.args
@@ -520,8 +521,10 @@
                 arg_node = node.args
         if not node:
             mlog.error('Unable to find the function node')
-        assert(isinstance(node, FunctionNode))
-        assert(isinstance(arg_node, ArgumentNode))
+        assert isinstance(node, FunctionNode)
+        assert isinstance(arg_node, ArgumentNode)
+        # Transform the key nodes to plain strings
+        arg_node.kwargs = {k.value: v for k, v in arg_node.kwargs.items()}
 
         # Print kwargs info
         if cmd['operation'] == 'info':
@@ -585,11 +588,13 @@
             arg_node.kwargs[key] = modifyer.get_node()
             num_changed += 1
 
-        if num_changed > 0 and node not in self.modefied_nodes:
-            self.modefied_nodes += [node]
+        # Convert the keys back to IdNode's
+        arg_node.kwargs = {IdNode(Token('', '', 0, 0, 0, None, k)): v for k, v in arg_node.kwargs.items()}
+        if num_changed > 0 and node not in self.modified_nodes:
+            self.modified_nodes += [node]
 
     def find_assignment_node(self, node: BaseNode) -> AssignmentNode:
-        if hasattr(node, 'ast_id') and node.ast_id in self.interpreter.reverse_assignment:
+        if node.ast_id and node.ast_id in self.interpreter.reverse_assignment:
             return self.interpreter.reverse_assignment[node.ast_id]
         return None
 
@@ -635,7 +640,7 @@
                 node = target['sources'][0]
             else:
                 node = target['node']
-            assert(node is not None)
+            assert node is not None
 
             # Generate the current source list
             src_list = []
@@ -651,8 +656,8 @@
                     mlog.log('  -- Source', mlog.green(i), 'is already defined for the target --> skipping')
                     continue
                 mlog.log('  -- Adding source', mlog.green(i), 'at',
-                         mlog.yellow('{}:{}'.format(os.path.join(node.subdir, environment.build_filename), node.lineno)))
-                token = Token('string', node.subdir, 0, 0, 0, None, i)
+                         mlog.yellow(f'{node.filename}:{node.lineno}'))
+                token = Token('string', node.filename, 0, 0, 0, None, i)
                 to_append += [StringNode(token)]
 
             # Append to the AST at the right place
@@ -661,14 +666,14 @@
                 arg_node = node.args
             elif isinstance(node, ArgumentNode):
                 arg_node = node
-            assert(arg_node is not None)
+            assert arg_node is not None
             arg_node.arguments += to_append
 
             # Mark the node as modified
             if arg_node not in to_sort_nodes and not isinstance(node, FunctionNode):
                 to_sort_nodes += [arg_node]
-            if node not in self.modefied_nodes:
-                self.modefied_nodes += [node]
+            if node not in self.modified_nodes:
+                self.modified_nodes += [node]
 
         elif cmd['operation'] == 'src_rm':
             # Helper to find the exact string node and its parent
@@ -693,16 +698,101 @@
                     arg_node = root.args
                 elif isinstance(root, ArgumentNode):
                     arg_node = root
-                assert(arg_node is not None)
+                assert arg_node is not None
                 mlog.log('  -- Removing source', mlog.green(i), 'from',
-                         mlog.yellow('{}:{}'.format(os.path.join(string_node.subdir, environment.build_filename), string_node.lineno)))
+                         mlog.yellow(f'{string_node.filename}:{string_node.lineno}'))
                 arg_node.arguments.remove(string_node)
 
                 # Mark the node as modified
                 if arg_node not in to_sort_nodes and not isinstance(root, FunctionNode):
                     to_sort_nodes += [arg_node]
-                if root not in self.modefied_nodes:
-                    self.modefied_nodes += [root]
+                if root not in self.modified_nodes:
+                    self.modified_nodes += [root]
+
+        elif cmd['operation'] == 'extra_files_add':
+            tgt_function: FunctionNode = target['node']
+            mark_array = True
+            try:
+                node = target['extra_files'][0]
+            except IndexError:
+                # Specifying `extra_files` with a list that flattens to empty gives an empty
+                # target['extra_files'] list, account for that.
+                try:
+                    extra_files_key = next(k for k in tgt_function.args.kwargs.keys() if isinstance(k, IdNode) and k.value == 'extra_files')
+                    node = tgt_function.args.kwargs[extra_files_key]
+                except StopIteration:
+                    # Target has no extra_files kwarg, create one
+                    node = ArrayNode(ArgumentNode(Token('', tgt_function.filename, 0, 0, 0, None, '[]')), tgt_function.end_lineno, tgt_function.end_colno, tgt_function.end_lineno, tgt_function.end_colno)
+                    tgt_function.args.kwargs[IdNode(Token('string', tgt_function.filename, 0, 0, 0, None, 'extra_files'))] = node
+                    mark_array = False
+                    if tgt_function not in self.modified_nodes:
+                        self.modified_nodes += [tgt_function]
+                target['extra_files'] = [node]
+            if isinstance(node, IdNode):
+                node = self.interpreter.assignments[node.value]
+                target['extra_files'] = [node]
+            if not isinstance(node, ArrayNode):
+                mlog.error('Target', mlog.bold(cmd['target']), 'extra_files argument must be a list', *self.on_error())
+                return self.handle_error()
+
+            # Generate the current extra files list
+            extra_files_list = []
+            for i in target['extra_files']:
+                for j in arg_list_from_node(i):
+                    if isinstance(j, StringNode):
+                        extra_files_list += [j.value]
+
+            # Generate the new String nodes
+            to_append = []
+            for i in sorted(set(cmd['sources'])):
+                if i in extra_files_list:
+                    mlog.log('  -- Extra file', mlog.green(i), 'is already defined for the target --> skipping')
+                    continue
+                mlog.log('  -- Adding extra file', mlog.green(i), 'at',
+                         mlog.yellow(f'{node.filename}:{node.lineno}'))
+                token = Token('string', node.filename, 0, 0, 0, None, i)
+                to_append += [StringNode(token)]
+
+            # Append to the AST at the right place
+            arg_node = node.args
+            arg_node.arguments += to_append
+
+            # Mark the node as modified
+            if arg_node not in to_sort_nodes:
+                to_sort_nodes += [arg_node]
+            # If the extra_files array is newly created, don't mark it as its parent function node already is,
+            # otherwise this would cause double modification.
+            if mark_array and node not in self.modified_nodes:
+                self.modified_nodes += [node]
+
+        elif cmd['operation'] == 'extra_files_rm':
+            # Helper to find the exact string node and its parent
+            def find_node(src):
+                for i in target['extra_files']:
+                    for j in arg_list_from_node(i):
+                        if isinstance(j, StringNode):
+                            if j.value == src:
+                                return i, j
+                return None, None
+
+            for i in cmd['sources']:
+                # Try to find the node with the source string
+                root, string_node = find_node(i)
+                if root is None:
+                    mlog.warning('  -- Unable to find extra file', mlog.green(i), 'in the target')
+                    continue
+
+                # Remove the found string node from the argument list
+                arg_node = root.args
+                mlog.log('  -- Removing extra file', mlog.green(i), 'from',
+                         mlog.yellow(f'{string_node.filename}:{string_node.lineno}'))
+                arg_node.arguments.remove(string_node)
+
+                # Mark the node as modified
+                if arg_node not in to_sort_nodes and not isinstance(root, FunctionNode):
+                    to_sort_nodes += [arg_node]
+                if root not in self.modified_nodes:
+                    self.modified_nodes += [root]
 
         elif cmd['operation'] == 'target_add':
             if target is not None:
@@ -712,23 +802,24 @@
             id_base = re.sub(r'[- ]', '_', cmd['target'])
             target_id = id_base + '_exe' if cmd['target_type'] == 'executable' else '_lib'
             source_id = id_base + '_sources'
+            filename = os.path.join(cmd['subdir'], environment.build_filename)
 
             # Build src list
-            src_arg_node = ArgumentNode(Token('string', cmd['subdir'], 0, 0, 0, None, ''))
+            src_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, ''))
             src_arr_node = ArrayNode(src_arg_node, 0, 0, 0, 0)
-            src_far_node = ArgumentNode(Token('string', cmd['subdir'], 0, 0, 0, None, ''))
-            src_fun_node = FunctionNode(cmd['subdir'], 0, 0, 0, 0, 'files', src_far_node)
-            src_ass_node = AssignmentNode(cmd['subdir'], 0, 0, source_id, src_fun_node)
-            src_arg_node.arguments = [StringNode(Token('string', cmd['subdir'], 0, 0, 0, None, x)) for x in cmd['sources']]
+            src_far_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, ''))
+            src_fun_node = FunctionNode(filename, 0, 0, 0, 0, 'files', src_far_node)
+            src_ass_node = AssignmentNode(filename, 0, 0, source_id, src_fun_node)
+            src_arg_node.arguments = [StringNode(Token('string', filename, 0, 0, 0, None, x)) for x in cmd['sources']]
             src_far_node.arguments = [src_arr_node]
 
             # Build target
-            tgt_arg_node = ArgumentNode(Token('string', cmd['subdir'], 0, 0, 0, None, ''))
-            tgt_fun_node = FunctionNode(cmd['subdir'], 0, 0, 0, 0, cmd['target_type'], tgt_arg_node)
-            tgt_ass_node = AssignmentNode(cmd['subdir'], 0, 0, target_id, tgt_fun_node)
+            tgt_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, ''))
+            tgt_fun_node = FunctionNode(filename, 0, 0, 0, 0, cmd['target_type'], tgt_arg_node)
+            tgt_ass_node = AssignmentNode(filename, 0, 0, target_id, tgt_fun_node)
             tgt_arg_node.arguments = [
-                StringNode(Token('string', cmd['subdir'], 0, 0, 0, None, cmd['target'])),
-                IdNode(Token('string', cmd['subdir'], 0, 0, 0, None, source_id))
+                StringNode(Token('string', filename, 0, 0, 0, None, cmd['target'])),
+                IdNode(Token('string', filename, 0, 0, 0, None, source_id))
             ]
 
             src_ass_node.accept(AstIndentationGenerator())
@@ -741,7 +832,7 @@
                 to_remove = target['node']
             self.to_remove_nodes += [to_remove]
             mlog.log('  -- Removing target', mlog.green(cmd['target']), 'at',
-                     mlog.yellow('{}:{}'.format(os.path.join(to_remove.subdir, environment.build_filename), to_remove.lineno)))
+                     mlog.yellow(f'{to_remove.filename}:{to_remove.lineno}'))
 
         elif cmd['operation'] == 'info':
             # T.List all sources in the target
@@ -750,9 +841,15 @@
                 for j in arg_list_from_node(i):
                     if isinstance(j, StringNode):
                         src_list += [j.value]
+            extra_files_list = []
+            for i in target['extra_files']:
+                for j in arg_list_from_node(i):
+                    if isinstance(j, StringNode):
+                        extra_files_list += [j.value]
             test_data = {
                 'name': target['name'],
-                'sources': src_list
+                'sources': src_list,
+                'extra_files': extra_files_list
             }
             self.add_info('target', target['id'], test_data)
 
@@ -776,12 +873,12 @@
         self.functions[cmd['type']](cmd)
 
     def apply_changes(self):
-        assert(all(hasattr(x, 'lineno') and hasattr(x, 'colno') and hasattr(x, 'subdir') for x in self.modefied_nodes))
-        assert(all(hasattr(x, 'lineno') and hasattr(x, 'colno') and hasattr(x, 'subdir') for x in self.to_remove_nodes))
-        assert(all(isinstance(x, (ArrayNode, FunctionNode)) for x in self.modefied_nodes))
-        assert(all(isinstance(x, (ArrayNode, AssignmentNode, FunctionNode)) for x in self.to_remove_nodes))
+        assert all(hasattr(x, 'lineno') and hasattr(x, 'colno') and hasattr(x, 'filename') for x in self.modified_nodes)
+        assert all(hasattr(x, 'lineno') and hasattr(x, 'colno') and hasattr(x, 'filename') for x in self.to_remove_nodes)
+        assert all(isinstance(x, (ArrayNode, FunctionNode)) for x in self.modified_nodes)
+        assert all(isinstance(x, (ArrayNode, AssignmentNode, FunctionNode)) for x in self.to_remove_nodes)
         # Sort based on line and column in reversed order
-        work_nodes = [{'node': x, 'action': 'modify'} for x in self.modefied_nodes]
+        work_nodes = [{'node': x, 'action': 'modify'} for x in self.modified_nodes]
         work_nodes += [{'node': x, 'action': 'rm'} for x in self.to_remove_nodes]
         work_nodes = list(sorted(work_nodes, key=lambda x: (x['node'].lineno, x['node'].colno), reverse=True))
         work_nodes += [{'node': x, 'action': 'add'} for x in self.to_add_nodes]
@@ -796,7 +893,7 @@
                 printer.post_process()
                 new_data = printer.result.strip()
             data = {
-                'file': os.path.join(i['node'].subdir, environment.build_filename),
+                'file': i['node'].filename,
                 'str': new_data,
                 'node': i['node'],
                 'action': i['action']
@@ -812,9 +909,9 @@
             fdata = ''
             # Create an empty file if it does not exist
             if not os.path.exists(fpath):
-                with open(fpath, 'w'):
+                with open(fpath, 'w', encoding='utf-8'):
                     pass
-            with open(fpath, 'r') as fp:
+            with open(fpath, encoding='utf-8') as fp:
                 fdata = fp.read()
 
             # Generate line offsets numbers
@@ -865,7 +962,7 @@
         # Write the files back
         for key, val in files.items():
             mlog.log('Rewriting', mlog.yellow(key))
-            with open(val['path'], 'w') as fp:
+            with open(val['path'], 'w', encoding='utf-8') as fp:
                 fp.write(val['raw'])
 
 target_operation_map = {
@@ -873,6 +970,8 @@
     'rm': 'src_rm',
     'add_target': 'target_add',
     'rm_target': 'target_rm',
+    'add_extra_files': 'extra_files_add',
+    'rm_extra_files': 'extra_files_rm',
     'info': 'info',
 }
 
@@ -915,9 +1014,9 @@
         'options': list_to_dict(options.options),
     }]
 
-def genreate_cmd(options) -> T.List[dict]:
+def generate_cmd(options) -> T.List[dict]:
     if os.path.exists(options.json):
-        with open(options.json, 'r') as fp:
+        with open(options.json, encoding='utf-8') as fp:
             return json.load(fp)
     else:
         return json.loads(options.json)
@@ -929,8 +1028,8 @@
     'kwargs': generate_kwargs,
     'default-options': generate_def_opts,
     'def': generate_def_opts,
-    'command': genreate_cmd,
-    'cmd': genreate_cmd,
+    'command': generate_cmd,
+    'cmd': generate_cmd,
 }
 
 def run(options):
diff -Nru meson-0.53.2/mesonbuild/scripts/clangformat.py meson-0.61.2/mesonbuild/scripts/clangformat.py
--- meson-0.53.2/mesonbuild/scripts/clangformat.py	2019-10-06 17:01:35.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/clangformat.py	2021-12-26 16:24:25.000000000 +0000
@@ -12,34 +12,41 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import pathlib
+import argparse
 import subprocess
-from concurrent.futures import ThreadPoolExecutor
+from pathlib import Path
 
+from .run_tool import run_tool
 from ..environment import detect_clangformat
-from ..compilers import lang_suffixes
+import typing as T
 
-def clangformat(exelist, srcdir_name, builddir_name):
-    srcdir = pathlib.Path(srcdir_name)
-    suffixes = set(lang_suffixes['c']).union(set(lang_suffixes['cpp']))
-    suffixes.add('h')
-    futures = []
-    with ThreadPoolExecutor() as e:
-        for f in (x for suff in suffixes for x in srcdir.glob('**/*.' + suff)):
-            strf = str(f)
-            if strf.startswith(builddir_name):
-                continue
-            futures.append(e.submit(subprocess.check_call, exelist + ['-style=file', '-i', strf]))
-        [x.result() for x in futures]
-    return 0
-
-def run(args):
-    srcdir_name = args[0]
-    builddir_name = args[1]
+def run_clang_format(fname: Path, exelist: T.List[str], check: bool) -> subprocess.CompletedProcess:
+    if check:
+        original = fname.read_bytes()
+    before = fname.stat().st_mtime
+    ret = subprocess.run(exelist + ['-style=file', '-i', str(fname)])
+    after = fname.stat().st_mtime
+    if before != after:
+        print('File reformatted: ', fname)
+        if check:
+            # Restore the original if only checking.
+            fname.write_bytes(original)
+            ret.returncode = 1
+    return ret
+
+def run(args: T.List[str]) -> int:
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--check', action='store_true')
+    parser.add_argument('sourcedir')
+    parser.add_argument('builddir')
+    options = parser.parse_args(args)
+
+    srcdir = Path(options.sourcedir)
+    builddir = Path(options.builddir)
 
     exelist = detect_clangformat()
     if not exelist:
         print('Could not execute clang-format "%s"' % ' '.join(exelist))
         return 1
 
-    return clangformat(exelist, srcdir_name, builddir_name)
+    return run_tool('clang-format', srcdir, builddir, run_clang_format, exelist, options.check)
diff -Nru meson-0.53.2/mesonbuild/scripts/clangtidy.py meson-0.61.2/mesonbuild/scripts/clangtidy.py
--- meson-0.53.2/mesonbuild/scripts/clangtidy.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/clangtidy.py	2021-12-26 16:24:25.000000000 +0000
@@ -12,41 +12,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import pathlib
+import argparse
 import subprocess
-import shutil
-from concurrent.futures import ThreadPoolExecutor
+from pathlib import Path
 
-from ..compilers import lang_suffixes
+from .run_tool import run_tool
+import typing as T
 
-def manual_clangformat(srcdir_name, builddir_name):
-    srcdir = pathlib.Path(srcdir_name)
-    suffixes = set(lang_suffixes['c']).union(set(lang_suffixes['cpp']))
-    suffixes.add('h')
-    futures = []
-    returncode = 0
-    with ThreadPoolExecutor() as e:
-        for f in (x for suff in suffixes for x in srcdir.glob('**/*.' + suff)):
-            strf = str(f)
-            if strf.startswith(builddir_name):
-                continue
-            futures.append(e.submit(subprocess.run, ['clang-tidy', '-p', builddir_name, strf]))
-        [max(returncode, x.result().returncode) for x in futures]
-    return returncode
-
-def clangformat(srcdir_name, builddir_name):
-    run_clang_tidy = None
-    for rct in ('run-clang-tidy', 'run-clang-tidy.py'):
-        if shutil.which(rct):
-            run_clang_tidy = rct
-            break
-    if run_clang_tidy:
-        return subprocess.run([run_clang_tidy, '-p', builddir_name]).returncode
-    else:
-        print('Could not find run-clang-tidy, running checks manually.')
-        manual_clangformat(srcdir_name, builddir_name)
-
-def run(args):
-    srcdir_name = args[0]
-    builddir_name = args[1]
-    return clangformat(srcdir_name, builddir_name)
+def run_clang_tidy(fname: Path, builddir: Path) -> subprocess.CompletedProcess:
+    return subprocess.run(['clang-tidy', '-p', str(builddir), str(fname)])
+
+def run(args: T.List[str]) -> int:
+    parser = argparse.ArgumentParser()
+    parser.add_argument('sourcedir')
+    parser.add_argument('builddir')
+    options = parser.parse_args(args)
+
+    srcdir = Path(options.sourcedir)
+    builddir = Path(options.builddir)
+
+    return run_tool('clang-tidy', srcdir, builddir, run_clang_tidy, builddir)
diff -Nru meson-0.53.2/mesonbuild/scripts/cleantrees.py meson-0.61.2/mesonbuild/scripts/cleantrees.py
--- meson-0.53.2/mesonbuild/scripts/cleantrees.py	2016-12-20 19:35:10.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/cleantrees.py	2021-04-27 06:49:45.000000000 +0000
@@ -16,19 +16,20 @@
 import sys
 import shutil
 import pickle
+import typing as T
 
-def rmtrees(build_dir, trees):
+def rmtrees(build_dir: str, trees: T.List[str]) -> None:
     for t in trees:
         # Never delete trees outside of the builddir
         if os.path.isabs(t):
-            print('Cannot delete dir with absolute path {!r}'.format(t))
+            print(f'Cannot delete dir with absolute path {t!r}')
             continue
         bt = os.path.join(build_dir, t)
         # Skip if it doesn't exist, or if it is not a directory
         if os.path.isdir(bt):
             shutil.rmtree(bt, ignore_errors=True)
 
-def run(args):
+def run(args: T.List[str]) -> int:
     if len(args) != 1:
         print('Cleaner script for Meson. Do not run on your own please.')
         print('cleantrees.py ')
diff -Nru meson-0.53.2/mesonbuild/scripts/cmake_run_ctgt.py meson-0.61.2/mesonbuild/scripts/cmake_run_ctgt.py
--- meson-0.53.2/mesonbuild/scripts/cmake_run_ctgt.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/cmake_run_ctgt.py	2021-04-27 06:49:45.000000000 +0000
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+
+import argparse
+import subprocess
+import shutil
+import sys
+from pathlib import Path
+import typing as T
+
+def run(argsv: T.List[str]) -> int:
+    commands = [[]]  # type: T.List[T.List[str]]
+    SEPARATOR = ';;;'
+
+    # Generate CMD parameters
+    parser = argparse.ArgumentParser(description='Wrapper for add_custom_command')
+    parser.add_argument('-d', '--directory', type=str, metavar='D', required=True, help='Working directory to cwd to')
+    parser.add_argument('-o', '--outputs', nargs='+', metavar='O', required=True, help='Expected output files')
+    parser.add_argument('-O', '--original-outputs', nargs='*', metavar='O', default=[], help='Output files expected by CMake')
+    parser.add_argument('commands', nargs=argparse.REMAINDER, help=f'A "{SEPARATOR}" separated list of commands')
+
+    # Parse
+    args = parser.parse_args(argsv)
+    directory = Path(args.directory)
+
+    dummy_target = None
+    if len(args.outputs) == 1 and len(args.original_outputs) == 0:
+        dummy_target = Path(args.outputs[0])
+    elif len(args.outputs) != len(args.original_outputs):
+        print('Length of output list and original output list differ')
+        return 1
+
+    for i in args.commands:
+        if i == SEPARATOR:
+            commands += [[]]
+            continue
+
+        i = i.replace('"', '')  # Remove lefover quotes
+        commands[-1] += [i]
+
+    # Execute
+    for i in commands:
+        # Skip empty lists
+        if not i:
+            continue
+
+        cmd = []
+        stdout = None
+        stderr = None
+        capture_file = ''
+
+        for j in i:
+            if j in ['>', '>>']:
+                stdout = subprocess.PIPE
+                continue
+            elif j in ['&>', '&>>']:
+                stdout = subprocess.PIPE
+                stderr = subprocess.STDOUT
+                continue
+
+            if stdout is not None or stderr is not None:
+                capture_file += j
+            else:
+                cmd += [j]
+
+        try:
+            directory.mkdir(parents=True, exist_ok=True)
+
+            res = subprocess.run(cmd, stdout=stdout, stderr=stderr, cwd=str(directory), check=True)
+            if capture_file:
+                out_file = directory / capture_file
+                out_file.write_bytes(res.stdout)
+        except subprocess.CalledProcessError:
+            return 1
+
+    if dummy_target:
+        dummy_target.touch()
+        return 0
+
+    # Copy outputs
+    zipped_outputs = zip([Path(x) for x in args.outputs], [Path(x) for x in args.original_outputs])
+    for expected, generated in zipped_outputs:
+        do_copy = False
+        if not expected.exists():
+            if not generated.exists():
+                print('Unable to find generated file. This can cause the build to fail:')
+                print(generated)
+                do_copy = False
+            else:
+                do_copy = True
+        elif generated.exists():
+            if generated.stat().st_mtime > expected.stat().st_mtime:
+                do_copy = True
+
+        if do_copy:
+            if expected.exists():
+                expected.unlink()
+            shutil.copyfile(str(generated), str(expected))
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(run(sys.argv[1:]))
diff -Nru meson-0.53.2/mesonbuild/scripts/cmd_or_ps.ps1 meson-0.61.2/mesonbuild/scripts/cmd_or_ps.ps1
--- meson-0.53.2/mesonbuild/scripts/cmd_or_ps.ps1	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/cmd_or_ps.ps1	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,22 @@
+# Copied from GStreamer project
+# Author: Seungha Yang 
+
+$i=1
+$ppid=(gwmi win32_process -Filter "processid='$pid'").parentprocessid
+$pname=(Get-Process -id $ppid).Name
+While($true) {
+  if($pname -eq "cmd" -Or $pname -eq "powershell") {
+    Write-Host ("{0}.exe" -f $pname)
+    Break
+  }
+
+  # 10 times iteration seems to be sufficient
+  if($i -gt 10) {
+    Break
+  }
+
+  # not found yet, find grand parant
+  $ppid=(gwmi win32_process -Filter "processid='$ppid'").parentprocessid
+  $pname=(Get-Process -id $ppid).Name
+  $i++
+}
diff -Nru meson-0.53.2/mesonbuild/scripts/commandrunner.py meson-0.61.2/mesonbuild/scripts/commandrunner.py
--- meson-0.53.2/mesonbuild/scripts/commandrunner.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/commandrunner.py	1970-01-01 00:00:00.000000000 +0000
@@ -1,83 +0,0 @@
-# Copyright 2014 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 program is a wrapper to run external commands. It determines
-what to run, sets up the environment and executes the command."""
-
-import sys, os, subprocess, shutil, shlex
-import re
-
-def run_command(source_dir, build_dir, subdir, meson_command, command, arguments):
-    env = {'MESON_SOURCE_ROOT': source_dir,
-           'MESON_BUILD_ROOT': build_dir,
-           'MESON_SUBDIR': subdir,
-           'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in meson_command + ['introspect']]),
-           }
-    cwd = os.path.join(source_dir, subdir)
-    child_env = os.environ.copy()
-    child_env.update(env)
-
-    # Is the command an executable in path?
-    exe = shutil.which(command)
-    if exe is not None:
-        command_array = [exe] + arguments
-    else:# No? Maybe it is a script in the source tree.
-        fullpath = os.path.join(source_dir, subdir, command)
-        command_array = [fullpath] + arguments
-    try:
-        return subprocess.Popen(command_array, env=child_env, cwd=cwd)
-    except FileNotFoundError:
-        print('Could not execute command "%s". File not found.' % command)
-        sys.exit(1)
-    except PermissionError:
-        print('Could not execute command "%s". File not executable.' % command)
-        sys.exit(1)
-    except OSError as err:
-        print('Could not execute command "{}": {}'.format(command, err))
-        sys.exit(1)
-    except subprocess.SubprocessError as err:
-        print('Could not execute command "{}": {}'.format(command, err))
-        sys.exit(1)
-
-def is_python_command(cmdname):
-    end_py_regex = r'python(3|3\.\d+)?(\.exe)?$'
-    return re.search(end_py_regex, cmdname) is not None
-
-def run(args):
-    if len(args) < 4:
-        print('commandrunner.py     [arguments]')
-        return 1
-    src_dir = args[0]
-    build_dir = args[1]
-    subdir = args[2]
-    meson_command = args[3]
-    if is_python_command(meson_command):
-        meson_command = [meson_command, args[4]]
-        command = args[5]
-        arguments = args[6:]
-    else:
-        meson_command = [meson_command]
-        command = args[4]
-        arguments = args[5:]
-    pc = run_command(src_dir, build_dir, subdir, meson_command, command, arguments)
-    while True:
-        try:
-            pc.wait()
-            break
-        except KeyboardInterrupt:
-            pass
-    return pc.returncode
-
-if __name__ == '__main__':
-    sys.exit(run(sys.argv[1:]))
diff -Nru meson-0.53.2/mesonbuild/scripts/coverage.py meson-0.61.2/mesonbuild/scripts/coverage.py
--- meson-0.53.2/mesonbuild/scripts/coverage.py	2019-05-02 18:59:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/coverage.py	2021-11-02 19:58:13.000000000 +0000
@@ -12,40 +12,58 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from mesonbuild import environment
+from mesonbuild import environment, mesonlib
 
-import argparse, sys, os, subprocess, pathlib
+import argparse, re, sys, os, subprocess, pathlib, stat
+import typing as T
 
-def coverage(outputs, source_root, subproject_root, build_root, log_dir):
+def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build_root: str, log_dir: str, use_llvm_cov: bool) -> int:
     outfiles = []
     exitcode = 0
 
-    (gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe) = environment.find_coverage_tools()
+    (gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools()
 
     # gcovr >= 4.2 requires a different syntax for out of source builds
-    if gcovr_new_rootdir:
+    if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=4.2'):
         gcovr_base_cmd = [gcovr_exe, '-r', source_root, build_root]
     else:
         gcovr_base_cmd = [gcovr_exe, '-r', build_root]
 
+    if use_llvm_cov:
+        gcov_exe_args = ['--gcov-executable', llvm_cov_exe + ' gcov']
+    else:
+        gcov_exe_args = []
+
     if not outputs or 'xml' in outputs:
-        if gcovr_exe:
+        if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'):
             subprocess.check_call(gcovr_base_cmd +
                                   ['-x',
-                                   '-e', subproject_root,
-                                   '-o', os.path.join(log_dir, 'coverage.xml'),
-                                   ])
+                                   '-e', re.escape(subproject_root),
+                                   '-o', os.path.join(log_dir, 'coverage.xml')
+                                   ] + gcov_exe_args)
             outfiles.append(('Xml', pathlib.Path(log_dir, 'coverage.xml')))
         elif outputs:
             print('gcovr >= 3.3 needed to generate Xml coverage report')
             exitcode = 1
 
+    if not outputs or 'sonarqube' in outputs:
+        if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=4.2'):
+            subprocess.check_call(gcovr_base_cmd +
+                                  ['--sonarqube',
+                                   '-o', os.path.join(log_dir, 'sonarqube.xml'),
+                                   '-e', re.escape(subproject_root)
+                                   ] + gcov_exe_args)
+            outfiles.append(('Sonarqube', pathlib.Path(log_dir, 'sonarqube.xml')))
+        elif outputs:
+            print('gcovr >= 4.2 needed to generate Xml coverage report')
+            exitcode = 1
+
     if not outputs or 'text' in outputs:
-        if gcovr_exe:
+        if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'):
             subprocess.check_call(gcovr_base_cmd +
-                                  ['-e', subproject_root,
-                                   '-o', os.path.join(log_dir, 'coverage.txt'),
-                                   ])
+                                  ['-e', re.escape(subproject_root),
+                                   '-o', os.path.join(log_dir, 'coverage.txt')
+                                   ] + gcov_exe_args)
             outfiles.append(('Text', pathlib.Path(log_dir, 'coverage.txt')))
         elif outputs:
             print('gcovr >= 3.3 needed to generate text coverage report')
@@ -58,19 +76,34 @@
             initial_tracefile = covinfo + '.initial'
             run_tracefile = covinfo + '.run'
             raw_tracefile = covinfo + '.raw'
+            if use_llvm_cov:
+                # Create a shim to allow using llvm-cov as a gcov tool.
+                if mesonlib.is_windows():
+                    llvm_cov_shim_path = os.path.join(log_dir, 'llvm-cov.bat')
+                    with open(llvm_cov_shim_path, 'w', encoding='utf-8') as llvm_cov_bat:
+                        llvm_cov_bat.write(f'@"{llvm_cov_exe}" gcov %*')
+                else:
+                    llvm_cov_shim_path = os.path.join(log_dir, 'llvm-cov.sh')
+                    with open(llvm_cov_shim_path, 'w', encoding='utf-8') as llvm_cov_sh:
+                        llvm_cov_sh.write(f'#!/usr/bin/env sh\nexec "{llvm_cov_exe}" gcov $@')
+                    os.chmod(llvm_cov_shim_path, os.stat(llvm_cov_shim_path).st_mode | stat.S_IEXEC)
+                gcov_tool_args = ['--gcov-tool', llvm_cov_shim_path]
+            else:
+                gcov_tool_args = []
             subprocess.check_call([lcov_exe,
                                    '--directory', build_root,
                                    '--capture',
                                    '--initial',
                                    '--output-file',
-                                   initial_tracefile])
+                                   initial_tracefile] +
+                                  gcov_tool_args)
             subprocess.check_call([lcov_exe,
                                    '--directory', build_root,
                                    '--capture',
                                    '--output-file', run_tracefile,
                                    '--no-checksum',
-                                   '--rc', 'lcov_branch_coverage=1',
-                                   ])
+                                   '--rc', 'lcov_branch_coverage=1'] +
+                                  gcov_tool_args)
             # Join initial and test results.
             subprocess.check_call([lcov_exe,
                                    '-a', initial_tracefile,
@@ -99,7 +132,7 @@
                                    '--branch-coverage',
                                    covinfo])
             outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html')))
-        elif gcovr_exe:
+        elif gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'):
             htmloutdir = os.path.join(log_dir, 'coveragereport')
             if not os.path.isdir(htmloutdir):
                 os.mkdir(htmloutdir)
@@ -107,7 +140,7 @@
                                   ['--html',
                                    '--html-details',
                                    '--print-summary',
-                                   '-e', subproject_root,
+                                   '-e', re.escape(subproject_root),
                                    '-o', os.path.join(htmloutdir, 'index.html'),
                                    ])
             outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html')))
@@ -126,7 +159,7 @@
 
     return exitcode
 
-def run(args):
+def run(args: T.List[str]) -> int:
     if not os.path.isfile('build.ninja'):
         print('Coverage currently only works with the Ninja backend.')
         return 1
@@ -135,8 +168,12 @@
                         const='text', help='generate Text report')
     parser.add_argument('--xml', dest='outputs', action='append_const',
                         const='xml', help='generate Xml report')
+    parser.add_argument('--sonarqube', dest='outputs', action='append_const',
+                        const='sonarqube', help='generate Sonarqube Xml report')
     parser.add_argument('--html', dest='outputs', action='append_const',
                         const='html', help='generate Html report')
+    parser.add_argument('--use_llvm_cov', action='store_true',
+                        help='use llvm-cov')
     parser.add_argument('source_root')
     parser.add_argument('subproject_root')
     parser.add_argument('build_root')
@@ -144,7 +181,7 @@
     options = parser.parse_args(args)
     return coverage(options.outputs, options.source_root,
                     options.subproject_root, options.build_root,
-                    options.log_dir)
+                    options.log_dir, options.use_llvm_cov)
 
 if __name__ == '__main__':
     sys.exit(run(sys.argv[1:]))
diff -Nru meson-0.53.2/mesonbuild/scripts/delwithsuffix.py meson-0.61.2/mesonbuild/scripts/delwithsuffix.py
--- meson-0.53.2/mesonbuild/scripts/delwithsuffix.py	2017-05-20 09:00:34.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/delwithsuffix.py	2021-04-01 21:12:21.000000000 +0000
@@ -13,8 +13,9 @@
 # limitations under the License.
 
 import os, sys
+import typing as T
 
-def run(args):
+def run(args: T.List[str]) -> int:
     if len(args) != 2:
         print('delwithsuffix.py  ')
         sys.exit(1)
diff -Nru meson-0.53.2/mesonbuild/scripts/depfixer.py meson-0.61.2/mesonbuild/scripts/depfixer.py
--- meson-0.53.2/mesonbuild/scripts/depfixer.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/depfixer.py	2021-12-26 16:24:25.000000000 +0000
@@ -13,10 +13,15 @@
 # limitations under the License.
 
 
-import sys, struct
-import shutil, subprocess
+import sys
+import os
+import stat
+import struct
+import shutil
+import subprocess
+import typing as T
 
-from ..mesonlib import OrderedSet
+from ..mesonlib import OrderedSet, generate_list
 
 SHT_STRTAB = 3
 DT_NEEDED = 1
@@ -26,8 +31,11 @@
 DT_SONAME = 14
 DT_MIPS_RLD_MAP_REL = 1879048245
 
+# Global cache for tools
+INSTALL_NAME_TOOL = False
+
 class DataSizes:
-    def __init__(self, ptrsize, is_le):
+    def __init__(self, ptrsize: int, is_le: bool) -> None:
         if is_le:
             p = '<'
         else:
@@ -54,7 +62,7 @@
             self.OffSize = 4
 
 class DynamicEntry(DataSizes):
-    def __init__(self, ifile, ptrsize, is_le):
+    def __init__(self, ifile: T.BinaryIO, ptrsize: int, is_le: bool) -> None:
         super().__init__(ptrsize, is_le)
         self.ptrsize = ptrsize
         if ptrsize == 64:
@@ -64,7 +72,7 @@
             self.d_tag = struct.unpack(self.Sword, ifile.read(self.SwordSize))[0]
             self.val = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
 
-    def write(self, ofile):
+    def write(self, ofile: T.BinaryIO) -> None:
         if self.ptrsize == 64:
             ofile.write(struct.pack(self.Sxword, self.d_tag))
             ofile.write(struct.pack(self.XWord, self.val))
@@ -73,7 +81,7 @@
             ofile.write(struct.pack(self.Word, self.val))
 
 class SectionHeader(DataSizes):
-    def __init__(self, ifile, ptrsize, is_le):
+    def __init__(self, ifile: T.BinaryIO, ptrsize: int, is_le: bool) -> None:
         super().__init__(ptrsize, is_le)
         if ptrsize == 64:
             is_64 = True
@@ -113,10 +121,12 @@
             self.sh_entsize = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
 
 class Elf(DataSizes):
-    def __init__(self, bfile, verbose=True):
+    def __init__(self, bfile: str, verbose: bool = True) -> None:
         self.bfile = bfile
         self.verbose = verbose
-        self.bf = open(bfile, 'r+b')
+        self.sections = []  # type: T.List[SectionHeader]
+        self.dynamic = []   # type: T.List[DynamicEntry]
+        self.open_bf(bfile)
         try:
             (self.ptrsize, self.is_le) = self.detect_elf_type()
             super().__init__(self.ptrsize, self.is_le)
@@ -124,43 +134,64 @@
             self.parse_sections()
             self.parse_dynamic()
         except (struct.error, RuntimeError):
-            self.bf.close()
+            self.close_bf()
             raise
 
-    def __enter__(self):
+    def open_bf(self, bfile: str) -> None:
+        self.bf = None
+        self.bf_perms = None
+        try:
+            self.bf = open(bfile, 'r+b')
+        except PermissionError as e:
+            self.bf_perms = stat.S_IMODE(os.lstat(bfile).st_mode)
+            os.chmod(bfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
+            try:
+                self.bf = open(bfile, 'r+b')
+            except Exception:
+                os.chmod(bfile, self.bf_perms)
+                self.bf_perms = None
+                raise e
+
+    def close_bf(self) -> None:
+        if self.bf is not None:
+            if self.bf_perms is not None:
+                os.fchmod(self.bf.fileno(), self.bf_perms)
+                self.bf_perms = None
+            self.bf.close()
+            self.bf = None
+
+    def __enter__(self) -> 'Elf':
         return self
 
-    def __del__(self):
-        if self.bf:
-            self.bf.close()
+    def __del__(self) -> None:
+        self.close_bf()
 
-    def __exit__(self, exc_type, exc_value, traceback):
-        self.bf.close()
-        self.bf = None
+    def __exit__(self, exc_type: T.Any, exc_value: T.Any, traceback: T.Any) -> None:
+        self.close_bf()
 
-    def detect_elf_type(self):
+    def detect_elf_type(self) -> T.Tuple[int, bool]:
         data = self.bf.read(6)
         if data[1:4] != b'ELF':
             # This script gets called to non-elf targets too
             # so just ignore them.
             if self.verbose:
-                print('File "%s" is not an ELF file.' % self.bfile)
+                print(f'File {self.bfile!r} is not an ELF file.')
             sys.exit(0)
         if data[4] == 1:
             ptrsize = 32
         elif data[4] == 2:
             ptrsize = 64
         else:
-            sys.exit('File "%s" has unknown ELF class.' % self.bfile)
+            sys.exit(f'File {self.bfile!r} has unknown ELF class.')
         if data[5] == 1:
             is_le = True
         elif data[5] == 2:
             is_le = False
         else:
-            sys.exit('File "%s" has unknown ELF endianness.' % self.bfile)
+            sys.exit(f'File {self.bfile!r} has unknown ELF endianness.')
         return ptrsize, is_le
 
-    def parse_header(self):
+    def parse_header(self) -> None:
         self.bf.seek(0)
         self.e_ident = struct.unpack('16s', self.bf.read(16))[0]
         self.e_type = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
@@ -177,13 +208,12 @@
         self.e_shnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
         self.e_shstrndx = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
 
-    def parse_sections(self):
+    def parse_sections(self) -> None:
         self.bf.seek(self.e_shoff)
-        self.sections = []
         for _ in range(self.e_shnum):
             self.sections.append(SectionHeader(self.bf, self.ptrsize, self.is_le))
 
-    def read_str(self):
+    def read_str(self) -> bytes:
         arr = []
         x = self.bf.read(1)
         while x != b'\0':
@@ -193,17 +223,17 @@
                 raise RuntimeError('Tried to read past the end of the file')
         return b''.join(arr)
 
-    def find_section(self, target_name):
+    def find_section(self, target_name: bytes) -> T.Optional[SectionHeader]:
         section_names = self.sections[self.e_shstrndx]
         for i in self.sections:
             self.bf.seek(section_names.sh_offset + i.sh_name)
             name = self.read_str()
             if name == target_name:
                 return i
+        return None
 
-    def parse_dynamic(self):
+    def parse_dynamic(self) -> None:
         sec = self.find_section(b'.dynamic')
-        self.dynamic = []
         if sec is None:
             return
         self.bf.seek(sec.sh_offset)
@@ -213,14 +243,14 @@
             if e.d_tag == 0:
                 break
 
-    def print_section_names(self):
+    @generate_list
+    def get_section_names(self) -> T.Generator[str, None, None]:
         section_names = self.sections[self.e_shstrndx]
         for i in self.sections:
             self.bf.seek(section_names.sh_offset + i.sh_name)
-            name = self.read_str()
-            print(name.decode())
+            yield self.read_str().decode()
 
-    def print_soname(self):
+    def get_soname(self) -> T.Optional[str]:
         soname = None
         strtab = None
         for i in self.dynamic:
@@ -229,47 +259,43 @@
             if i.d_tag == DT_STRTAB:
                 strtab = i
         if soname is None or strtab is None:
-            print("This file does not have a soname")
-            return
+            return None
         self.bf.seek(strtab.val + soname.val)
-        print(self.read_str())
+        return self.read_str().decode()
 
-    def get_entry_offset(self, entrynum):
+    def get_entry_offset(self, entrynum: int) -> T.Optional[int]:
         sec = self.find_section(b'.dynstr')
         for i in self.dynamic:
             if i.d_tag == entrynum:
-                return sec.sh_offset + i.val
+                res = sec.sh_offset + i.val
+                assert isinstance(res, int)
+                return res
         return None
 
-    def print_rpath(self):
+    def get_rpath(self) -> T.Optional[str]:
         offset = self.get_entry_offset(DT_RPATH)
         if offset is None:
-            print("This file does not have an rpath.")
-        else:
-            self.bf.seek(offset)
-            print(self.read_str())
+            return None
+        self.bf.seek(offset)
+        return self.read_str().decode()
 
-    def print_runpath(self):
+    def get_runpath(self) -> T.Optional[str]:
         offset = self.get_entry_offset(DT_RUNPATH)
         if offset is None:
-            print("This file does not have a runpath.")
-        else:
-            self.bf.seek(offset)
-            print(self.read_str())
+            return None
+        self.bf.seek(offset)
+        return self.read_str().decode()
 
-    def print_deps(self):
+    @generate_list
+    def get_deps(self) -> T.Generator[str, None, None]:
         sec = self.find_section(b'.dynstr')
-        deps = []
         for i in self.dynamic:
             if i.d_tag == DT_NEEDED:
-                deps.append(i)
-        for i in deps:
-            offset = sec.sh_offset + i.val
-            self.bf.seek(offset)
-            name = self.read_str()
-            print(name)
+                offset = sec.sh_offset + i.val
+                self.bf.seek(offset)
+                yield self.read_str().decode()
 
-    def fix_deps(self, prefix):
+    def fix_deps(self, prefix: bytes) -> None:
         sec = self.find_section(b'.dynstr')
         deps = []
         for i in self.dynamic:
@@ -283,28 +309,46 @@
                 basename = name.split(b'/')[-1]
                 padding = b'\0' * (len(name) - len(basename))
                 newname = basename + padding
-                assert(len(newname) == len(name))
+                assert len(newname) == len(name)
                 self.bf.seek(offset)
                 self.bf.write(newname)
 
-    def fix_rpath(self, new_rpath):
+    def fix_rpath(self, fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: bytes) -> None:
         # The path to search for can be either rpath or runpath.
         # Fix both of them to be sure.
-        self.fix_rpathtype_entry(new_rpath, DT_RPATH)
-        self.fix_rpathtype_entry(new_rpath, DT_RUNPATH)
+        self.fix_rpathtype_entry(fname, rpath_dirs_to_remove, new_rpath, DT_RPATH)
+        self.fix_rpathtype_entry(fname, rpath_dirs_to_remove, new_rpath, DT_RUNPATH)
 
-    def fix_rpathtype_entry(self, new_rpath, entrynum):
-        if isinstance(new_rpath, str):
-            new_rpath = new_rpath.encode('utf8')
+    def fix_rpathtype_entry(self, fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: bytes, entrynum: int) -> None:
         rp_off = self.get_entry_offset(entrynum)
         if rp_off is None:
             if self.verbose:
-                print('File does not have rpath. It should be a fully static executable.')
+                print(f'File {fname!r} does not have an rpath. It should be a fully static executable.')
             return
         self.bf.seek(rp_off)
+
         old_rpath = self.read_str()
+        # Some rpath entries may come from multiple sources.
+        # Only add each one once.
+        new_rpaths = OrderedSet()  # type: OrderedSet[bytes]
+        if new_rpath:
+            new_rpaths.update(new_rpath.split(b':'))
+        if old_rpath:
+            # Filter out build-only rpath entries
+            # added by get_link_dep_subdirs() or
+            # specified by user with build_rpath.
+            for rpath_dir in old_rpath.split(b':'):
+                if not (rpath_dir in rpath_dirs_to_remove or
+                        rpath_dir == (b'X' * len(rpath_dir))):
+                    if rpath_dir:
+                        new_rpaths.add(rpath_dir)
+
+        # Prepend user-specified new entries while preserving the ones that came from pkgconfig etc.
+        new_rpath = b':'.join(new_rpaths)
+
         if len(old_rpath) < len(new_rpath):
-            sys.exit("New rpath must not be longer than the old one.")
+            msg = "New rpath must not be longer than the old one.\n Old: {}\n New: {}".format(old_rpath.decode('utf-8'), new_rpath.decode('utf-8'))
+            sys.exit(msg)
         # The linker does read-only string deduplication. If there is a
         # string that shares a suffix with the rpath, they might get
         # dedupped. This means changing the rpath string might break something
@@ -320,7 +364,7 @@
             self.bf.write(new_rpath)
             self.bf.write(b'\0')
 
-    def remove_rpath_entry(self, entrynum):
+    def remove_rpath_entry(self, entrynum: int) -> None:
         sec = self.find_section(b'.dynamic')
         if sec is None:
             return None
@@ -340,15 +384,13 @@
             entry.write(self.bf)
         return None
 
-def fix_elf(fname, new_rpath, verbose=True):
-    with Elf(fname, verbose) as e:
-        if new_rpath is None:
-            e.print_rpath()
-            e.print_runpath()
-        else:
-            e.fix_rpath(new_rpath)
+def fix_elf(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Optional[bytes], verbose: bool = True) -> None:
+    if new_rpath is not None:
+        with Elf(fname, verbose) as e:
+            # note: e.get_rpath() and e.get_runpath() may be useful
+            e.fix_rpath(fname, rpath_dirs_to_remove, new_rpath)
 
-def get_darwin_rpaths_to_remove(fname):
+def get_darwin_rpaths_to_remove(fname: str) -> T.List[str]:
     out = subprocess.check_output(['otool', '-l', fname],
                                   universal_newlines=True,
                                   stderr=subprocess.DEVNULL)
@@ -366,7 +408,7 @@
             result.append(rp)
     return result
 
-def fix_darwin(fname, new_rpath, final_path, install_name_mappings):
+def fix_darwin(fname: str, new_rpath: str, final_path: str, install_name_mappings: T.Dict[str, str]) -> None:
     try:
         rpaths = get_darwin_rpaths_to_remove(fname)
     except subprocess.CalledProcessError:
@@ -416,9 +458,9 @@
     except Exception as err:
         raise SystemExit(err)
 
-def fix_jar(fname):
+def fix_jar(fname: str) -> None:
     subprocess.check_call(['jar', 'xfv', fname, 'META-INF/MANIFEST.MF'])
-    with open('META-INF/MANIFEST.MF', 'r+') as f:
+    with open('META-INF/MANIFEST.MF', 'r+', encoding='utf-8') as f:
         lines = f.readlines()
         f.seek(0)
         for line in lines:
@@ -427,23 +469,33 @@
         f.truncate()
     subprocess.check_call(['jar', 'ufm', fname, 'META-INF/MANIFEST.MF'])
 
-def fix_rpath(fname, new_rpath, final_path, install_name_mappings, verbose=True):
-    # Static libraries never have rpaths
-    if fname.endswith('.a'):
-        return
-    # DLLs and EXE never have rpaths
-    if fname.endswith('.dll') or fname.endswith('.exe'):
+def fix_rpath(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Union[str, bytes], final_path: str, install_name_mappings: T.Dict[str, str], verbose: bool = True) -> None:
+    global INSTALL_NAME_TOOL
+    # Static libraries, import libraries, debug information, headers, etc
+    # never have rpaths
+    # DLLs and EXE currently do not need runtime path fixing
+    if fname.endswith(('.a', '.lib', '.pdb', '.h', '.hpp', '.dll', '.exe')):
         return
     try:
         if fname.endswith('.jar'):
             fix_jar(fname)
             return
-        fix_elf(fname, new_rpath, verbose)
+        if isinstance(new_rpath, str):
+            new_rpath = new_rpath.encode('utf8')
+        fix_elf(fname, rpath_dirs_to_remove, new_rpath, verbose)
         return
     except SystemExit as e:
         if isinstance(e.code, int) and e.code == 0:
             pass
         else:
             raise
-    if shutil.which('install_name_tool'):
+    # We don't look for this on import because it will do a useless PATH lookup
+    # on non-mac platforms. That can be expensive on some Windows machines
+    # (up to 30ms), which is significant with --only-changed. For details, see:
+    # https://github.com/mesonbuild/meson/pull/6612#discussion_r378581401
+    if INSTALL_NAME_TOOL is False:
+        INSTALL_NAME_TOOL = bool(shutil.which('install_name_tool'))
+    if INSTALL_NAME_TOOL:
+        if isinstance(new_rpath, bytes):
+            new_rpath = new_rpath.decode('utf8')
         fix_darwin(fname, new_rpath, final_path, install_name_mappings)
diff -Nru meson-0.53.2/mesonbuild/scripts/depscan.py meson-0.61.2/mesonbuild/scripts/depscan.py
--- meson-0.53.2/mesonbuild/scripts/depscan.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/depscan.py	2021-11-02 19:58:13.000000000 +0000
@@ -0,0 +1,202 @@
+# Copyright 2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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 json
+import os
+import pathlib
+import pickle
+import re
+import sys
+import typing as T
+
+from ..backend.ninjabackend import TargetDependencyScannerInfo, ninja_quote
+from ..compilers.compilers import lang_suffixes
+
+CPP_IMPORT_RE = re.compile(r'\w*import ([a-zA-Z0-9]+);')
+CPP_EXPORT_RE = re.compile(r'\w*export module ([a-zA-Z0-9]+);')
+
+FORTRAN_INCLUDE_PAT = r"^\s*include\s*['\"](\w+\.\w+)['\"]"
+FORTRAN_MODULE_PAT = r"^\s*\bmodule\b\s+(\w+)\s*(?:!+.*)*$"
+FORTRAN_SUBMOD_PAT = r"^\s*\bsubmodule\b\s*\((\w+:?\w+)\)\s*(\w+)"
+FORTRAN_USE_PAT = r"^\s*use,?\s*(?:non_intrinsic)?\s*(?:::)?\s*(\w+)"
+
+FORTRAN_MODULE_RE = re.compile(FORTRAN_MODULE_PAT, re.IGNORECASE)
+FORTRAN_SUBMOD_RE = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE)
+FORTRAN_USE_RE = re.compile(FORTRAN_USE_PAT, re.IGNORECASE)
+
+class DependencyScanner:
+    def __init__(self, pickle_file: str, outfile: str, sources: T.List[str]):
+        with open(pickle_file, 'rb') as pf:
+            self.target_data = pickle.load(pf) # type: TargetDependencyScannerInfo
+        self.outfile = outfile
+        self.sources = sources
+        self.provided_by = {} # type: T.Dict[str, str]
+        self.exports = {} # type: T.Dict[str, str]
+        self.needs = {} # type: T.Dict[str, T.List[str]]
+        self.sources_with_exports = [] # type: T.List[str]
+
+    def scan_file(self, fname: str) -> None:
+        suffix = os.path.splitext(fname)[1][1:].lower()
+        if suffix in lang_suffixes['fortran']:
+            self.scan_fortran_file(fname)
+        elif suffix in lang_suffixes['cpp']:
+            self.scan_cpp_file(fname)
+        else:
+            sys.exit(f'Can not scan files with suffix .{suffix}.')
+
+    def scan_fortran_file(self, fname: str) -> None:
+        fpath = pathlib.Path(fname)
+        modules_in_this_file = set()
+        for line in fpath.read_text(encoding='utf-8').split('\n'):
+            import_match = FORTRAN_USE_RE.match(line)
+            export_match = FORTRAN_MODULE_RE.match(line)
+            submodule_export_match = FORTRAN_SUBMOD_RE.match(line)
+            if import_match:
+                needed = import_match.group(1).lower()
+                # In Fortran you have an using declaration also for the module
+                # you define in the same file. Prevent circular dependencies.
+                if needed not in modules_in_this_file:
+                    if fname in self.needs:
+                        self.needs[fname].append(needed)
+                    else:
+                        self.needs[fname] = [needed]
+            if export_match:
+                exported_module = export_match.group(1).lower()
+                assert exported_module not in modules_in_this_file
+                modules_in_this_file.add(exported_module)
+                if exported_module in self.provided_by:
+                    raise RuntimeError(f'Multiple files provide module {exported_module}.')
+                self.sources_with_exports.append(fname)
+                self.provided_by[exported_module] = fname
+                self.exports[fname] = exported_module
+            if submodule_export_match:
+                # Store submodule "Foo" "Bar" as "foo:bar".
+                # A submodule declaration can be both an import and an export declaration:
+                #
+                # submodule (a1:a2) a3
+                #  - requires a1@a2.smod
+                #  - produces a1@a3.smod
+                parent_module_name_full = submodule_export_match.group(1).lower()
+                parent_module_name = parent_module_name_full.split(':')[0]
+                submodule_name = submodule_export_match.group(2).lower()
+                concat_name = f'{parent_module_name}:{submodule_name}'
+                self.sources_with_exports.append(fname)
+                self.provided_by[concat_name] = fname
+                self.exports[fname] = concat_name
+                # Fortran requires that the immediate parent module must be built
+                # before the current one. Thus:
+                #
+                # submodule (parent) parent   <- requires parent.mod (really parent.smod, but they are created at the same time)
+                # submodule (a1:a2) a3        <- requires a1@a2.smod
+                #
+                # a3 does not depend on the a1 parent module directly, only transitively.
+                if fname in self.needs:
+                    self.needs[fname].append(parent_module_name_full)
+                else:
+                    self.needs[fname] = [parent_module_name_full]
+
+    def scan_cpp_file(self, fname: str) -> None:
+        fpath = pathlib.Path(fname)
+        for line in fpath.read_text(encoding='utf-8').split('\n'):
+            import_match = CPP_IMPORT_RE.match(line)
+            export_match = CPP_EXPORT_RE.match(line)
+            if import_match:
+                needed = import_match.group(1)
+                if fname in self.needs:
+                    self.needs[fname].append(needed)
+                else:
+                    self.needs[fname] = [needed]
+            if export_match:
+                exported_module = export_match.group(1)
+                if exported_module in self.provided_by:
+                    raise RuntimeError(f'Multiple files provide module {exported_module}.')
+                self.sources_with_exports.append(fname)
+                self.provided_by[exported_module] = fname
+                self.exports[fname] = exported_module
+
+    def objname_for(self, src: str) -> str:
+        objname = self.target_data.source2object[src]
+        assert isinstance(objname, str)
+        return objname
+
+    def module_name_for(self, src: str) -> str:
+        suffix = os.path.splitext(src)[1][1:].lower()
+        if suffix in lang_suffixes['fortran']:
+            exported = self.exports[src]
+            # Module foo:bar goes to a file name foo@bar.smod
+            # Module Foo goes to a file name foo.mod
+            namebase = exported.replace(':', '@')
+            if ':' in exported:
+                extension = 'smod'
+            else:
+                extension = 'mod'
+            return os.path.join(self.target_data.private_dir, f'{namebase}.{extension}')
+        elif suffix in lang_suffixes['cpp']:
+            return '{}.ifc'.format(self.exports[src])
+        else:
+            raise RuntimeError('Unreachable code.')
+
+    def scan(self) -> int:
+        for s in self.sources:
+            self.scan_file(s)
+        with open(self.outfile, 'w', encoding='utf-8') as ofile:
+            ofile.write('ninja_dyndep_version = 1\n')
+            for src in self.sources:
+                objfilename = self.objname_for(src)
+                mods_and_submods_needed = []
+                module_files_generated = []
+                module_files_needed = []
+                if src in self.sources_with_exports:
+                    module_files_generated.append(self.module_name_for(src))
+                if src in self.needs:
+                    for modname in self.needs[src]:
+                        if modname not in self.provided_by:
+                            # Nothing provides this module, we assume that it
+                            # comes from a dependency library somewhere and is
+                            # already built by the time this compilation starts.
+                            pass
+                        else:
+                            mods_and_submods_needed.append(modname)
+
+                for modname in mods_and_submods_needed:
+                    provider_src = self.provided_by[modname]
+                    provider_modfile = self.module_name_for(provider_src)
+                    # Prune self-dependencies
+                    if provider_src != src:
+                        module_files_needed.append(provider_modfile)
+
+                quoted_objfilename = ninja_quote(objfilename, True)
+                quoted_module_files_generated = [ninja_quote(x, True) for x in module_files_generated]
+                quoted_module_files_needed = [ninja_quote(x, True) for x in module_files_needed]
+                if quoted_module_files_generated:
+                    mod_gen = '| ' + ' '.join(quoted_module_files_generated)
+                else:
+                    mod_gen = ''
+                if quoted_module_files_needed:
+                    mod_dep = '| ' + ' '.join(quoted_module_files_needed)
+                else:
+                    mod_dep = ''
+                build_line = 'build {} {}: dyndep {}'.format(quoted_objfilename,
+                                                             mod_gen,
+                                                             mod_dep)
+                ofile.write(build_line + '\n')
+        return 0
+
+def run(args: T.List[str]) -> int:
+    assert len(args) == 3, 'got wrong number of arguments!'
+    pickle_file, outfile, jsonfile = args
+    with open(jsonfile, encoding='utf-8') as f:
+        sources = json.load(f)
+    scanner = DependencyScanner(pickle_file, outfile, sources)
+    return scanner.scan()
diff -Nru meson-0.53.2/mesonbuild/scripts/dirchanger.py meson-0.61.2/mesonbuild/scripts/dirchanger.py
--- meson-0.53.2/mesonbuild/scripts/dirchanger.py	2016-12-18 18:47:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/dirchanger.py	2021-04-01 21:12:21.000000000 +0000
@@ -16,8 +16,9 @@
 the command given in the rest of the arguments.'''
 
 import os, subprocess, sys
+import typing as T
 
-def run(args):
+def run(args: T.List[str]) -> int:
     dirname = args[0]
     command = args[1:]
 
diff -Nru meson-0.53.2/mesonbuild/scripts/externalproject.py meson-0.61.2/mesonbuild/scripts/externalproject.py
--- meson-0.53.2/mesonbuild/scripts/externalproject.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/externalproject.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,119 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import argparse
+import multiprocessing
+import subprocess
+from pathlib import Path
+import typing as T
+
+from ..mesonlib import Popen_safe, split_args
+
+class ExternalProject:
+    def __init__(self, options: argparse.Namespace):
+        self.name = options.name
+        self.src_dir = options.srcdir
+        self.build_dir = options.builddir
+        self.install_dir = options.installdir
+        self.log_dir = options.logdir
+        self.verbose = options.verbose
+        self.stampfile = options.stampfile
+        self.depfile = options.depfile
+        self.make = split_args(options.make)
+
+    def write_depfile(self) -> None:
+        with open(self.depfile, 'w', encoding='utf-8') as f:
+            f.write(f'{self.stampfile}: \\\n')
+            for dirpath, dirnames, filenames in os.walk(self.src_dir):
+                dirnames[:] = [d for d in dirnames if not d.startswith('.')]
+                for fname in filenames:
+                    if fname.startswith('.'):
+                        continue
+                    path = Path(dirpath, fname)
+                    f.write('  {} \\\n'.format(path.as_posix().replace(' ', '\\ ')))
+
+    def write_stampfile(self) -> None:
+        with open(self.stampfile, 'w', encoding='utf-8'):
+            pass
+
+    def gnu_make(self) -> bool:
+        p, o, e = Popen_safe(self.make + ['--version'])
+        if p.returncode == 0 and 'GNU Make' in o:
+            return True
+        return False
+
+    def build(self) -> int:
+        is_make = self.make[0] == 'make'
+        make_cmd = self.make.copy()
+        if is_make and self.gnu_make():
+            make_cmd.append(f'-j{multiprocessing.cpu_count()}')
+        rc = self._run('build', make_cmd)
+        if rc != 0:
+            return rc
+
+        install_cmd = self.make.copy()
+        install_env = {}
+        if is_make:
+            install_cmd.append(f'DESTDIR={self.install_dir}')
+        else:
+            install_env['DESTDIR'] = self.install_dir
+        install_cmd.append('install')
+        rc = self._run('install', install_cmd, install_env)
+        if rc != 0:
+            return rc
+
+        self.write_depfile()
+        self.write_stampfile()
+
+        return 0
+
+    def _run(self, step: str, command: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> int:
+        m = 'Running command ' + str(command) + ' in directory ' + str(self.build_dir) + '\n'
+        log_filename = Path(self.log_dir, f'{self.name}-{step}.log')
+        output = None
+        if not self.verbose:
+            output = open(log_filename, 'w', encoding='utf-8')
+            output.write(m + '\n')
+            output.flush()
+        else:
+            print(m)
+        run_env = os.environ.copy()
+        if env:
+            run_env.update(env)
+        p, o, e = Popen_safe(command, stderr=subprocess.STDOUT, stdout=output,
+                             cwd=self.build_dir,
+                             env=run_env)
+        if p.returncode != 0:
+            m = f'{step} step returned error code {p.returncode}.'
+            if not self.verbose:
+                m += '\nSee logs: ' + str(log_filename)
+            print(m)
+        return p.returncode
+
+def run(args: T.List[str]) -> int:
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--name')
+    parser.add_argument('--srcdir')
+    parser.add_argument('--builddir')
+    parser.add_argument('--installdir')
+    parser.add_argument('--logdir')
+    parser.add_argument('--make')
+    parser.add_argument('--verbose', action='store_true')
+    parser.add_argument('stampfile')
+    parser.add_argument('depfile')
+
+    options = parser.parse_args(args)
+    ep = ExternalProject(options)
+    return ep.build()
diff -Nru meson-0.53.2/mesonbuild/scripts/gettext.py meson-0.61.2/mesonbuild/scripts/gettext.py
--- meson-0.53.2/mesonbuild/scripts/gettext.py	2019-04-17 08:08:43.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/gettext.py	2021-11-02 19:58:07.000000000 +0000
@@ -13,10 +13,9 @@
 # limitations under the License.
 
 import os
-import shutil
 import argparse
 import subprocess
-from . import destdir_join
+import typing as T
 
 parser = argparse.ArgumentParser()
 parser.add_argument('command')
@@ -27,23 +26,23 @@
 parser.add_argument('--subdir', default='')
 parser.add_argument('--extra-args', default='')
 
-def read_linguas(src_sub):
+def read_linguas(src_sub: str) -> T.List[str]:
     # Syntax of this file is documented here:
     # https://www.gnu.org/software/gettext/manual/html_node/po_002fLINGUAS.html
     linguas = os.path.join(src_sub, 'LINGUAS')
     try:
         langs = []
-        with open(linguas) as f:
+        with open(linguas, encoding='utf-8') as f:
             for line in f:
                 line = line.strip()
                 if line and not line.startswith('#'):
                     langs += line.split()
         return langs
     except (FileNotFoundError, PermissionError):
-        print('Could not find file LINGUAS in {}'.format(src_sub))
+        print(f'Could not find file LINGUAS in {src_sub}')
         return []
 
-def run_potgen(src_sub, pkgname, datadirs, args):
+def run_potgen(src_sub: str, pkgname: str, datadirs: str, args: T.List[str]) -> int:
     listfile = os.path.join(src_sub, 'POTFILES.in')
     if not os.path.exists(listfile):
         listfile = os.path.join(src_sub, 'POTFILES')
@@ -60,13 +59,7 @@
                             '-D', os.environ['MESON_SOURCE_ROOT'], '-k_', '-o', ofile] + args,
                            env=child_env)
 
-def gen_gmo(src_sub, bld_sub, langs):
-    for l in langs:
-        subprocess.check_call(['msgfmt', os.path.join(src_sub, l + '.po'),
-                               '-o', os.path.join(bld_sub, l + '.gmo')])
-    return 0
-
-def update_po(src_sub, pkgname, langs):
+def update_po(src_sub: str, pkgname: str, langs: T.List[str]) -> int:
     potfile = os.path.join(src_sub, pkgname + '.pot')
     for l in langs:
         pofile = os.path.join(src_sub, l + '.po')
@@ -76,20 +69,7 @@
             subprocess.check_call(['msginit', '--input', potfile, '--output-file', pofile, '--locale', l, '--no-translator'])
     return 0
 
-def do_install(src_sub, bld_sub, dest, pkgname, langs):
-    for l in langs:
-        srcfile = os.path.join(bld_sub, l + '.gmo')
-        outfile = os.path.join(dest, l, 'LC_MESSAGES',
-                               pkgname + '.mo')
-        tempfile = outfile + '.tmp'
-        os.makedirs(os.path.dirname(outfile), exist_ok=True)
-        shutil.copyfile(srcfile, tempfile)
-        shutil.copystat(srcfile, tempfile)
-        os.replace(tempfile, outfile)
-        print('Installing %s to %s' % (srcfile, outfile))
-    return 0
-
-def run(args):
+def run(args: T.List[str]) -> int:
     options = parser.parse_args(args)
     subcmd = options.command
     langs = options.langs.split('@@') if options.langs else None
@@ -98,26 +78,16 @@
     if options.subdir:
         subdir = options.subdir
     src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], subdir)
-    bld_sub = os.path.join(os.environ['MESON_BUILD_ROOT'], subdir)
 
     if not langs:
         langs = read_linguas(src_sub)
 
     if subcmd == 'pot':
         return run_potgen(src_sub, options.pkgname, options.datadirs, extra_args)
-    elif subcmd == 'gen_gmo':
-        return gen_gmo(src_sub, bld_sub, langs)
     elif subcmd == 'update_po':
         if run_potgen(src_sub, options.pkgname, options.datadirs, extra_args) != 0:
             return 1
         return update_po(src_sub, options.pkgname, langs)
-    elif subcmd == 'install':
-        destdir = os.environ.get('DESTDIR', '')
-        dest = destdir_join(destdir, os.path.join(os.environ['MESON_INSTALL_PREFIX'],
-                                                  options.localedir))
-        if gen_gmo(src_sub, bld_sub, langs) != 0:
-            return 1
-        do_install(src_sub, bld_sub, dest, options.pkgname, langs)
     else:
         print('Unknown subcommand.')
         return 1
diff -Nru meson-0.53.2/mesonbuild/scripts/gtkdochelper.py meson-0.61.2/mesonbuild/scripts/gtkdochelper.py
--- meson-0.53.2/mesonbuild/scripts/gtkdochelper.py	2019-09-16 21:20:45.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/gtkdochelper.py	2021-04-27 06:49:45.000000000 +0000
@@ -16,8 +16,9 @@
 import subprocess
 import shutil
 import argparse
-from ..mesonlib import MesonException, Popen_safe, is_windows, split_args
+from ..mesonlib import MesonException, Popen_safe, is_windows, is_cygwin, split_args
 from . import destdir_join
+import typing as T
 
 parser = argparse.ArgumentParser()
 
@@ -50,12 +51,12 @@
     program_name = 'gtkdoc-' + tool
     parser.add_argument('--' + program_name, dest=program_name.replace('-', '_'))
 
-def gtkdoc_run_check(cmd, cwd, library_paths=None):
+def gtkdoc_run_check(cmd: T.List[str], cwd: str, library_paths: T.Optional[T.List[str]] = None) -> None:
     if library_paths is None:
         library_paths = []
 
     env = dict(os.environ)
-    if is_windows():
+    if is_windows() or is_cygwin():
         if 'PATH' in env:
             library_paths.extend(env['PATH'].split(os.pathsep))
         env['PATH'] = os.pathsep.join(library_paths)
@@ -64,23 +65,33 @@
             library_paths.extend(env['LD_LIBRARY_PATH'].split(os.pathsep))
         env['LD_LIBRARY_PATH'] = os.pathsep.join(library_paths)
 
+    if is_windows():
+        cmd.insert(0, sys.executable)
+
     # Put stderr into stdout since we want to print it out anyway.
     # This preserves the order of messages.
     p, out = Popen_safe(cmd, cwd=cwd, env=env, stderr=subprocess.STDOUT)[0:2]
     if p.returncode != 0:
-        err_msg = ["{!r} failed with status {:d}".format(cmd, p.returncode)]
+        err_msg = [f"{cmd!r} failed with status {p.returncode:d}"]
         if out:
             err_msg.append(out)
         raise MesonException('\n'.join(err_msg))
     elif out:
-        print(out)
-
-def build_gtkdoc(source_root, build_root, doc_subdir, src_subdirs,
-                 main_file, module, module_version,
-                 html_args, scan_args, fixxref_args, mkdb_args,
-                 gobject_typesfile, scanobjs_args, run, ld, cc, ldflags, cflags,
-                 html_assets, content_files, ignore_headers, namespace,
-                 expand_content_files, mode, options):
+        # Unfortunately Windows cmd.exe consoles may be using a codepage
+        # that might choke print() with a UnicodeEncodeError, so let's
+        # ignore such errors for now, as a compromise as we are outputting
+        # console output here...
+        try:
+            print(out)
+        except UnicodeEncodeError:
+            pass
+
+def build_gtkdoc(source_root: str, build_root: str, doc_subdir: str, src_subdirs: T.List[str],
+                 main_file: str, module: str, module_version: str,
+                 html_args: T.List[str], scan_args: T.List[str], fixxref_args: T.List[str], mkdb_args: T.List[str],
+                 gobject_typesfile: str, scanobjs_args: T.List[str], run: str, ld: str, cc: str, ldflags: str, cflags: str,
+                 html_assets: T.List[str], content_files: T.List[str], ignore_headers: T.List[str], namespace: str,
+                 expand_content_files: T.List[str], mode: str, options: argparse.Namespace) -> None:
     print("Building documentation for %s" % module)
 
     src_dir_args = []
@@ -204,16 +215,16 @@
     gtkdoc_run_check(fixref_cmd, abs_out)
 
     if module_version:
-        shutil.move(os.path.join(htmldir, '{}.devhelp2'.format(module)),
-                    os.path.join(htmldir, '{}-{}.devhelp2'.format(module, module_version)))
+        shutil.move(os.path.join(htmldir, f'{module}.devhelp2'),
+                    os.path.join(htmldir, f'{module}-{module_version}.devhelp2'))
 
-def install_gtkdoc(build_root, doc_subdir, install_prefix, datadir, module):
+def install_gtkdoc(build_root: str, doc_subdir: str, install_prefix: str, datadir: str, module: str) -> None:
     source = os.path.join(build_root, doc_subdir, 'html')
     final_destination = os.path.join(install_prefix, datadir, module)
     shutil.rmtree(final_destination, ignore_errors=True)
     shutil.copytree(source, final_destination)
 
-def run(args):
+def run(args: T.List[str]) -> int:
     options = parser.parse_args(args)
     if options.htmlargs:
         htmlargs = options.htmlargs.split('@@')
diff -Nru meson-0.53.2/mesonbuild/scripts/hotdochelper.py meson-0.61.2/mesonbuild/scripts/hotdochelper.py
--- meson-0.53.2/mesonbuild/scripts/hotdochelper.py	2018-10-31 09:31:20.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/hotdochelper.py	2021-04-01 21:12:21.000000000 +0000
@@ -5,6 +5,7 @@
 from . import destdir_join
 
 import argparse
+import typing as T
 
 parser = argparse.ArgumentParser()
 parser.add_argument('--install')
@@ -14,7 +15,7 @@
 parser.add_argument('--project-version')
 
 
-def run(argv):
+def run(argv: T.List[str]) -> int:
     options, args = parser.parse_known_args(argv)
     subenv = os.environ.copy()
 
@@ -23,7 +24,7 @@
 
     res = subprocess.call(args, cwd=options.builddir, env=subenv)
     if res != 0:
-        exit(res)
+        return res
 
     if options.install:
         source_dir = os.path.join(options.builddir, options.install)
@@ -34,3 +35,4 @@
 
         shutil.rmtree(installdir, ignore_errors=True)
         shutil.copytree(source_dir, installdir)
+    return 0
diff -Nru meson-0.53.2/mesonbuild/scripts/__init__.py meson-0.61.2/mesonbuild/scripts/__init__.py
--- meson-0.53.2/mesonbuild/scripts/__init__.py	2017-01-12 20:52:44.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/__init__.py	2021-04-01 21:12:21.000000000 +0000
@@ -12,7 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-def destdir_join(d1, d2):
+# TODO: consider switching to pathlib for this
+def destdir_join(d1: str, d2: str) -> str:
     # c:\destdir + c:\prefix must produce c:\destdir\prefix
     if len(d1) > 1 and d1[1] == ':' \
             and len(d2) > 1 and d2[1] == ':':
diff -Nru meson-0.53.2/mesonbuild/scripts/meson_exe.py meson-0.61.2/mesonbuild/scripts/meson_exe.py
--- meson-0.53.2/mesonbuild/scripts/meson_exe.py	2019-09-16 21:20:45.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/meson_exe.py	2021-12-26 16:24:25.000000000 +0000
@@ -16,74 +16,91 @@
 import sys
 import argparse
 import pickle
-import platform
 import subprocess
+import typing as T
+import locale
 
 from .. import mesonlib
 from ..backend.backends import ExecutableSerialisation
 
 options = None
 
-def buildparser():
+def buildparser() -> argparse.ArgumentParser:
     parser = argparse.ArgumentParser(description='Custom executable wrapper for Meson. Do not run on your own, mmm\'kay?')
     parser.add_argument('--unpickle')
     parser.add_argument('--capture')
+    parser.add_argument('--feed')
     return parser
 
-def is_windows():
-    platname = platform.system().lower()
-    return platname == 'windows' or 'mingw' in platname
-
-def is_cygwin():
-    platname = platform.system().lower()
-    return 'cygwin' in platname
-
-def run_exe(exe):
-    if exe.exe_runner:
-        if not exe.exe_runner.found():
+def run_exe(exe: ExecutableSerialisation, extra_env: T.Optional[T.Dict[str, str]] = None) -> int:
+    if exe.exe_wrapper:
+        if not exe.exe_wrapper.found():
             raise AssertionError('BUG: Can\'t run cross-compiled exe {!r} with not-found '
-                                 'wrapper {!r}'.format(exe.cmd_args[0], exe.exe_runner.get_path()))
-        cmd_args = exe.exe_runner.get_command() + exe.cmd_args
+                                 'wrapper {!r}'.format(exe.cmd_args[0], exe.exe_wrapper.get_path()))
+        cmd_args = exe.exe_wrapper.get_command() + exe.cmd_args
     else:
         cmd_args = exe.cmd_args
     child_env = os.environ.copy()
-    child_env.update(exe.env)
+    if extra_env:
+        child_env.update(extra_env)
+    if exe.env:
+        child_env = exe.env.get_env(child_env)
     if exe.extra_paths:
         child_env['PATH'] = (os.pathsep.join(exe.extra_paths + ['']) +
                              child_env['PATH'])
-        if exe.exe_runner and mesonlib.substring_is_in_list('wine', exe.exe_runner.get_command()):
+        if exe.exe_wrapper and mesonlib.substring_is_in_list('wine', exe.exe_wrapper.get_command()):
             child_env['WINEPATH'] = mesonlib.get_wine_shortpath(
-                exe.exe_runner.get_command(),
+                exe.exe_wrapper.get_command(),
                 ['Z:' + p for p in exe.extra_paths] + child_env.get('WINEPATH', '').split(';')
             )
 
+    stdin = None
+    if exe.feed:
+        stdin = open(exe.feed, 'rb')
+
+    pipe = subprocess.PIPE
+    if exe.verbose:
+        assert not exe.capture, 'Cannot capture and print to console at the same time'
+        pipe = None
+
     p = subprocess.Popen(cmd_args, env=child_env, cwd=exe.workdir,
-                         close_fds=False,
-                         stdout=subprocess.PIPE,
-                         stderr=subprocess.PIPE)
+                         close_fds=False, stdin=stdin, stdout=pipe, stderr=pipe)
     stdout, stderr = p.communicate()
 
+    if stdin is not None:
+        stdin.close()
+
     if p.returncode == 0xc0000135:
         # STATUS_DLL_NOT_FOUND on Windows indicating a common problem that is otherwise hard to diagnose
-        raise FileNotFoundError('Missing DLLs on calling {!r}'.format(exe.name))
+        raise FileNotFoundError('due to missing DLLs')
+
+    if p.returncode != 0:
+        if exe.pickled:
+            print(f'while executing {cmd_args!r}')
+        if exe.verbose:
+            return p.returncode
+        encoding = locale.getpreferredencoding()
+        if not exe.capture:
+            print('--- stdout ---')
+            print(stdout.decode(encoding=encoding, errors='replace'))
+        print('--- stderr ---')
+        print(stderr.decode(encoding=encoding, errors='replace'))
+        return p.returncode
 
-    if exe.capture and p.returncode == 0:
+    if exe.capture:
         skip_write = False
         try:
             with open(exe.capture, 'rb') as cur:
                 skip_write = cur.read() == stdout
-        except IOError:
+        except OSError:
             pass
         if not skip_write:
             with open(exe.capture, 'wb') as output:
                 output.write(stdout)
-    else:
-        sys.stdout.buffer.write(stdout)
-    if stderr:
-        sys.stderr.buffer.write(stderr)
-    return p.returncode
 
-def run(args):
+    return 0
+
+def run(args: T.List[str]) -> int:
     global options
     parser = buildparser()
     options, cmd_args = parser.parse_known_args(args)
@@ -94,12 +111,13 @@
     if not options.unpickle and not cmd_args:
         parser.error('either --unpickle or executable and arguments are required')
     if options.unpickle:
-        if cmd_args or options.capture:
+        if cmd_args or options.capture or options.feed:
             parser.error('no other arguments can be used with --unpickle')
         with open(options.unpickle, 'rb') as f:
             exe = pickle.load(f)
+            exe.pickled = True
     else:
-        exe = ExecutableSerialisation(cmd_args, capture=options.capture)
+        exe = ExecutableSerialisation(cmd_args, capture=options.capture, feed=options.feed)
 
     return run_exe(exe)
 
diff -Nru meson-0.53.2/mesonbuild/scripts/msgfmthelper.py meson-0.61.2/mesonbuild/scripts/msgfmthelper.py
--- meson-0.53.2/mesonbuild/scripts/msgfmthelper.py	2019-05-02 18:59:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/msgfmthelper.py	2021-04-01 21:12:21.000000000 +0000
@@ -15,6 +15,7 @@
 import argparse
 import subprocess
 import os
+import typing as T
 
 parser = argparse.ArgumentParser()
 parser.add_argument('input')
@@ -25,7 +26,7 @@
 parser.add_argument('args', default=[], metavar='extra msgfmt argument', nargs='*')
 
 
-def run(args):
+def run(args: T.List[str]) -> int:
     options = parser.parse_args(args)
     env = None
     if options.datadirs:
diff -Nru meson-0.53.2/mesonbuild/scripts/regen_checker.py meson-0.61.2/mesonbuild/scripts/regen_checker.py
--- meson-0.53.2/mesonbuild/scripts/regen_checker.py	2018-08-25 08:05:43.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/regen_checker.py	2021-04-27 06:50:21.000000000 +0000
@@ -14,10 +14,14 @@
 
 import sys, os
 import pickle, subprocess
+import typing as T
+from ..coredata import CoreData
+from ..backend.backends import RegenInfo
+from ..mesonlib import OptionKey
 
 # This could also be used for XCode.
 
-def need_regen(regeninfo, regen_timestamp):
+def need_regen(regeninfo: RegenInfo, regen_timestamp: float) -> bool:
     for i in regeninfo.depfiles:
         curfile = os.path.join(regeninfo.build_dir, i)
         curtime = os.stat(curfile).st_mtime
@@ -31,7 +35,7 @@
     Vs2010Backend.touch_regen_timestamp(regeninfo.build_dir)
     return False
 
-def regen(regeninfo, meson_command, backend):
+def regen(regeninfo: RegenInfo, meson_command: T.List[str], backend: str) -> None:
     cmd = meson_command + ['--internal',
                            'regenerate',
                            regeninfo.build_dir,
@@ -39,19 +43,22 @@
                            '--backend=' + backend]
     subprocess.check_call(cmd)
 
-def run(args):
+def run(args: T.List[str]) -> int:
     private_dir = args[0]
     dumpfile = os.path.join(private_dir, 'regeninfo.dump')
-    coredata = os.path.join(private_dir, 'coredata.dat')
+    coredata_file = os.path.join(private_dir, 'coredata.dat')
     with open(dumpfile, 'rb') as f:
         regeninfo = pickle.load(f)
-    with open(coredata, 'rb') as f:
+        assert isinstance(regeninfo, RegenInfo)
+    with open(coredata_file, 'rb') as f:
         coredata = pickle.load(f)
-    backend = coredata.get_builtin_option('backend')
+        assert isinstance(coredata, CoreData)
+    backend = coredata.get_option(OptionKey('backend'))
+    assert isinstance(backend, str)
     regen_timestamp = os.stat(dumpfile).st_mtime
     if need_regen(regeninfo, regen_timestamp):
         regen(regeninfo, coredata.meson_command, backend)
-    sys.exit(0)
+    return 0
 
 if __name__ == '__main__':
-    run(sys.argv[1:])
+    sys.exit(run(sys.argv[1:]))
diff -Nru meson-0.53.2/mesonbuild/scripts/run_tool.py meson-0.61.2/mesonbuild/scripts/run_tool.py
--- meson-0.53.2/mesonbuild/scripts/run_tool.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/run_tool.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,65 @@
+# Copyright 2018 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 subprocess
+import itertools
+import fnmatch
+from pathlib import Path
+from concurrent.futures import ThreadPoolExecutor
+
+from ..compilers import lang_suffixes
+from ..mesonlib import Popen_safe
+import typing as T
+
+def parse_pattern_file(fname: Path) -> T.List[str]:
+    patterns = []
+    try:
+        with fname.open(encoding='utf-8') as f:
+            for line in f:
+                pattern = line.strip()
+                if pattern and not pattern.startswith('#'):
+                    patterns.append(pattern)
+    except FileNotFoundError:
+        pass
+    return patterns
+
+def run_tool(name: str, srcdir: Path, builddir: Path, fn: T.Callable[..., subprocess.CompletedProcess], *args: T.Any) -> int:
+    patterns = parse_pattern_file(srcdir / f'.{name}-include')
+    globs: T.Union[T.List[T.List[Path]], T.List[T.Generator[Path, None, None]]]
+    if patterns:
+        globs = [srcdir.glob(p) for p in patterns]
+    else:
+        p, o, _ = Popen_safe(['git', 'ls-files'], cwd=srcdir)
+        if p.returncode == 0:
+            globs = [[Path(srcdir, f) for f in o.splitlines()]]
+        else:
+            globs = [srcdir.glob('**/*')]
+    patterns = parse_pattern_file(srcdir / f'.{name}-ignore')
+    ignore = [str(builddir / '*')]
+    ignore.extend([str(srcdir / p) for p in patterns])
+    suffixes = set(lang_suffixes['c']).union(set(lang_suffixes['cpp']))
+    suffixes.add('h')
+    suffixes = {f'.{s}' for s in suffixes}
+    futures = []
+    returncode = 0
+    with ThreadPoolExecutor() as e:
+        for f in itertools.chain(*globs):
+            strf = str(f)
+            if f.is_dir() or f.suffix not in suffixes or \
+                any(fnmatch.fnmatch(strf, i) for i in ignore):
+                continue
+            futures.append(e.submit(fn, f, *args))
+        if futures:
+            returncode = max(x.result().returncode for x in futures)
+    return returncode
diff -Nru meson-0.53.2/mesonbuild/scripts/scanbuild.py meson-0.61.2/mesonbuild/scripts/scanbuild.py
--- meson-0.53.2/mesonbuild/scripts/scanbuild.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/scanbuild.py	2021-08-18 11:22:15.000000000 +0000
@@ -12,34 +12,54 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os
 import subprocess
 import shutil
 import tempfile
 from ..environment import detect_ninja, detect_scanbuild
+from ..coredata import get_cmd_line_file, CmdLineFileParser
+from ..mesonlib import windows_proof_rmtree
+from pathlib import Path
+import typing as T
+from ast import literal_eval
+import os
 
-
-def scanbuild(exelist, srcdir, blddir, privdir, logdir, args):
-    with tempfile.TemporaryDirectory(dir=privdir) as scandir:
-        meson_cmd = exelist + args
-        build_cmd = exelist + ['-o', logdir, detect_ninja(), '-C', scandir]
-        rc = subprocess.call(meson_cmd + [srcdir, scandir])
-        if rc != 0:
-            return rc
-        return subprocess.call(build_cmd)
-
-
-def run(args):
-    srcdir = args[0]
+def scanbuild(exelist: T.List[str], srcdir: Path, blddir: Path, privdir: Path, logdir: Path, args: T.List[str]) -> int:
+    # In case of problems leave the temp directory around
+    # so it can be debugged.
+    scandir = tempfile.mkdtemp(dir=str(privdir))
+    meson_cmd = exelist + args
+    build_cmd = exelist + ['-o', str(logdir)] + detect_ninja() + ['-C', scandir]
+    rc = subprocess.call(meson_cmd + [str(srcdir), scandir])
+    if rc != 0:
+        return rc
+    rc = subprocess.call(build_cmd)
+    if rc == 0:
+        windows_proof_rmtree(scandir)
+    return rc
+
+def run(args: T.List[str]) -> int:
+    srcdir = Path(args[0])
+    bldpath = Path(args[1])
     blddir = args[1]
     meson_cmd = args[2:]
-    privdir = os.path.join(blddir, 'meson-private')
-    logdir = os.path.join(blddir, 'meson-logs/scanbuild')
-    shutil.rmtree(logdir, ignore_errors=True)
+    privdir = bldpath / 'meson-private'
+    logdir = bldpath / 'meson-logs' / 'scanbuild'
+    shutil.rmtree(str(logdir), ignore_errors=True)
+
+    # if any cross or native files are specified we should use them
+    cmd = get_cmd_line_file(blddir)
+    data = CmdLineFileParser()
+    data.read(cmd)
+
+    if 'cross_file' in data['properties']:
+        meson_cmd.extend([f'--cross-file={os.path.abspath(f)}' for f in literal_eval(data['properties']['cross_file'])])
+
+    if 'native_file' in data['properties']:
+        meson_cmd.extend([f'--native-file={os.path.abspath(f)}' for f in literal_eval(data['properties']['native_file'])])
 
     exelist = detect_scanbuild()
     if not exelist:
         print('Could not execute scan-build "%s"' % ' '.join(exelist))
         return 1
 
-    return scanbuild(exelist, srcdir, blddir, privdir, logdir, meson_cmd)
+    return scanbuild(exelist, srcdir, bldpath, privdir, logdir, meson_cmd)
diff -Nru meson-0.53.2/mesonbuild/scripts/symbolextractor.py meson-0.61.2/mesonbuild/scripts/symbolextractor.py
--- meson-0.53.2/mesonbuild/scripts/symbolextractor.py	2019-05-02 18:59:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/symbolextractor.py	2021-11-02 19:58:07.000000000 +0000
@@ -20,8 +20,10 @@
 # This file is basically a reimplementation of
 # http://cgit.freedesktop.org/libreoffice/core/commit/?id=3213cd54b76bc80a6f0516aac75a48ff3b2ad67c
 
+import typing as T
 import os, sys
 from .. import mesonlib
+from .. import mlog
 from ..mesonlib import Popen_safe
 import argparse
 
@@ -31,91 +33,298 @@
                     help='cross compilation host platform')
 parser.add_argument('args', nargs='+')
 
-def dummy_syms(outfilename):
+TOOL_WARNING_FILE = None
+RELINKING_WARNING = 'Relinking will always happen on source changes.'
+
+def dummy_syms(outfilename: str) -> None:
     """Just touch it so relinking happens always."""
-    with open(outfilename, 'w'):
+    with open(outfilename, 'w', encoding='utf-8'):
         pass
 
-def write_if_changed(text, outfilename):
+def write_if_changed(text: str, outfilename: str) -> None:
     try:
-        with open(outfilename, 'r') as f:
+        with open(outfilename, encoding='utf-8') as f:
             oldtext = f.read()
         if text == oldtext:
             return
     except FileNotFoundError:
         pass
-    with open(outfilename, 'w') as f:
+    with open(outfilename, 'w', encoding='utf-8') as f:
         f.write(text)
 
-def linux_syms(libfilename, outfilename):
-    evar = 'READELF'
-    if evar in os.environ:
-        readelfbin = os.environ[evar].strip()
-    else:
-        readelfbin = 'readelf'
-    evar = 'NM'
+def print_tool_warning(tools: T.List[str], msg: str, stderr: T.Optional[str] = None) -> None:
+    global TOOL_WARNING_FILE
+    if os.path.exists(TOOL_WARNING_FILE):
+        return
+    m = f'{tools!r} {msg}. {RELINKING_WARNING}'
+    if stderr:
+        m += '\n' + stderr
+    mlog.warning(m)
+    # Write it out so we don't warn again
+    with open(TOOL_WARNING_FILE, 'w', encoding='utf-8'):
+        pass
+
+def get_tool(name: str) -> T.List[str]:
+    evar = name.upper()
     if evar in os.environ:
-        nmbin = os.environ[evar].strip()
-    else:
-        nmbin = 'nm'
-    pe, output = Popen_safe([readelfbin, '-d', libfilename])[0:2]
-    if pe.returncode != 0:
-        raise RuntimeError('Readelf does not work')
+        import shlex
+        return shlex.split(os.environ[evar])
+    return [name]
+
+def call_tool(name: str, args: T.List[str], **kwargs: T.Any) -> str:
+    tool = get_tool(name)
+    try:
+        p, output, e = Popen_safe(tool + args, **kwargs)
+    except FileNotFoundError:
+        print_tool_warning(tool, 'not found')
+        return None
+    except PermissionError:
+        print_tool_warning(tool, 'not usable')
+        return None
+    if p.returncode != 0:
+        print_tool_warning(tool, 'does not work', e)
+        return None
+    return output
+
+def call_tool_nowarn(tool: T.List[str], **kwargs: T.Any) -> T.Tuple[str, str]:
+    try:
+        p, output, e = Popen_safe(tool, **kwargs)
+    except FileNotFoundError:
+        return None, '{!r} not found\n'.format(tool[0])
+    except PermissionError:
+        return None, '{!r} not usable\n'.format(tool[0])
+    if p.returncode != 0:
+        return None, e
+    return output, None
+
+def gnu_syms(libfilename: str, outfilename: str) -> None:
+    # Get the name of the library
+    output = call_tool('readelf', ['-d', libfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
     result = [x for x in output.split('\n') if 'SONAME' in x]
-    assert(len(result) <= 1)
-    pnm, output = Popen_safe([nmbin, '--dynamic', '--extern-only',
-                              '--defined-only', '--format=posix',
-                              libfilename])[0:2]
-    if pnm.returncode != 0:
-        raise RuntimeError('nm does not work.')
+    assert len(result) <= 1
+    # Get a list of all symbols exported
+    output = call_tool('nm', ['--dynamic', '--extern-only', '--defined-only',
+                              '--format=posix', libfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
     for line in output.split('\n'):
         if not line:
             continue
         line_split = line.split()
         entry = line_split[0:2]
-        if len(line_split) >= 4:
+        # Store the size of symbols pointing to data objects so we relink
+        # when those change, which is needed because of copy relocations
+        # https://github.com/mesonbuild/meson/pull/7132#issuecomment-628353702
+        if line_split[1].upper() in ('B', 'G', 'D') and len(line_split) >= 4:
             entry += [line_split[3]]
         result += [' '.join(entry)]
     write_if_changed('\n'.join(result) + '\n', outfilename)
 
-def osx_syms(libfilename, outfilename):
-    pe, output = Popen_safe(['otool', '-l', libfilename])[0:2]
-    if pe.returncode != 0:
-        raise RuntimeError('Otool does not work.')
+def solaris_syms(libfilename: str, outfilename: str) -> None:
+    # gnu_syms() works with GNU nm & readelf, not Solaris nm & elfdump
+    origpath = os.environ['PATH']
+    try:
+        os.environ['PATH'] = '/usr/gnu/bin:' + origpath
+        gnu_syms(libfilename, outfilename)
+    finally:
+        os.environ['PATH'] = origpath
+
+def osx_syms(libfilename: str, outfilename: str) -> None:
+    # Get the name of the library
+    output = call_tool('otool', ['-l', libfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
     arr = output.split('\n')
     for (i, val) in enumerate(arr):
         if 'LC_ID_DYLIB' in val:
             match = i
             break
     result = [arr[match + 2], arr[match + 5]] # Libreoffice stores all 5 lines but the others seem irrelevant.
-    pnm, output = Popen_safe(['nm', '-g', '-P', libfilename])[0:2]
-    if pnm.returncode != 0:
-        raise RuntimeError('nm does not work.')
-    result += [' '.join(x.split()[0:2]) for x in output.split('\n') if x and not x.endswith('U')]
+    # Get a list of all symbols exported
+    output = call_tool('nm', ['--extern-only', '--defined-only',
+                              '--format=posix', libfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
+    result += [' '.join(x.split()[0:2]) for x in output.split('\n')]
+    write_if_changed('\n'.join(result) + '\n', outfilename)
+
+def openbsd_syms(libfilename: str, outfilename: str) -> None:
+    # Get the name of the library
+    output = call_tool('readelf', ['-d', libfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
+    result = [x for x in output.split('\n') if 'SONAME' in x]
+    assert len(result) <= 1
+    # Get a list of all symbols exported
+    output = call_tool('nm', ['-D', '-P', '-g', libfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
+    # U = undefined (cope with the lack of --defined-only option)
+    result += [' '.join(x.split()[0:2]) for x in output.split('\n') if x and not x.endswith('U ')]
+    write_if_changed('\n'.join(result) + '\n', outfilename)
+
+def freebsd_syms(libfilename: str, outfilename: str) -> None:
+    # Get the name of the library
+    output = call_tool('readelf', ['-d', libfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
+    result = [x for x in output.split('\n') if 'SONAME' in x]
+    assert len(result) <= 1
+    # Get a list of all symbols exported
+    output = call_tool('nm', ['--dynamic', '--extern-only', '--defined-only',
+                              '--format=posix', libfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
+
+    result += [' '.join(x.split()[0:2]) for x in output.split('\n')]
+    write_if_changed('\n'.join(result) + '\n', outfilename)
+
+def cygwin_syms(impfilename: str, outfilename: str) -> None:
+    # Get the name of the library
+    output = call_tool('dlltool', ['-I', impfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
+    result = [output]
+    # Get the list of all symbols exported
+    output = call_tool('nm', ['--extern-only', '--defined-only',
+                              '--format=posix', impfilename])
+    if not output:
+        dummy_syms(outfilename)
+        return
+    for line in output.split('\n'):
+        if ' T ' not in line:
+            continue
+        result.append(line.split(maxsplit=1)[0])
+    write_if_changed('\n'.join(result) + '\n', outfilename)
+
+def _get_implib_dllname(impfilename: str) -> T.Tuple[T.List[str], str]:
+    all_stderr = ''
+    # First try lib.exe, which is provided by MSVC. Then llvm-lib.exe, by LLVM
+    # for clang-cl.
+    #
+    # We cannot call get_tool on `lib` because it will look at the `LIB` env
+    # var which is the list of library paths MSVC will search for import
+    # libraries while linking.
+    for lib in (['lib'], get_tool('llvm-lib')):
+        output, e = call_tool_nowarn(lib + ['-list', impfilename])
+        if output:
+            # The output is a list of DLLs that each symbol exported by the import
+            # library is available in. We only build import libraries that point to
+            # a single DLL, so we can pick any of these. Pick the last one for
+            # simplicity. Also skip the last line, which is empty.
+            return output.split('\n')[-2:-1], None
+        all_stderr += e
+    # Next, try dlltool.exe which is provided by MinGW
+    output, e = call_tool_nowarn(get_tool('dlltool') + ['-I', impfilename])
+    if output:
+        return [output], None
+    all_stderr += e
+    return ([], all_stderr)
+
+def _get_implib_exports(impfilename: str) -> T.Tuple[T.List[str], str]:
+    all_stderr = ''
+    # Force dumpbin.exe to use en-US so we can parse its output
+    env = os.environ.copy()
+    env['VSLANG'] = '1033'
+    output, e = call_tool_nowarn(get_tool('dumpbin') + ['-exports', impfilename], env=env)
+    if output:
+        lines = output.split('\n')
+        start = lines.index('File Type: LIBRARY')
+        end = lines.index('  Summary')
+        return lines[start:end], None
+    all_stderr += e
+    # Next, try llvm-nm.exe provided by LLVM, then nm.exe provided by MinGW
+    for nm in ('llvm-nm', 'nm'):
+        output, e = call_tool_nowarn(get_tool(nm) + ['--extern-only', '--defined-only',
+                                                     '--format=posix', impfilename])
+        if output:
+            result = []
+            for line in output.split('\n'):
+                if ' T ' not in line or line.startswith('.text'):
+                    continue
+                result.append(line.split(maxsplit=1)[0])
+            return result, None
+        all_stderr += e
+    return ([], all_stderr)
+
+def windows_syms(impfilename: str, outfilename: str) -> None:
+    # Get the name of the library
+    result, e = _get_implib_dllname(impfilename)
+    if not result:
+        print_tool_warning(['lib', 'llvm-lib', 'dlltool'], 'do not work or were not found', e)
+        dummy_syms(outfilename)
+        return
+    # Get a list of all symbols exported
+    symbols, e = _get_implib_exports(impfilename)
+    if not symbols:
+        print_tool_warning(['dumpbin', 'llvm-nm', 'nm'], 'do not work or were not found', e)
+        dummy_syms(outfilename)
+        return
+    result += symbols
     write_if_changed('\n'.join(result) + '\n', outfilename)
 
-def gen_symbols(libfilename, outfilename, cross_host):
+def gen_symbols(libfilename: str, impfilename: str, outfilename: str, cross_host: str) -> None:
     if cross_host is not None:
-        # In case of cross builds just always relink.
-        # In theory we could determine the correct
-        # toolset but there are more important things
-        # to do.
+        # In case of cross builds just always relink. In theory we could
+        # determine the correct toolset, but we would need to use the correct
+        # `nm`, `readelf`, etc, from the cross info which requires refactoring.
         dummy_syms(outfilename)
-    elif mesonlib.is_linux():
-        linux_syms(libfilename, outfilename)
+    elif mesonlib.is_linux() or mesonlib.is_hurd():
+        gnu_syms(libfilename, outfilename)
     elif mesonlib.is_osx():
         osx_syms(libfilename, outfilename)
+    elif mesonlib.is_openbsd():
+        openbsd_syms(libfilename, outfilename)
+    elif mesonlib.is_freebsd():
+        freebsd_syms(libfilename, outfilename)
+    elif mesonlib.is_windows():
+        if os.path.isfile(impfilename):
+            windows_syms(impfilename, outfilename)
+        else:
+            # No import library. Not sure how the DLL is being used, so just
+            # rebuild everything that links to it every time.
+            dummy_syms(outfilename)
+    elif mesonlib.is_cygwin():
+        if os.path.isfile(impfilename):
+            cygwin_syms(impfilename, outfilename)
+        else:
+            # No import library. Not sure how the DLL is being used, so just
+            # rebuild everything that links to it every time.
+            dummy_syms(outfilename)
+    elif mesonlib.is_sunos():
+        solaris_syms(libfilename, outfilename)
     else:
+        if not os.path.exists(TOOL_WARNING_FILE):
+            mlog.warning('Symbol extracting has not been implemented for this '
+                         'platform. ' + RELINKING_WARNING)
+            # Write it out so we don't warn again
+            with open(TOOL_WARNING_FILE, 'w', encoding='utf-8'):
+                pass
         dummy_syms(outfilename)
 
-def run(args):
+def run(args: T.List[str]) -> int:
+    global TOOL_WARNING_FILE
     options = parser.parse_args(args)
-    if len(options.args) != 2:
-        print('symbolextractor.py  ')
+    if len(options.args) != 4:
+        print('symbolextractor.py   ')
         sys.exit(1)
-    libfile = options.args[0]
-    outfile = options.args[1]
-    gen_symbols(libfile, outfile, options.cross_host)
+    privdir = os.path.join(options.args[0], 'meson-private')
+    TOOL_WARNING_FILE = os.path.join(privdir, 'symbolextractor_tool_warning_printed')
+    libfile = options.args[1]
+    impfile = options.args[2] # Only used on Windows
+    outfile = options.args[3]
+    gen_symbols(libfile, impfile, outfile, options.cross_host)
     return 0
 
 if __name__ == '__main__':
diff -Nru meson-0.53.2/mesonbuild/scripts/tags.py meson-0.61.2/mesonbuild/scripts/tags.py
--- meson-0.53.2/mesonbuild/scripts/tags.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/tags.py	2021-04-01 21:12:21.000000000 +0000
@@ -15,9 +15,9 @@
 import os
 import subprocess
 from pathlib import Path
+import typing as T
 
-
-def ls_as_bytestream():
+def ls_as_bytestream() -> bytes:
     if os.path.exists('.git'):
         return subprocess.run(['git', 'ls-tree', '-r', '--name-only', 'HEAD'],
                               stdout=subprocess.PIPE).stdout
@@ -28,24 +28,26 @@
     return '\n'.join(files).encode()
 
 
-def cscope():
+def cscope() -> int:
     ls = b'\n'.join([b'"%s"' % f for f in ls_as_bytestream().split()])
     return subprocess.run(['cscope', '-v', '-b', '-i-'], input=ls).returncode
 
 
-def ctags():
+def ctags() -> int:
     ls = ls_as_bytestream()
     return subprocess.run(['ctags', '-L-'], input=ls).returncode
 
 
-def etags():
+def etags() -> int:
     ls = ls_as_bytestream()
     return subprocess.run(['etags', '-'], input=ls).returncode
 
 
-def run(args):
+def run(args: T.List[str]) -> int:
     tool_name = args[0]
     srcdir_name = args[1]
     os.chdir(srcdir_name)
     assert tool_name in ['cscope', 'ctags', 'etags']
-    return globals()[tool_name]()
+    res = globals()[tool_name]()
+    assert isinstance(res, int)
+    return res
diff -Nru meson-0.53.2/mesonbuild/scripts/uninstall.py meson-0.61.2/mesonbuild/scripts/uninstall.py
--- meson-0.53.2/mesonbuild/scripts/uninstall.py	2017-08-02 19:21:35.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/uninstall.py	2021-07-20 08:56:20.000000000 +0000
@@ -13,13 +13,14 @@
 # limitations under the License.
 
 import os
+import typing as T
 
 logfile = 'meson-logs/install-log.txt'
 
-def do_uninstall(log):
+def do_uninstall(log: str) -> None:
     failures = 0
     successes = 0
-    for line in open(log):
+    for line in open(log, encoding='utf-8'):
         if line.startswith('#'):
             continue
         fname = line.strip()
@@ -31,14 +32,14 @@
             print('Deleted:', fname)
             successes += 1
         except Exception as e:
-            print('Could not delete %s: %s.' % (fname, e))
+            print(f'Could not delete {fname}: {e}.')
             failures += 1
     print('\nUninstall finished.\n')
     print('Deleted:', successes)
     print('Failed:', failures)
     print('\nRemember that files created by custom scripts have not been removed.')
 
-def run(args):
+def run(args: T.List[str]) -> int:
     if args:
         print('Weird error.')
         return 1
diff -Nru meson-0.53.2/mesonbuild/scripts/vcstagger.py meson-0.61.2/mesonbuild/scripts/vcstagger.py
--- meson-0.53.2/mesonbuild/scripts/vcstagger.py	2019-04-17 08:08:43.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/vcstagger.py	2021-07-20 08:56:20.000000000 +0000
@@ -13,28 +13,28 @@
 # limitations under the License.
 
 import sys, os, subprocess, re
+import typing as T
 
-
-def config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_selector, cmd):
+def config_vcs_tag(infile: str, outfile: str, fallback: str, source_dir: str, replace_string: str, regex_selector: str, cmd: T.List[str]) -> None:
     try:
         output = subprocess.check_output(cmd, cwd=source_dir)
         new_string = re.search(regex_selector, output.decode()).group(1).strip()
     except Exception:
         new_string = fallback
 
-    with open(infile, encoding='utf8') as f:
+    with open(infile, encoding='utf-8') as f:
         new_data = f.read().replace(replace_string, new_string)
     if os.path.exists(outfile):
-        with open(outfile, encoding='utf8') as f:
+        with open(outfile, encoding='utf-8') as f:
             needs_update = (f.read() != new_data)
     else:
         needs_update = True
     if needs_update:
-        with open(outfile, 'w', encoding='utf8') as f:
+        with open(outfile, 'w', encoding='utf-8') as f:
             f.write(new_data)
 
 
-def run(args):
+def run(args: T.List[str]) -> int:
     infile, outfile, fallback, source_dir, replace_string, regex_selector = args[0:6]
     command = args[6:]
     config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_selector, command)
diff -Nru meson-0.53.2/mesonbuild/scripts/yelphelper.py meson-0.61.2/mesonbuild/scripts/yelphelper.py
--- meson-0.53.2/mesonbuild/scripts/yelphelper.py	2019-06-16 18:54:18.000000000 +0000
+++ meson-0.61.2/mesonbuild/scripts/yelphelper.py	1970-01-01 00:00:00.000000000 +0000
@@ -1,132 +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
-
-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, project_id, sources):
-    # 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, project_id, langs):
-    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, blddir, langs):
-    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, sources, langs):
-    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, blddir, sources, media, langs, install_dir, destdir, project_id, symlinks):
-    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('Installing %s to %s' % (infile, outfile))
-            shutil.copyfile(infile, outfile)
-            shutil.copystat(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('Symlinking %s to %s.' % (outfile, 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('Installing %s to %s' % (infile, 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):
-    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)
diff -Nru meson-0.53.2/mesonbuild/templates/cpptemplates.py meson-0.61.2/mesonbuild/templates/cpptemplates.py
--- meson-0.53.2/mesonbuild/templates/cpptemplates.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/cpptemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -11,6 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
 import re
 
 
@@ -139,39 +140,46 @@
 '''
 
 
-def create_exe_cpp_sample(project_name, project_version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    source_name = lowercase_token + '.cpp'
-    open(source_name, 'w').write(hello_cpp_template.format(project_name=project_name))
-    open('meson.build', 'w').write(hello_cpp_meson_template.format(project_name=project_name,
-                                                                   exe_name=lowercase_token,
-                                                                   source_name=source_name,
-                                                                   version=project_version))
-
-
-def create_lib_cpp_sample(project_name, version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    uppercase_token = lowercase_token.upper()
-    class_name = uppercase_token[0] + lowercase_token[1:]
-    namespace = lowercase_token
-    lib_hpp_name = lowercase_token + '.hpp'
-    lib_cpp_name = lowercase_token + '.cpp'
-    test_cpp_name = lowercase_token + '_test.cpp'
-    kwargs = {'utoken': uppercase_token,
-              'ltoken': lowercase_token,
-              'header_dir': lowercase_token,
-              'class_name': class_name,
-              'namespace': namespace,
-              'header_file': lib_hpp_name,
-              'source_file': lib_cpp_name,
-              'test_source_file': test_cpp_name,
-              'test_exe_name': lowercase_token,
-              'project_name': project_name,
-              'lib_name': lowercase_token,
-              'test_name': lowercase_token,
-              'version': version,
-              }
-    open(lib_hpp_name, 'w').write(lib_hpp_template.format(**kwargs))
-    open(lib_cpp_name, 'w').write(lib_cpp_template.format(**kwargs))
-    open(test_cpp_name, 'w').write(lib_cpp_test_template.format(**kwargs))
-    open('meson.build', 'w').write(lib_cpp_meson_template.format(**kwargs))
+class CppProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.cpp'
+        open(source_name, 'w', encoding='utf-8').write(hello_cpp_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_cpp_meson_template.format(project_name=self.name,
+                                            exe_name=lowercase_token,
+                                            source_name=source_name,
+                                            version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        class_name = uppercase_token[0] + lowercase_token[1:]
+        test_exe_name = lowercase_token + '_test'
+        namespace = lowercase_token
+        lib_hpp_name = lowercase_token + '.hpp'
+        lib_cpp_name = lowercase_token + '.cpp'
+        test_cpp_name = lowercase_token + '_test.cpp'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'class_name': class_name,
+                  'namespace': namespace,
+                  'header_file': lib_hpp_name,
+                  'source_file': lib_cpp_name,
+                  'test_source_file': test_cpp_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_hpp_name, 'w', encoding='utf-8').write(lib_hpp_template.format(**kwargs))
+        open(lib_cpp_name, 'w', encoding='utf-8').write(lib_cpp_template.format(**kwargs))
+        open(test_cpp_name, 'w', encoding='utf-8').write(lib_cpp_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_cpp_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/cstemplates.py meson-0.61.2/mesonbuild/templates/cstemplates.py
--- meson-0.53.2/mesonbuild/templates/cstemplates.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/cstemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -0,0 +1,134 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
+import re
+
+
+hello_cs_template = '''using System;
+
+public class {class_name} {{
+    const String PROJECT_NAME = "{project_name}";
+
+    static int Main(String[] args) {{
+      if (args.Length > 0) {{
+          System.Console.WriteLine(String.Format("{project_name} takes no arguments.."));
+          return 1;
+      }}
+      Console.WriteLine(String.Format("This is project {{0}}.", PROJECT_NAME));
+      return 0;
+    }}
+}}
+
+'''
+
+hello_cs_meson_template = '''project('{project_name}', 'cs',
+  version : '{version}',
+  default_options : ['warning_level=3'])
+
+exe = executable('{exe_name}', '{source_name}',
+  install : true)
+
+test('basic', exe)
+'''
+
+lib_cs_template = '''
+public class {class_name} {{
+    private const int number = 6;
+
+    public int get_number() {{
+      return number;
+    }}
+}}
+
+'''
+
+lib_cs_test_template = '''using System;
+
+public class {class_test} {{
+    static int Main(String[] args) {{
+      if (args.Length > 0) {{
+          System.Console.WriteLine("{project_name} takes no arguments..");
+          return 1;
+      }}
+      {class_name} c = new {class_name}();
+      Boolean result = true;
+      return result.CompareTo(c.get_number() != 6);
+    }}
+}}
+
+'''
+
+lib_cs_meson_template = '''project('{project_name}', 'cs',
+  version : '{version}',
+  default_options : ['warning_level=3'])
+
+stlib = shared_library('{lib_name}', '{source_file}',
+  install : true,
+)
+
+test_exe = executable('{test_exe_name}', '{test_source_file}',
+  link_with : stlib)
+test('{test_name}', test_exe)
+
+# Make this library usable as a Meson subproject.
+{ltoken}_dep = declare_dependency(
+  include_directories: include_directories('.'),
+  link_with : stlib)
+
+'''
+
+
+class CSharpProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        class_name = uppercase_token[0] + lowercase_token[1:]
+        source_name = uppercase_token[0] + lowercase_token[1:] + '.cs'
+        open(source_name, 'w', encoding='utf-8').write(
+            hello_cs_template.format(project_name=self.name,
+                                     class_name=class_name))
+        open('meson.build', 'w', encoding='utf-8').write(
+          hello_cs_meson_template.format(project_name=self.name,
+                                         exe_name=self.name,
+                                         source_name=source_name,
+                                         version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        class_name = uppercase_token[0] + lowercase_token[1:]
+        class_test = uppercase_token[0] + lowercase_token[1:] + '_test'
+        project_test = lowercase_token + '_test'
+        lib_cs_name = uppercase_token[0] + lowercase_token[1:] + '.cs'
+        test_cs_name = uppercase_token[0] + lowercase_token[1:] + '_test.cs'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'class_test': class_test,
+                  'class_name': class_name,
+                  'source_file': lib_cs_name,
+                  'test_source_file': test_cs_name,
+                  'test_exe_name': project_test,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_cs_name, 'w', encoding='utf-8').write(lib_cs_template.format(**kwargs))
+        open(test_cs_name, 'w', encoding='utf-8').write(lib_cs_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_cs_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/ctemplates.py meson-0.61.2/mesonbuild/templates/ctemplates.py
--- meson-0.53.2/mesonbuild/templates/ctemplates.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/ctemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -11,6 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
 import re
 
 
@@ -121,36 +122,45 @@
 test('basic', exe)
 '''
 
-def create_exe_c_sample(project_name, project_version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    source_name = lowercase_token + '.c'
-    open(source_name, 'w').write(hello_c_template.format(project_name=project_name))
-    open('meson.build', 'w').write(hello_c_meson_template.format(project_name=project_name,
-                                                                 exe_name=lowercase_token,
-                                                                 source_name=source_name,
-                                                                 version=project_version))
-
-def create_lib_c_sample(project_name, version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    uppercase_token = lowercase_token.upper()
-    function_name = lowercase_token[0:3] + '_func'
-    lib_h_name = lowercase_token + '.h'
-    lib_c_name = lowercase_token + '.c'
-    test_c_name = lowercase_token + '_test.c'
-    kwargs = {'utoken': uppercase_token,
-              'ltoken': lowercase_token,
-              'header_dir': lowercase_token,
-              'function_name': function_name,
-              'header_file': lib_h_name,
-              'source_file': lib_c_name,
-              'test_source_file': test_c_name,
-              'test_exe_name': lowercase_token,
-              'project_name': project_name,
-              'lib_name': lowercase_token,
-              'test_name': lowercase_token,
-              'version': version,
-              }
-    open(lib_h_name, 'w').write(lib_h_template.format(**kwargs))
-    open(lib_c_name, 'w').write(lib_c_template.format(**kwargs))
-    open(test_c_name, 'w').write(lib_c_test_template.format(**kwargs))
-    open('meson.build', 'w').write(lib_c_meson_template.format(**kwargs))
+
+class CProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.c'
+        open(source_name, 'w', encoding='utf-8').write(hello_c_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_c_meson_template.format(project_name=self.name,
+                                          exe_name=lowercase_token,
+                                          source_name=source_name,
+                                          version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        function_name = lowercase_token[0:3] + '_func'
+        test_exe_name = lowercase_token + '_test'
+        lib_h_name = lowercase_token + '.h'
+        lib_c_name = lowercase_token + '.c'
+        test_c_name = lowercase_token + '_test.c'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'function_name': function_name,
+                  'header_file': lib_h_name,
+                  'source_file': lib_c_name,
+                  'test_source_file': test_c_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs))
+        open(lib_c_name, 'w', encoding='utf-8').write(lib_c_template.format(**kwargs))
+        open(test_c_name, 'w', encoding='utf-8').write(lib_c_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_c_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/cudatemplates.py meson-0.61.2/mesonbuild/templates/cudatemplates.py
--- meson-0.53.2/mesonbuild/templates/cudatemplates.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/cudatemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -0,0 +1,185 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
+import re
+
+
+hello_cuda_template = '''#include 
+
+#define PROJECT_NAME "{project_name}"
+
+int main(int argc, char **argv) {{
+    if(argc != 1) {{
+        std::cout << argv[0] <<  "takes no arguments.\\n";
+        return 1;
+    }}
+    std::cout << "This is project " << PROJECT_NAME << ".\\n";
+    return 0;
+}}
+'''
+
+hello_cuda_meson_template = '''project('{project_name}', ['cuda', 'cpp'],
+  version : '{version}',
+  default_options : ['warning_level=3',
+                     'cpp_std=c++14'])
+
+exe = executable('{exe_name}', '{source_name}',
+  install : true)
+
+test('basic', exe)
+'''
+
+lib_h_template = '''#pragma once
+#if defined _WIN32 || defined __CYGWIN__
+  #ifdef BUILDING_{utoken}
+    #define {utoken}_PUBLIC __declspec(dllexport)
+  #else
+    #define {utoken}_PUBLIC __declspec(dllimport)
+  #endif
+#else
+  #ifdef BUILDING_{utoken}
+      #define {utoken}_PUBLIC __attribute__ ((visibility ("default")))
+  #else
+      #define {utoken}_PUBLIC
+  #endif
+#endif
+
+namespace {namespace} {{
+
+class {utoken}_PUBLIC {class_name} {{
+
+public:
+  {class_name}();
+  int get_number() const;
+
+private:
+
+  int number;
+
+}};
+
+}}
+
+'''
+
+lib_cuda_template = '''#include <{header_file}>
+
+namespace {namespace} {{
+
+{class_name}::{class_name}() {{
+    number = 6;
+}}
+
+int {class_name}::get_number() const {{
+  return number;
+}}
+
+}}
+'''
+
+lib_cuda_test_template = '''#include <{header_file}>
+#include 
+
+int main(int argc, char **argv) {{
+    if(argc != 1) {{
+        std::cout << argv[0] << " takes no arguments.\\n";
+        return 1;
+    }}
+    {namespace}::{class_name} c;
+    return c.get_number() != 6;
+}}
+'''
+
+lib_cuda_meson_template = '''project('{project_name}', ['cuda', 'cpp'],
+  version : '{version}',
+  default_options : ['warning_level=3'])
+
+# These arguments are only used to build the shared library
+# not the executables that use the library.
+lib_args = ['-DBUILDING_{utoken}']
+
+shlib = shared_library('{lib_name}', '{source_file}',
+  install : true,
+  cpp_args : lib_args,
+  gnu_symbol_visibility : 'hidden',
+)
+
+test_exe = executable('{test_exe_name}', '{test_source_file}',
+  link_with : shlib)
+test('{test_name}', test_exe)
+
+# Make this library usable as a Meson subproject.
+{ltoken}_dep = declare_dependency(
+  include_directories: include_directories('.'),
+  link_with : shlib)
+
+# Make this library usable from the system's
+# package manager.
+install_headers('{header_file}', subdir : '{header_dir}')
+
+pkg_mod = import('pkgconfig')
+pkg_mod.generate(
+  name : '{project_name}',
+  filebase : '{ltoken}',
+  description : 'Meson sample project.',
+  subdirs : '{header_dir}',
+  libraries : shlib,
+  version : '{version}',
+)
+'''
+
+
+class CudaProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.cu'
+        open(source_name, 'w', encoding='utf-8').write(hello_cuda_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_cuda_meson_template.format(project_name=self.name,
+                                             exe_name=lowercase_token,
+                                             source_name=source_name,
+                                             version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        class_name = uppercase_token[0] + lowercase_token[1:]
+        test_exe_name = lowercase_token + '_test'
+        namespace = lowercase_token
+        lib_h_name = lowercase_token + '.h'
+        lib_cuda_name = lowercase_token + '.cu'
+        test_cuda_name = lowercase_token + '_test.cu'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'class_name': class_name,
+                  'namespace': namespace,
+                  'header_file': lib_h_name,
+                  'source_file': lib_cuda_name,
+                  'test_source_file': test_cuda_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs))
+        open(lib_cuda_name, 'w', encoding='utf-8').write(lib_cuda_template.format(**kwargs))
+        open(test_cuda_name, 'w', encoding='utf-8').write(lib_cuda_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_cuda_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/dlangtemplates.py meson-0.61.2/mesonbuild/templates/dlangtemplates.py
--- meson-0.53.2/mesonbuild/templates/dlangtemplates.py	2020-01-07 19:29:59.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/dlangtemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -11,6 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
 import re
 
 
@@ -99,36 +100,44 @@
 endif
 '''
 
-def create_exe_d_sample(project_name, project_version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    source_name = lowercase_token + '.d'
-    open(source_name, 'w').write(hello_d_template.format(project_name=project_name))
-    open('meson.build', 'w').write(hello_d_meson_template.format(project_name=project_name,
-                                                                 exe_name=lowercase_token,
-                                                                 source_name=source_name,
-                                                                 version=project_version))
-
-
-def create_lib_d_sample(project_name, version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    uppercase_token = lowercase_token.upper()
-    function_name = lowercase_token[0:3] + '_func'
-    lib_m_name = lowercase_token
-    lib_d_name = lowercase_token + '.d'
-    test_d_name = lowercase_token + '_test.d'
-    kwargs = {'utoken': uppercase_token,
-              'ltoken': lowercase_token,
-              'header_dir': lowercase_token,
-              'function_name': function_name,
-              'module_file': lib_m_name,
-              'source_file': lib_d_name,
-              'test_source_file': test_d_name,
-              'test_exe_name': lowercase_token,
-              'project_name': project_name,
-              'lib_name': lowercase_token,
-              'test_name': lowercase_token,
-              'version': version,
-              }
-    open(lib_d_name, 'w').write(lib_d_template.format(**kwargs))
-    open(test_d_name, 'w').write(lib_d_test_template.format(**kwargs))
-    open('meson.build', 'w').write(lib_d_meson_template.format(**kwargs))
+
+class DlangProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.d'
+        open(source_name, 'w', encoding='utf-8').write(hello_d_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_d_meson_template.format(project_name=self.name,
+                                          exe_name=lowercase_token,
+                                          source_name=source_name,
+                                          version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        function_name = lowercase_token[0:3] + '_func'
+        test_exe_name = lowercase_token + '_test'
+        lib_m_name = lowercase_token
+        lib_d_name = lowercase_token + '.d'
+        test_d_name = lowercase_token + '_test.d'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'function_name': function_name,
+                  'module_file': lib_m_name,
+                  'source_file': lib_d_name,
+                  'test_source_file': test_d_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_d_name, 'w', encoding='utf-8').write(lib_d_template.format(**kwargs))
+        open(test_d_name, 'w', encoding='utf-8').write(lib_d_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_d_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/fortrantemplates.py meson-0.61.2/mesonbuild/templates/fortrantemplates.py
--- meson-0.53.2/mesonbuild/templates/fortrantemplates.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/fortrantemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -11,6 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
 import re
 
 lib_fortran_template = '''
@@ -98,33 +99,42 @@
 test('basic', exe)
 '''
 
-def create_exe_fortran_sample(project_name, project_version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    source_name = lowercase_token + '.f90'
-    open(source_name, 'w').write(hello_fortran_template.format(project_name=project_name))
-    open('meson.build', 'w').write(hello_fortran_meson_template.format(project_name=project_name,
-                                                                       exe_name=lowercase_token,
-                                                                       source_name=source_name,
-                                                                       version=project_version))
-
-def create_lib_fortran_sample(project_name, version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    uppercase_token = lowercase_token.upper()
-    function_name = lowercase_token[0:3] + '_func'
-    lib_fortran_name = lowercase_token + '.f90'
-    test_fortran_name = lowercase_token + '_test.f90'
-    kwargs = {'utoken': uppercase_token,
-              'ltoken': lowercase_token,
-              'header_dir': lowercase_token,
-              'function_name': function_name,
-              'source_file': lib_fortran_name,
-              'test_source_file': test_fortran_name,
-              'test_exe_name': lowercase_token,
-              'project_name': project_name,
-              'lib_name': lowercase_token,
-              'test_name': lowercase_token,
-              'version': version,
-              }
-    open(lib_fortran_name, 'w').write(lib_fortran_template.format(**kwargs))
-    open(test_fortran_name, 'w').write(lib_fortran_test_template.format(**kwargs))
-    open('meson.build', 'w').write(lib_fortran_meson_template.format(**kwargs))
+
+class FortranProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.f90'
+        open(source_name, 'w', encoding='utf-8').write(hello_fortran_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_fortran_meson_template.format(project_name=self.name,
+                                                exe_name=lowercase_token,
+                                                source_name=source_name,
+                                                version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        function_name = lowercase_token[0:3] + '_func'
+        test_exe_name = lowercase_token + '_test'
+        lib_fortran_name = lowercase_token + '.f90'
+        test_fortran_name = lowercase_token + '_test.f90'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'function_name': function_name,
+                  'source_file': lib_fortran_name,
+                  'test_source_file': test_fortran_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_fortran_name, 'w', encoding='utf-8').write(lib_fortran_template.format(**kwargs))
+        open(test_fortran_name, 'w', encoding='utf-8').write(lib_fortran_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_fortran_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/javatemplates.py meson-0.61.2/mesonbuild/templates/javatemplates.py
--- meson-0.53.2/mesonbuild/templates/javatemplates.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/javatemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -0,0 +1,136 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
+import re
+
+
+hello_java_template = '''
+
+public class {class_name} {{
+    final static String PROJECT_NAME = "{project_name}";
+
+    public static void main (String args[]) {{
+        if(args.length != 0) {{
+            System.out.println(args + " takes no arguments.");
+            System.exit(0);
+        }}
+        System.out.println("This is project " + PROJECT_NAME + ".");
+        System.exit(0);
+    }}
+}}
+
+'''
+
+hello_java_meson_template = '''project('{project_name}', 'java',
+  version : '{version}',
+  default_options : ['warning_level=3'])
+
+exe = jar('{exe_name}', '{source_name}',
+  main_class : '{exe_name}',
+  install : true)
+
+test('basic', exe)
+'''
+
+lib_java_template = '''
+
+public class {class_name} {{
+    final static int number = 6;
+
+    public final int get_number() {{
+      return number;
+    }}
+}}
+
+'''
+
+lib_java_test_template = '''
+
+public class {class_test} {{
+    public static void main (String args[]) {{
+        if(args.length != 0) {{
+            System.out.println(args + " takes no arguments.");
+            System.exit(1);
+        }}
+
+        {class_name} c = new {class_name}();
+        Boolean result = true;
+        System.exit(result.compareTo(c.get_number() != 6));
+    }}
+}}
+
+'''
+
+lib_java_meson_template = '''project('{project_name}', 'java',
+  version : '{version}',
+  default_options : ['warning_level=3'])
+
+jarlib = jar('{class_name}', '{source_file}',
+  main_class : '{class_name}',
+  install : true,
+)
+
+test_jar = jar('{class_test}', '{test_source_file}',
+  main_class : '{class_test}',
+  link_with : jarlib)
+test('{test_name}', test_jar)
+
+# Make this library usable as a Meson subproject.
+{ltoken}_dep = declare_dependency(
+  include_directories: include_directories('.'),
+  link_with : jarlib)
+'''
+
+
+class JavaProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        class_name = uppercase_token[0] + lowercase_token[1:]
+        source_name = uppercase_token[0] + lowercase_token[1:] + '.java'
+        open(source_name, 'w', encoding='utf-8').write(
+            hello_java_template.format(project_name=self.name,
+                                       class_name=class_name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_java_meson_template.format(project_name=self.name,
+                                             exe_name=class_name,
+                                             source_name=source_name,
+                                             version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        class_name = uppercase_token[0] + lowercase_token[1:]
+        class_test = uppercase_token[0] + lowercase_token[1:] + '_test'
+        lib_java_name = uppercase_token[0] + lowercase_token[1:] + '.java'
+        test_java_name = uppercase_token[0] + lowercase_token[1:] + '_test.java'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'class_test': class_test,
+                  'class_name': class_name,
+                  'source_file': lib_java_name,
+                  'test_source_file': test_java_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_java_name, 'w', encoding='utf-8').write(lib_java_template.format(**kwargs))
+        open(test_java_name, 'w', encoding='utf-8').write(lib_java_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_java_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/mesontemplates.py meson-0.61.2/mesonbuild/templates/mesontemplates.py
--- meson-0.53.2/mesonbuild/templates/mesontemplates.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/mesontemplates.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,76 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+
+meson_executable_template = '''project('{project_name}', {language},
+  version : '{version}',
+  default_options : [{default_options}])
+
+executable('{executable}',
+           {sourcespec},{depspec}
+           install : true)
+'''
+
+
+meson_jar_template = '''project('{project_name}', '{language}',
+  version : '{version}',
+  default_options : [{default_options}])
+
+jar('{executable}',
+    {sourcespec},{depspec}
+    main_class: '{main_class}',
+    install : true)
+'''
+
+
+def create_meson_build(options: argparse.Namespace) -> None:
+    if options.type != 'executable':
+        raise SystemExit('\nGenerating a meson.build file from existing sources is\n'
+                         'supported only for project type "executable".\n'
+                         'Run meson init in an empty directory to create a sample project.')
+    default_options = ['warning_level=3']
+    if options.language == 'cpp':
+        # This shows how to set this very common option.
+        default_options += ['cpp_std=c++14']
+    # If we get a meson.build autoformatter one day, this code could
+    # be simplified quite a bit.
+    formatted_default_options = ', '.join(f"'{x}'" for x in default_options)
+    sourcespec = ',\n           '.join(f"'{x}'" for x in options.srcfiles)
+    depspec = ''
+    if options.deps:
+        depspec = '\n           dependencies : [\n              '
+        depspec += ',\n              '.join(f"dependency('{x}')"
+                                            for x in options.deps.split(','))
+        depspec += '],'
+    if options.language != 'java':
+        language = f"'{options.language}'" if options.language != 'vala' else ['c', 'vala']
+        content = meson_executable_template.format(project_name=options.name,
+                                                   language=language,
+                                                   version=options.version,
+                                                   executable=options.executable,
+                                                   sourcespec=sourcespec,
+                                                   depspec=depspec,
+                                                   default_options=formatted_default_options)
+    else:
+        content = meson_jar_template.format(project_name=options.name,
+                                            language=options.language,
+                                            version=options.version,
+                                            executable=options.executable,
+                                            main_class=options.name,
+                                            sourcespec=sourcespec,
+                                            depspec=depspec,
+                                            default_options=formatted_default_options)
+    open('meson.build', 'w', encoding='utf-8').write(content)
+    print('Generated meson.build file:\n\n' + content)
diff -Nru meson-0.53.2/mesonbuild/templates/objcpptemplates.py meson-0.61.2/mesonbuild/templates/objcpptemplates.py
--- meson-0.53.2/mesonbuild/templates/objcpptemplates.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/objcpptemplates.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,166 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
+import re
+
+
+lib_h_template = '''#pragma once
+#if defined _WIN32 || defined __CYGWIN__
+  #ifdef BUILDING_{utoken}
+    #define {utoken}_PUBLIC __declspec(dllexport)
+  #else
+    #define {utoken}_PUBLIC __declspec(dllimport)
+  #endif
+#else
+  #ifdef BUILDING_{utoken}
+      #define {utoken}_PUBLIC __attribute__ ((visibility ("default")))
+  #else
+      #define {utoken}_PUBLIC
+  #endif
+#endif
+
+int {utoken}_PUBLIC {function_name}();
+
+'''
+
+lib_objcpp_template = '''#import <{header_file}>
+
+/* This function will not be exported and is not
+ * directly callable by users of this library.
+ */
+int internal_function() {{
+    return 0;
+}}
+
+int {function_name}() {{
+    return internal_function();
+}}
+'''
+
+lib_objcpp_test_template = '''#import <{header_file}>
+#import 
+
+int main(int argc, char **argv) {{
+    if(argc != 1) {{
+        std::cout << argv[0] << " takes no arguments." << std::endl;
+        return 1;
+    }}
+    return {function_name}();
+}}
+'''
+
+lib_objcpp_meson_template = '''project('{project_name}', 'objcpp',
+  version : '{version}',
+  default_options : ['warning_level=3'])
+
+# These arguments are only used to build the shared library
+# not the executables that use the library.
+lib_args = ['-DBUILDING_{utoken}']
+
+shlib = shared_library('{lib_name}', '{source_file}',
+  install : true,
+  objcpp_args : lib_args,
+  gnu_symbol_visibility : 'hidden',
+)
+
+test_exe = executable('{test_exe_name}', '{test_source_file}',
+  link_with : shlib)
+test('{test_name}', test_exe)
+
+# Make this library usable as a Meson subproject.
+{ltoken}_dep = declare_dependency(
+  include_directories: include_directories('.'),
+  link_with : shlib)
+
+# Make this library usable from the system's
+# package manager.
+install_headers('{header_file}', subdir : '{header_dir}')
+
+pkg_mod = import('pkgconfig')
+pkg_mod.generate(
+  name : '{project_name}',
+  filebase : '{ltoken}',
+  description : 'Meson sample project.',
+  subdirs : '{header_dir}',
+  libraries : shlib,
+  version : '{version}',
+)
+'''
+
+hello_objcpp_template = '''#import 
+
+#define PROJECT_NAME "{project_name}"
+
+int main(int argc, char **argv) {{
+    if(argc != 1) {{
+        std::cout << argv[0] << " takes no arguments." << std::endl;
+        return 1;
+    }}
+    std::cout << "This is project " << PROJECT_NAME << "." << std::endl;
+    return 0;
+}}
+'''
+
+hello_objcpp_meson_template = '''project('{project_name}', 'objcpp',
+  version : '{version}',
+  default_options : ['warning_level=3'])
+
+exe = executable('{exe_name}', '{source_name}',
+  install : true)
+
+test('basic', exe)
+'''
+
+
+class ObjCppProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.mm'
+        open(source_name, 'w', encoding='utf-8').write(hello_objcpp_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_objcpp_meson_template.format(project_name=self.name,
+                                               exe_name=lowercase_token,
+                                               source_name=source_name,
+                                               version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        function_name = lowercase_token[0:3] + '_func'
+        test_exe_name = lowercase_token + '_test'
+        lib_h_name = lowercase_token + '.h'
+        lib_objcpp_name = lowercase_token + '.mm'
+        test_objcpp_name = lowercase_token + '_test.mm'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'function_name': function_name,
+                  'header_file': lib_h_name,
+                  'source_file': lib_objcpp_name,
+                  'test_source_file': test_objcpp_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs))
+        open(lib_objcpp_name, 'w', encoding='utf-8').write(lib_objcpp_template.format(**kwargs))
+        open(test_objcpp_name, 'w', encoding='utf-8').write(lib_objcpp_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_objcpp_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/objctemplates.py meson-0.61.2/mesonbuild/templates/objctemplates.py
--- meson-0.53.2/mesonbuild/templates/objctemplates.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/objctemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -11,6 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
 import re
 
 
@@ -121,36 +122,45 @@
 test('basic', exe)
 '''
 
-def create_exe_objc_sample(project_name, project_version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    source_name = lowercase_token + '.m'
-    open(source_name, 'w').write(hello_objc_template.format(project_name=project_name))
-    open('meson.build', 'w').write(hello_objc_meson_template.format(project_name=project_name,
-                                                                    exe_name=lowercase_token,
-                                                                    source_name=source_name,
-                                                                    version=project_version))
-
-def create_lib_objc_sample(project_name, version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    uppercase_token = lowercase_token.upper()
-    function_name = lowercase_token[0:3] + '_func'
-    lib_h_name = lowercase_token + '.h'
-    lib_objc_name = lowercase_token + '.m'
-    test_objc_name = lowercase_token + '_test.m'
-    kwargs = {'utoken': uppercase_token,
-              'ltoken': lowercase_token,
-              'header_dir': lowercase_token,
-              'function_name': function_name,
-              'header_file': lib_h_name,
-              'source_file': lib_objc_name,
-              'test_source_file': test_objc_name,
-              'test_exe_name': lowercase_token,
-              'project_name': project_name,
-              'lib_name': lowercase_token,
-              'test_name': lowercase_token,
-              'version': version,
-              }
-    open(lib_h_name, 'w').write(lib_h_template.format(**kwargs))
-    open(lib_objc_name, 'w').write(lib_objc_template.format(**kwargs))
-    open(test_objc_name, 'w').write(lib_objc_test_template.format(**kwargs))
-    open('meson.build', 'w').write(lib_objc_meson_template.format(**kwargs))
+
+class ObjCProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.m'
+        open(source_name, 'w', encoding='utf-8').write(hello_objc_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_objc_meson_template.format(project_name=self.name,
+                                             exe_name=lowercase_token,
+                                             source_name=source_name,
+                                             version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        function_name = lowercase_token[0:3] + '_func'
+        test_exe_name = lowercase_token + '_test'
+        lib_h_name = lowercase_token + '.h'
+        lib_objc_name = lowercase_token + '.m'
+        test_objc_name = lowercase_token + '_test.m'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'function_name': function_name,
+                  'header_file': lib_h_name,
+                  'source_file': lib_objc_name,
+                  'test_source_file': test_objc_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs))
+        open(lib_objc_name, 'w', encoding='utf-8').write(lib_objc_template.format(**kwargs))
+        open(test_objc_name, 'w', encoding='utf-8').write(lib_objc_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_objc_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/rusttemplates.py meson-0.61.2/mesonbuild/templates/rusttemplates.py
--- meson-0.53.2/mesonbuild/templates/rusttemplates.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/rusttemplates.py	2021-07-20 08:56:20.000000000 +0000
@@ -11,6 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
 import re
 
 
@@ -69,35 +70,44 @@
 test('basic', exe)
 '''
 
-def create_exe_rust_sample(project_name, project_version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    source_name = lowercase_token + '.rs'
-    open(source_name, 'w').write(hello_rust_template.format(project_name=project_name))
-    open('meson.build', 'w').write(hello_rust_meson_template.format(project_name=project_name,
-                                                                    exe_name=lowercase_token,
-                                                                    source_name=source_name,
-                                                                    version=project_version))
-
-def create_lib_rust_sample(project_name, version):
-    lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
-    uppercase_token = lowercase_token.upper()
-    function_name = lowercase_token[0:3] + '_func'
-    lib_crate_name = lowercase_token
-    lib_rs_name = lowercase_token + '.rs'
-    test_rs_name = lowercase_token + '_test.rs'
-    kwargs = {'utoken': uppercase_token,
-              'ltoken': lowercase_token,
-              'header_dir': lowercase_token,
-              'function_name': function_name,
-              'crate_file': lib_crate_name,
-              'source_file': lib_rs_name,
-              'test_source_file': test_rs_name,
-              'test_exe_name': lowercase_token,
-              'project_name': project_name,
-              'lib_name': lowercase_token,
-              'test_name': lowercase_token,
-              'version': version,
-              }
-    open(lib_rs_name, 'w').write(lib_rust_template.format(**kwargs))
-    open(test_rs_name, 'w').write(lib_rust_test_template.format(**kwargs))
-    open('meson.build', 'w').write(lib_rust_meson_template.format(**kwargs))
+
+class RustProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.rs'
+        open(source_name, 'w', encoding='utf-8').write(hello_rust_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_rust_meson_template.format(project_name=self.name,
+                                             exe_name=lowercase_token,
+                                             source_name=source_name,
+                                             version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        function_name = lowercase_token[0:3] + '_func'
+        test_exe_name = lowercase_token + '_test'
+        lib_crate_name = lowercase_token
+        lib_rs_name = lowercase_token + '.rs'
+        test_rs_name = lowercase_token + '_test.rs'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'function_name': function_name,
+                  'crate_file': lib_crate_name,
+                  'source_file': lib_rs_name,
+                  'test_source_file': test_rs_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_rs_name, 'w', encoding='utf-8').write(lib_rust_template.format(**kwargs))
+        open(test_rs_name, 'w', encoding='utf-8').write(lib_rust_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_rust_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/templates/samplefactory.py meson-0.61.2/mesonbuild/templates/samplefactory.py
--- meson-0.53.2/mesonbuild/templates/samplefactory.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/samplefactory.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,42 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from mesonbuild.templates.valatemplates import ValaProject
+from mesonbuild.templates.fortrantemplates import FortranProject
+from mesonbuild.templates.objcpptemplates import ObjCppProject
+from mesonbuild.templates.dlangtemplates import DlangProject
+from mesonbuild.templates.rusttemplates import RustProject
+from mesonbuild.templates.javatemplates import JavaProject
+from mesonbuild.templates.cudatemplates import CudaProject
+from mesonbuild.templates.objctemplates import ObjCProject
+from mesonbuild.templates.cpptemplates import CppProject
+from mesonbuild.templates.cstemplates import CSharpProject
+from mesonbuild.templates.ctemplates import CProject
+from mesonbuild.templates.sampleimpl import SampleImpl
+
+import argparse
+
+def sameple_generator(options: argparse.Namespace) -> SampleImpl:
+    return {
+        'c': CProject,
+        'cpp': CppProject,
+        'cs': CSharpProject,
+        'cuda': CudaProject,
+        'objc': ObjCProject,
+        'objcpp': ObjCppProject,
+        'java': JavaProject,
+        'd': DlangProject,
+        'rust': RustProject,
+        'fortran': FortranProject,
+        'vala': ValaProject
+    }[options.language](options)
diff -Nru meson-0.53.2/mesonbuild/templates/sampleimpl.py meson-0.61.2/mesonbuild/templates/sampleimpl.py
--- meson-0.53.2/mesonbuild/templates/sampleimpl.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/sampleimpl.py	2021-04-01 21:12:21.000000000 +0000
@@ -0,0 +1,21 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+class SampleImpl:
+    def create_executable(self) -> None:
+        raise NotImplementedError('Sample implementation for "executable" not implemented!')
+
+    def create_library(self) -> None:
+        raise NotImplementedError('Sample implementation for "library" not implemented!')
diff -Nru meson-0.53.2/mesonbuild/templates/valatemplates.py meson-0.61.2/mesonbuild/templates/valatemplates.py
--- meson-0.53.2/mesonbuild/templates/valatemplates.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/templates/valatemplates.py	2021-12-26 16:24:25.000000000 +0000
@@ -0,0 +1,123 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from mesonbuild.templates.sampleimpl import SampleImpl
+import re
+
+
+hello_vala_template = '''void main (string[] args) {{
+    stdout.printf ("Hello {project_name}!\\n");
+}}
+'''
+
+hello_vala_meson_template = '''project('{project_name}', ['c', 'vala'],
+  version : '{version}')
+
+dependencies = [
+    dependency('glib-2.0'),
+    dependency('gobject-2.0'),
+]
+
+exe = executable('{exe_name}', '{source_name}', dependencies : dependencies,
+  install : true)
+
+test('basic', exe)
+'''
+
+
+lib_vala_template = '''namespace {namespace} {{
+    public int sum(int a, int b) {{
+        return(a + b);
+    }}
+
+    public int square(int a) {{
+        return(a * a);
+    }}
+}}
+'''
+
+lib_vala_test_template = '''using {namespace};
+
+public void main() {{
+    stdout.printf("\nTesting shlib");
+    stdout.printf("\n\t2 + 3 is %d", sum(2, 3));
+    stdout.printf("\n\t8 squared is %d\\n", square(8));
+}}
+'''
+
+lib_vala_meson_template = '''project('{project_name}', ['c', 'vala'],
+  version : '{version}')
+
+dependencies = [
+    dependency('glib-2.0'),
+    dependency('gobject-2.0'),
+]
+
+# These arguments are only used to build the shared library
+# not the executables that use the library.
+shlib = shared_library('foo', '{source_file}',
+               dependencies: dependencies,
+               install: true,
+               install_dir: [true, true, true])
+
+test_exe = executable('{test_exe_name}', '{test_source_file}', dependencies : dependencies,
+  link_with : shlib)
+test('{test_name}', test_exe)
+
+# Make this library usable as a Meson subproject.
+{ltoken}_dep = declare_dependency(
+  include_directories: include_directories('.'),
+  link_with : shlib)
+'''
+
+
+class ValaProject(SampleImpl):
+    def __init__(self, options):
+        super().__init__()
+        self.name = options.name
+        self.version = options.version
+
+    def create_executable(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        source_name = lowercase_token + '.vala'
+        open(source_name, 'w', encoding='utf-8').write(hello_vala_template.format(project_name=self.name))
+        open('meson.build', 'w', encoding='utf-8').write(
+            hello_vala_meson_template.format(project_name=self.name,
+                                            exe_name=lowercase_token,
+                                            source_name=source_name,
+                                            version=self.version))
+
+    def create_library(self) -> None:
+        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
+        uppercase_token = lowercase_token.upper()
+        class_name = uppercase_token[0] + lowercase_token[1:]
+        test_exe_name = lowercase_token + '_test'
+        namespace = lowercase_token
+        lib_vala_name = lowercase_token + '.vala'
+        test_vala_name = lowercase_token + '_test.vala'
+        kwargs = {'utoken': uppercase_token,
+                  'ltoken': lowercase_token,
+                  'header_dir': lowercase_token,
+                  'class_name': class_name,
+                  'namespace': namespace,
+                  'source_file': lib_vala_name,
+                  'test_source_file': test_vala_name,
+                  'test_exe_name': test_exe_name,
+                  'project_name': self.name,
+                  'lib_name': lowercase_token,
+                  'test_name': lowercase_token,
+                  'version': self.version,
+                  }
+        open(lib_vala_name, 'w', encoding='utf-8').write(lib_vala_template.format(**kwargs))
+        open(test_vala_name, 'w', encoding='utf-8').write(lib_vala_test_template.format(**kwargs))
+        open('meson.build', 'w', encoding='utf-8').write(lib_vala_meson_template.format(**kwargs))
diff -Nru meson-0.53.2/mesonbuild/_typing.py meson-0.61.2/mesonbuild/_typing.py
--- meson-0.53.2/mesonbuild/_typing.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/mesonbuild/_typing.py	2021-11-02 19:58:13.000000000 +0000
@@ -0,0 +1,120 @@
+# SPDX-License-Identifer: Apache-2.0
+# Copyright 2020 The Meson development team
+# Copyright © 2020-2021 Intel Corporation
+
+# 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.
+
+"""Meson specific typing helpers.
+
+Holds typing helper classes, such as the ImmutableProtocol classes
+"""
+
+__all__ = [
+    'Protocol',
+    'ImmutableListProtocol'
+]
+
+import typing
+
+# We can change this to typing when we require python 3.8
+from typing_extensions import Protocol
+
+
+T = typing.TypeVar('T')
+
+
+class StringProtocol(Protocol):
+    def __str__(self) -> str: ...
+
+class SizedStringProtocol(Protocol, StringProtocol, typing.Sized):
+    pass
+
+class ImmutableListProtocol(Protocol[T]):
+
+    """A protocol used in cases where a list is returned, but should not be
+    mutated.
+
+    This provides all of the methods of a Sequence, as well as copy(). copy()
+    returns a list, which allows mutation as it's a copy and that's (hopefully)
+    safe.
+
+    One particular case this is important is for cached values, since python is
+    a pass-by-reference language.
+    """
+
+    def __iter__(self) -> typing.Iterator[T]: ...
+
+    @typing.overload
+    def __getitem__(self, index: int) -> T: ...
+    @typing.overload
+    def __getitem__(self, index: slice) -> typing.List[T]: ...
+
+    def __contains__(self, item: T) -> bool: ...
+
+    def __reversed__(self) -> typing.Iterator[T]: ...
+
+    def __len__(self) -> int: ...
+
+    def __add__(self, other: typing.List[T]) -> typing.List[T]: ...
+
+    def __eq__(self, other: typing.Any) -> bool: ...
+    def __ne__(self, other: typing.Any) -> bool: ...
+    def __le__(self, other: typing.Any) -> bool: ...
+    def __lt__(self, other: typing.Any) -> bool: ...
+    def __gt__(self, other: typing.Any) -> bool: ...
+    def __ge__(self, other: typing.Any) -> bool: ...
+
+    def count(self, item: T) -> int: ...
+
+    def index(self, item: T) -> int: ...
+
+    def copy(self) -> typing.List[T]: ...
+
+
+class ImmutableSetProtocol(Protocol[T]):
+
+    """A protocol for a set that cannot be mutated.
+
+    This provides for cases where mutation of the set is undesired. Although
+    this will be allowed at runtime, mypy (or another type checker), will see
+    any attempt to use mutative methods as an error.
+    """
+
+    def __iter__(self) -> typing.Iterator[T]: ...
+
+    def __contains__(self, item: T) -> bool: ...
+
+    def __len__(self) -> int: ...
+
+    def __add__(self, other: typing.Set[T]) -> typing.Set[T]: ...
+
+    def __eq__(self, other: typing.Any) -> bool: ...
+    def __ne__(self, other: typing.Any) -> bool: ...
+    def __le__(self, other: typing.Any) -> bool: ...
+    def __lt__(self, other: typing.Any) -> bool: ...
+    def __gt__(self, other: typing.Any) -> bool: ...
+    def __ge__(self, other: typing.Any) -> bool: ...
+
+    def copy(self) -> typing.Set[T]: ...
+
+    def difference(self, other: typing.Set[T]) -> typing.Set[T]: ...
+
+    def intersection(self, other: typing.Set[T]) -> typing.Set[T]: ...
+
+    def issubset(self, other: typing.Set[T]) -> bool: ...
+
+    def issuperset(self, other: typing.Set[T]) -> bool: ...
+
+    def symmetric_difference(self, other: typing.Set[T]) -> typing.Set[T]: ...
+
+    def union(self, other: typing.Set[T]) -> typing.Set[T]: ...
diff -Nru meson-0.53.2/mesonbuild/wrap/__init__.py meson-0.61.2/mesonbuild/wrap/__init__.py
--- meson-0.53.2/mesonbuild/wrap/__init__.py	2019-12-04 18:45:50.000000000 +0000
+++ meson-0.61.2/mesonbuild/wrap/__init__.py	2021-04-01 21:12:21.000000000 +0000
@@ -40,6 +40,7 @@
                    'nofallback': 2,
                    'nodownload': 3,
                    'forcefallback': 4,
+                   'nopromote': 5,
                    }
 
 class WrapMode(Enum):
@@ -47,11 +48,12 @@
     nofallback = 2
     nodownload = 3
     forcefallback = 4
+    nopromote = 5
 
     def __str__(self) -> str:
         return self.name
 
     @staticmethod
-    def from_string(mode_name: str):
+    def from_string(mode_name: str) -> 'WrapMode':
         g = string_to_value[mode_name]
         return WrapMode(g)
diff -Nru meson-0.53.2/mesonbuild/wrap/wrap.py meson-0.61.2/mesonbuild/wrap/wrap.py
--- meson-0.53.2/mesonbuild/wrap/wrap.py	2020-02-25 18:00:46.000000000 +0000
+++ meson-0.61.2/mesonbuild/wrap/wrap.py	2022-01-17 10:50:45.000000000 +0000
@@ -26,9 +26,14 @@
 import sys
 import configparser
 import typing as T
+import textwrap
 
+from pathlib import Path
 from . import WrapMode
-from ..mesonlib import git, GIT, ProgressBar, MesonException
+from .. import coredata
+from ..mesonlib import quiet_git, GIT, ProgressBar, MesonException
+from ..interpreterbase import FeatureNew
+from .. import mesonlib
 
 if T.TYPE_CHECKING:
     import http.client
@@ -38,38 +43,24 @@
     # regarding 'imported but unused' can be safely ignored
     import ssl  # noqa
     has_ssl = True
-    API_ROOT = 'https://wrapdb.mesonbuild.com/v1/'
 except ImportError:
     has_ssl = False
-    API_ROOT = 'http://wrapdb.mesonbuild.com/v1/'
 
 REQ_TIMEOUT = 600.0
 SSL_WARNING_PRINTED = False
 WHITELIST_SUBDOMAIN = 'wrapdb.mesonbuild.com'
 
-def quiet_git(cmd: T.List[str], workingdir: str) -> T.Tuple[bool, str]:
-    if not GIT:
-        return False, 'Git program not found.'
-    pc = git(cmd, workingdir, universal_newlines=True,
-             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-    if pc.returncode != 0:
-        return False, pc.stderr
-    return True, pc.stdout
-
-def verbose_git(cmd: T.List[str], workingdir: str, check: bool = False) -> bool:
-    if not GIT:
-        return False
-    return git(cmd, workingdir, check=check).returncode == 0
+ALL_TYPES = ['file', 'git', 'hg', 'svn']
 
 def whitelist_wrapdb(urlstr: str) -> urllib.parse.ParseResult:
     """ raises WrapException if not whitelisted subdomain """
     url = urllib.parse.urlparse(urlstr)
     if not url.hostname:
-        raise WrapException('{} is not a valid URL'.format(urlstr))
+        raise WrapException(f'{urlstr} is not a valid URL')
     if not url.hostname.endswith(WHITELIST_SUBDOMAIN):
-        raise WrapException('{} is not a whitelisted WrapDB URL'.format(urlstr))
+        raise WrapException(f'{urlstr} is not a whitelisted WrapDB URL')
     if has_ssl and not url.scheme == 'https':
-        raise WrapException('WrapDB did not have expected SSL https url, instead got {}'.format(urlstr))
+        raise WrapException(f'WrapDB did not have expected SSL https url, instead got {urlstr}')
     return url
 
 def open_wrapdburl(urlstring: str) -> 'http.client.HTTPResponse':
@@ -78,19 +69,19 @@
     url = whitelist_wrapdb(urlstring)
     if has_ssl:
         try:
-            return urllib.request.urlopen(urllib.parse.urlunparse(url), timeout=REQ_TIMEOUT)
+            return T.cast('http.client.HTTPResponse', urllib.request.urlopen(urllib.parse.urlunparse(url), timeout=REQ_TIMEOUT))
         except urllib.error.URLError as excp:
-            raise WrapException('WrapDB connection failed to {} with error {}'.format(urlstring, excp))
+            raise WrapException(f'WrapDB connection failed to {urlstring} with error {excp}')
 
     # following code is only for those without Python SSL
     nossl_url = url._replace(scheme='http')
     if not SSL_WARNING_PRINTED:
-        mlog.warning('SSL module not available in {}: WrapDB traffic not authenticated.'.format(sys.executable))
+        mlog.warning(f'SSL module not available in {sys.executable}: WrapDB traffic not authenticated.')
         SSL_WARNING_PRINTED = True
     try:
-        return urllib.request.urlopen(urllib.parse.urlunparse(nossl_url), timeout=REQ_TIMEOUT)
+        return T.cast('http.client.HTTPResponse', urllib.request.urlopen(urllib.parse.urlunparse(nossl_url), timeout=REQ_TIMEOUT))
     except urllib.error.URLError as excp:
-        raise WrapException('WrapDB connection failed to {} with error {}'.format(urlstring, excp))
+        raise WrapException(f'WrapDB connection failed to {urlstring} with error {excp}')
 
 
 class WrapException(MesonException):
@@ -100,61 +91,226 @@
     pass
 
 class PackageDefinition:
-    def __init__(self, fname: str):
+    def __init__(self, fname: str, subproject: str = ''):
         self.filename = fname
+        self.subproject = subproject
+        self.type = None  # type: T.Optional[str]
+        self.values = {} # type: T.Dict[str, str]
+        self.provided_deps = {} # type: T.Dict[str, T.Optional[str]]
+        self.provided_programs = [] # type: T.List[str]
         self.basename = os.path.basename(fname)
-        self.name = self.basename[:-5]
+        self.has_wrap = self.basename.endswith('.wrap')
+        self.name = self.basename[:-5] if self.has_wrap else self.basename
+        self.directory = self.name
+        self.provided_deps[self.name] = None
+        self.original_filename = fname
+        self.redirected = False
+        if self.has_wrap:
+            self.parse_wrap()
+        self.directory = self.values.get('directory', self.name)
+        if os.path.dirname(self.directory):
+            raise WrapException('Directory key must be a name and not a path')
+        if self.type and self.type not in ALL_TYPES:
+            raise WrapException(f'Unknown wrap type {self.type!r}')
+        self.filesdir = os.path.join(os.path.dirname(self.filename), 'packagefiles')
+        # What the original file name was before redirection
+
+    def parse_wrap(self) -> None:
         try:
-            self.config = configparser.ConfigParser(interpolation=None)
-            self.config.read(fname)
-        except configparser.Error:
-            raise WrapException('Failed to parse {}'.format(self.basename))
-        if len(self.config.sections()) < 1:
-            raise WrapException('Missing sections in {}'.format(self.basename))
-        self.wrap_section = self.config.sections()[0]
+            config = configparser.ConfigParser(interpolation=None)
+            config.read(self.filename)
+        except configparser.Error as e:
+            raise WrapException(f'Failed to parse {self.basename}: {e!s}')
+        self.parse_wrap_section(config)
+        if self.type == 'redirect':
+            # [wrap-redirect] have a `filename` value pointing to the real wrap
+            # file we should parse instead. It must be relative to the current
+            # wrap file location and must be in the form foo/subprojects/bar.wrap.
+            dirname = Path(self.filename).parent
+            fname = Path(self.values['filename'])
+            for i, p in enumerate(fname.parts):
+                if i % 2 == 0:
+                    if p == '..':
+                        raise WrapException('wrap-redirect filename cannot contain ".."')
+                else:
+                    if p != 'subprojects':
+                        raise WrapException('wrap-redirect filename must be in the form foo/subprojects/bar.wrap')
+            if fname.suffix != '.wrap':
+                raise WrapException('wrap-redirect filename must be a .wrap file')
+            fname = dirname / fname
+            if not fname.is_file():
+                raise WrapException(f'wrap-redirect {fname} filename does not exist')
+            self.filename = str(fname)
+            self.parse_wrap()
+            self.redirected = True
+        else:
+            self.parse_provide_section(config)
+        if 'patch_directory' in self.values:
+            FeatureNew('Wrap files with patch_directory', '0.55.0').use(self.subproject)
+        for what in ['patch', 'source']:
+            if f'{what}_filename' in self.values and f'{what}_url' not in self.values:
+                FeatureNew(f'Local wrap patch files without {what}_url', '0.55.0').use(self.subproject)
+
+    def parse_wrap_section(self, config: configparser.ConfigParser) -> None:
+        if len(config.sections()) < 1:
+            raise WrapException(f'Missing sections in {self.basename}')
+        self.wrap_section = config.sections()[0]
         if not self.wrap_section.startswith('wrap-'):
-            m = '{!r} is not a valid first section in {}'
-            raise WrapException(m.format(self.wrap_section, self.basename))
+            raise WrapException(f'{self.wrap_section!r} is not a valid first section in {self.basename}')
         self.type = self.wrap_section[5:]
-        self.values = dict(self.config[self.wrap_section])
+        self.values = dict(config[self.wrap_section])
+
+    def parse_provide_section(self, config: configparser.ConfigParser) -> None:
+        if config.has_section('provide'):
+            for k, v in config['provide'].items():
+                if k == 'dependency_names':
+                    # A comma separated list of dependency names that does not
+                    # need a variable name
+                    names_dict = {n.strip(): None for n in v.split(',')}
+                    self.provided_deps.update(names_dict)
+                    continue
+                if k == 'program_names':
+                    # A comma separated list of program names
+                    names_list = [n.strip() for n in v.split(',')]
+                    self.provided_programs += names_list
+                    continue
+                if not v:
+                    m = (f'Empty dependency variable name for {k!r} in {self.basename}. '
+                         'If the subproject uses meson.override_dependency() '
+                         'it can be added in the "dependency_names" special key.')
+                    raise WrapException(m)
+                self.provided_deps[k] = v
 
     def get(self, key: str) -> str:
         try:
             return self.values[key]
         except KeyError:
-            m = 'Missing key {!r} in {}'
-            raise WrapException(m.format(key, self.basename))
+            raise WrapException(f'Missing key {key!r} in {self.basename}')
 
-    def has_patch(self) -> bool:
-        return 'patch_url' in self.values
-
-def load_wrap(subdir_root: str, packagename: str) -> PackageDefinition:
+def get_directory(subdir_root: str, packagename: str) -> str:
     fname = os.path.join(subdir_root, packagename + '.wrap')
     if os.path.isfile(fname):
-        return PackageDefinition(fname)
-    return None
+        wrap = PackageDefinition(fname)
+        return wrap.directory
+    return packagename
 
-def get_directory(subdir_root: str, packagename: str):
-    directory = packagename
-    # We always have to load the wrap file, if it exists, because it could
-    # override the default directory name.
-    wrap = load_wrap(subdir_root, packagename)
-    if wrap and 'directory' in wrap.values:
-        directory = wrap.get('directory')
-        if os.path.dirname(directory):
-            raise WrapException('Directory key must be a name and not a path')
-    return wrap, directory
+def verbose_git(cmd: T.List[str], workingdir: str, check: bool = False) -> bool:
+    '''
+    Wrapper to convert GitException to WrapException caught in interpreter.
+    '''
+    try:
+        return mesonlib.verbose_git(cmd, workingdir, check=check)
+    except mesonlib.GitException as e:
+        raise WrapException(str(e))
 
 class Resolver:
-    def __init__(self, subdir_root: str, wrap_mode=WrapMode.default):
+    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 = subdir_root
+        self.subdir_root = os.path.join(source_dir, 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]
+        self.provided_programs = {} # type: T.Dict[str, PackageDefinition]
+        self.load_wraps()
+
+    def load_wraps(self) -> None:
+        if not os.path.isdir(self.subdir_root):
+            return
+        root, dirs, files = next(os.walk(self.subdir_root))
+        for i in files:
+            if not i.endswith('.wrap'):
+                continue
+            fname = os.path.join(self.subdir_root, i)
+            wrap = PackageDefinition(fname, self.subproject)
+            self.wraps[wrap.name] = wrap
+            if wrap.directory in dirs:
+                dirs.remove(wrap.directory)
+        # Add dummy package definition for directories not associated with a wrap file.
+        for i in dirs:
+            if i in ['packagecache', 'packagefiles']:
+                continue
+            fname = os.path.join(self.subdir_root, i)
+            wrap = PackageDefinition(fname, self.subproject)
+            self.wraps[wrap.name] = wrap
+
+        for wrap in self.wraps.values():
+            for k in wrap.provided_deps.keys():
+                if k in self.provided_deps:
+                    prev_wrap = self.provided_deps[k]
+                    m = f'Multiple wrap files provide {k!r} dependency: {wrap.basename} and {prev_wrap.basename}'
+                    raise WrapException(m)
+                self.provided_deps[k] = wrap
+            for k in wrap.provided_programs:
+                if k in self.provided_programs:
+                    prev_wrap = self.provided_programs[k]
+                    m = f'Multiple wrap files provide {k!r} program: {wrap.basename} and {prev_wrap.basename}'
+                    raise WrapException(m)
+                self.provided_programs[k] = wrap
+
+    def merge_wraps(self, other_resolver: 'Resolver') -> None:
+        for k, v in other_resolver.wraps.items():
+            self.wraps.setdefault(k, v)
+        for k, v in other_resolver.provided_deps.items():
+            self.provided_deps.setdefault(k, v)
+        for k, v in other_resolver.provided_programs.items():
+            self.provided_programs.setdefault(k, v)
+
+    def find_dep_provider(self, packagename: str) -> T.Tuple[T.Optional[str], T.Optional[str]]:
+        # Python's ini parser converts all key values to lowercase.
+        # Thus the query name must also be in lower case.
+        packagename = packagename.lower()
+        wrap = self.provided_deps.get(packagename)
+        if wrap:
+            dep_var = wrap.provided_deps.get(packagename)
+            return wrap.name, dep_var
+        return None, None
+
+    def get_varname(self, subp_name: str, depname: str) -> T.Optional[str]:
+        wrap = self.wraps.get(subp_name)
+        return wrap.provided_deps.get(depname) if wrap else None
+
+    def find_program_provider(self, names: T.List[str]) -> T.Optional[str]:
+        for name in names:
+            wrap = self.provided_programs.get(name)
+            if wrap:
+                return wrap.name
+        return None
 
     def resolve(self, packagename: str, method: str) -> str:
         self.packagename = packagename
-        self.wrap, self.directory = get_directory(self.subdir_root, self.packagename)
-        self.dirname = os.path.join(self.subdir_root, self.directory)
+        self.directory = packagename
+        self.wrap = self.wraps.get(packagename)
+        if not self.wrap:
+            m = f'Neither a subproject directory nor a {self.packagename}.wrap file was found.'
+            raise WrapNotFoundException(m)
+        self.directory = self.wrap.directory
+
+        if self.wrap.has_wrap:
+            # We have a .wrap file, source code will be placed into main
+            # project's subproject_dir even if the wrap file comes from another
+            # subproject.
+            self.dirname = os.path.join(self.subdir_root, self.directory)
+            # Check if the wrap comes from the main project.
+            main_fname = os.path.join(self.subdir_root, self.wrap.basename)
+            if self.wrap.filename != main_fname:
+                rel = os.path.relpath(self.wrap.filename, self.source_dir)
+                mlog.log('Using', mlog.bold(rel))
+                # Write a dummy wrap file in main project that redirect to the
+                # wrap we picked.
+                with open(main_fname, 'w', encoding='utf-8') as f:
+                    f.write(textwrap.dedent('''\
+                        [wrap-redirect]
+                        filename = {}
+                        '''.format(os.path.relpath(self.wrap.filename, self.subdir_root))))
+        else:
+            # No wrap file, it's a dummy package definition for an existing
+            # directory. Use the source code in place.
+            self.dirname = self.wrap.filename
+        rel_path = os.path.relpath(self.dirname, self.source_dir)
+
         meson_file = os.path.join(self.dirname, 'meson.build')
         cmake_file = os.path.join(self.dirname, 'CMakeLists.txt')
 
@@ -163,9 +319,9 @@
 
         # The directory is there and has meson.build? Great, use it.
         if method == 'meson' and os.path.exists(meson_file):
-            return self.directory
+            return rel_path
         if method == 'cmake' and os.path.exists(cmake_file):
-            return self.directory
+            return rel_path
 
         # Check if the subproject is a git submodule
         self.resolve_git_submodule()
@@ -174,11 +330,6 @@
             if not os.path.isdir(self.dirname):
                 raise WrapException('Path already exists but is not a directory')
         else:
-            # A wrap file is required to download
-            if not self.wrap:
-                m = 'Subproject directory not found and {}.wrap file not found'
-                raise WrapNotFoundException(m.format(self.packagename))
-
             if self.wrap.type == 'file':
                 self.get_file()
             else:
@@ -190,7 +341,8 @@
                 elif self.wrap.type == "svn":
                     self.get_svn()
                 else:
-                    raise WrapException('Unknown wrap type {!r}'.format(self.wrap.type))
+                    raise WrapException(f'Unknown wrap type {self.wrap.type!r}')
+            self.apply_patch()
 
         # A meson.build or CMakeLists.txt file is required in the directory
         if method == 'meson' and not os.path.exists(meson_file):
@@ -198,7 +350,7 @@
         if method == 'cmake' and not os.path.exists(cmake_file):
             raise WrapException('Subproject exists but has no CMakeLists.txt file')
 
-        return self.directory
+        return rel_path
 
     def check_can_download(self) -> None:
         # Don't download subproject data based on wrap file if requested.
@@ -208,8 +360,10 @@
             raise WrapException(m)
 
     def resolve_git_submodule(self) -> bool:
+        # Is git installed? If not, we're probably not in a git repository and
+        # definitely cannot try to conveniently set up a submodule.
         if not GIT:
-            raise WrapException('Git program not found.')
+            return False
         # Are we in a git repository?
         ret, out = quiet_git(['rev-parse'], self.subdir_root)
         if not ret:
@@ -238,8 +392,7 @@
         elif out == '':
             # It is not a submodule, just a folder that exists in the main repository.
             return False
-        m = 'Unknown git submodule output: {!r}'
-        raise WrapException(m.format(out))
+        raise WrapException(f'Unknown git submodule output: {out!r}')
 
     def get_file(self) -> None:
         path = self.get_file_internal('source')
@@ -250,13 +403,12 @@
             os.mkdir(self.dirname)
             extract_dir = self.dirname
         shutil.unpack_archive(path, extract_dir)
-        if self.wrap.has_patch():
-            self.apply_patch()
 
     def get_git(self) -> None:
         if not GIT:
-            raise WrapException('Git program not found.')
+            raise WrapException(f'Git program not found, cannot download {self.packagename}.wrap via git.')
         revno = self.wrap.get('revision')
+        checkout_cmd = ['-c', 'advice.detachedHead=false', 'checkout', revno, '--']
         is_shallow = False
         depth_option = []    # type: T.List[str]
         if self.wrap.values.get('depth', '') != '':
@@ -266,11 +418,11 @@
         if is_shallow and self.is_git_full_commit_id(revno):
             # git doesn't support directly cloning shallowly for commits,
             # so we follow https://stackoverflow.com/a/43136160
-            verbose_git(['init', self.directory], self.subdir_root, check=True)
+            verbose_git(['-c', 'init.defaultBranch=meson-dummy-branch', 'init', self.directory], self.subdir_root, check=True)
             verbose_git(['remote', 'add', 'origin', self.wrap.get('url')], self.dirname, check=True)
             revno = self.wrap.get('revision')
             verbose_git(['fetch', *depth_option, 'origin', revno], self.dirname, check=True)
-            verbose_git(['checkout', revno], self.dirname, check=True)
+            verbose_git(checkout_cmd, self.dirname, check=True)
             if self.wrap.values.get('clone-recursive', '').lower() == 'true':
                 verbose_git(['submodule', 'update', '--init', '--checkout',
                              '--recursive', *depth_option], self.dirname, check=True)
@@ -281,9 +433,9 @@
             if not is_shallow:
                 verbose_git(['clone', self.wrap.get('url'), self.directory], self.subdir_root, check=True)
                 if revno.lower() != 'head':
-                    if not verbose_git(['checkout', revno], self.dirname):
+                    if not verbose_git(checkout_cmd, self.dirname):
                         verbose_git(['fetch', self.wrap.get('url'), revno], self.dirname, check=True)
-                        verbose_git(['checkout', revno], self.dirname, check=True)
+                        verbose_git(checkout_cmd, self.dirname, check=True)
             else:
                 verbose_git(['clone', *depth_option, '--branch', revno, self.wrap.get('url'),
                              self.directory], self.subdir_root, check=True)
@@ -297,7 +449,7 @@
     def is_git_full_commit_id(self, revno: str) -> bool:
         result = False
         if len(revno) in (40, 64): # 40 for sha1, 64 for upcoming sha256
-            result = all((ch in '0123456789AaBbCcDdEeFf' for ch in revno))
+            result = all(ch in '0123456789AaBbCcDdEeFf' for ch in revno)
         return result
 
     def get_hg(self) -> None:
@@ -327,12 +479,14 @@
         if url.hostname and url.hostname.endswith(WHITELIST_SUBDOMAIN):
             resp = open_wrapdburl(urlstring)
         elif WHITELIST_SUBDOMAIN in urlstring:
-            raise WrapException('{} may be a WrapDB-impersonating URL'.format(urlstring))
+            raise WrapException(f'{urlstring} may be a WrapDB-impersonating URL')
         else:
             try:
-                resp = urllib.request.urlopen(urlstring, timeout=REQ_TIMEOUT)
-            except urllib.error.URLError:
-                raise WrapException('could not get {} is the internet available?'.format(urlstring))
+                req = urllib.request.Request(urlstring, headers={'User-Agent': f'mesonbuild/{coredata.version}'})
+                resp = urllib.request.urlopen(req, timeout=REQ_TIMEOUT)
+            except urllib.error.URLError as e:
+                mlog.log(str(e))
+                raise WrapException(f'could not get {urlstring} is the internet available?')
         with contextlib.closing(resp) as resp:
             try:
                 dlsize = int(resp.info()['Content-Length'])
@@ -362,48 +516,76 @@
             hashvalue = h.hexdigest()
         return hashvalue, tmpfile.name
 
-    def check_hash(self, what: str, path: str) -> None:
-        expected = self.wrap.get(what + '_hash')
+    def check_hash(self, what: str, path: str, hash_required: bool = True) -> None:
+        if what + '_hash' not in self.wrap.values and not hash_required:
+            return
+        expected = self.wrap.get(what + '_hash').lower()
         h = hashlib.sha256()
         with open(path, 'rb') as f:
             h.update(f.read())
         dhash = h.hexdigest()
         if dhash != expected:
-            raise WrapException('Incorrect hash for {}:\n {} expected\n {} actual.'.format(what, expected, dhash))
+            raise WrapException(f'Incorrect hash for {what}:\n {expected} expected\n {dhash} actual.')
 
-    def download(self, what: str, ofname: str) -> None:
+    def download(self, what: str, ofname: str, fallback: bool = False) -> None:
         self.check_can_download()
-        srcurl = self.wrap.get(what + '_url')
+        srcurl = self.wrap.get(what + ('_fallback_url' if fallback else '_url'))
         mlog.log('Downloading', mlog.bold(self.packagename), what, 'from', mlog.bold(srcurl))
-        dhash, tmpfile = self.get_data(srcurl)
-        expected = self.wrap.get(what + '_hash')
-        if dhash != expected:
-            os.remove(tmpfile)
-            raise WrapException('Incorrect hash for {}:\n {} expected\n {} actual.'.format(what, expected, dhash))
+        try:
+            dhash, tmpfile = self.get_data(srcurl)
+            expected = self.wrap.get(what + '_hash').lower()
+            if dhash != expected:
+                os.remove(tmpfile)
+                raise WrapException(f'Incorrect hash for {what}:\n {expected} expected\n {dhash} actual.')
+        except WrapException:
+            if not fallback:
+                if what + '_fallback_url' in self.wrap.values:
+                    return self.download(what, ofname, fallback=True)
+                mlog.log('A fallback URL could be specified using',
+                         mlog.bold(what + '_fallback_url'), 'key in the wrap file')
+            raise
         os.rename(tmpfile, ofname)
 
     def get_file_internal(self, what: str) -> str:
         filename = self.wrap.get(what + '_filename')
-        cache_path = os.path.join(self.cachedir, filename)
+        if what + '_url' in self.wrap.values:
+            cache_path = os.path.join(self.cachedir, filename)
 
-        if os.path.exists(cache_path):
-            self.check_hash(what, cache_path)
-            mlog.log('Using', mlog.bold(self.packagename), what, 'from cache.')
+            if os.path.exists(cache_path):
+                self.check_hash(what, cache_path)
+                mlog.log('Using', mlog.bold(self.packagename), what, 'from cache.')
+                return cache_path
+
+            os.makedirs(self.cachedir, exist_ok=True)
+            self.download(what, cache_path)
             return cache_path
+        else:
+            path = Path(self.wrap.filesdir) / filename
+
+            if not path.exists():
+                raise WrapException(f'File "{path}" does not exist')
+            self.check_hash(what, path.as_posix(), hash_required=False)
 
-        if not os.path.isdir(self.cachedir):
-            os.mkdir(self.cachedir)
-        self.download(what, cache_path)
-        return cache_path
+            return path.as_posix()
 
     def apply_patch(self) -> None:
-        path = self.get_file_internal('patch')
-        try:
-            shutil.unpack_archive(path, self.subdir_root)
-        except Exception:
-            with tempfile.TemporaryDirectory() as workdir:
-                shutil.unpack_archive(path, workdir)
-                self.copy_tree(workdir, self.subdir_root)
+        if 'patch_filename' in self.wrap.values and 'patch_directory' in self.wrap.values:
+            m = f'Wrap file {self.wrap.basename!r} must not have both "patch_filename" and "patch_directory"'
+            raise WrapException(m)
+        if 'patch_filename' in self.wrap.values:
+            path = self.get_file_internal('patch')
+            try:
+                shutil.unpack_archive(path, self.subdir_root)
+            except Exception:
+                with tempfile.TemporaryDirectory() as workdir:
+                    shutil.unpack_archive(path, workdir)
+                    self.copy_tree(workdir, self.subdir_root)
+        elif 'patch_directory' in self.wrap.values:
+            patch_dir = self.wrap.values['patch_directory']
+            src_dir = os.path.join(self.wrap.filesdir, patch_dir)
+            if not os.path.isdir(src_dir):
+                raise WrapException(f'patch directory does not exist: {patch_dir}')
+            self.copy_tree(src_dir, self.dirname)
 
     def copy_tree(self, root_src_dir: str, root_dst_dir: str) -> None:
         """
diff -Nru meson-0.53.2/mesonbuild/wrap/wraptool.py meson-0.61.2/mesonbuild/wrap/wraptool.py
--- meson-0.53.2/mesonbuild/wrap/wraptool.py	2019-12-29 22:47:27.000000000 +0000
+++ meson-0.61.2/mesonbuild/wrap/wraptool.py	2021-12-26 16:24:25.000000000 +0000
@@ -16,14 +16,19 @@
 import sys, os
 import configparser
 import shutil
+import typing as T
 
 from glob import glob
-
-from .wrap import API_ROOT, open_wrapdburl
+from urllib.parse import urlparse
+from urllib.request import urlopen
+from .wrap import WrapException
 
 from .. import mesonlib
 
-def add_arguments(parser):
+if T.TYPE_CHECKING:
+    import argparse
+
+def add_arguments(parser: 'argparse.ArgumentParser') -> None:
     subparsers = parser.add_subparsers(title='Commands', dest='command')
     subparsers.required = True
 
@@ -53,38 +58,36 @@
     p.add_argument('project_path')
     p.set_defaults(wrap_func=promote)
 
-def get_result(urlstring):
-    u = open_wrapdburl(urlstring)
-    data = u.read().decode('utf-8')
-    jd = json.loads(data)
-    if jd['output'] != 'ok':
-        print('Got bad output from server.', file=sys.stderr)
-        raise SystemExit(data)
-    return jd
-
-def get_projectlist():
-    jd = get_result(API_ROOT + 'projects')
-    projects = jd['projects']
-    return projects
-
-def list_projects(options):
-    projects = get_projectlist()
-    for p in projects:
+def get_releases() -> T.Dict[str, T.Any]:
+    url = urlopen('https://wrapdb.mesonbuild.com/v2/releases.json')
+    return T.cast(T.Dict[str, T.Any], json.loads(url.read().decode()))
+
+def list_projects(options: 'argparse.Namespace') -> None:
+    releases = get_releases()
+    for p in releases.keys():
         print(p)
 
-def search(options):
+def search(options: 'argparse.Namespace') -> None:
     name = options.name
-    jd = get_result(API_ROOT + 'query/byname/' + name)
-    for p in jd['projects']:
-        print(p)
-
-def get_latest_version(name: str) -> tuple:
-    jd = get_result(API_ROOT + 'query/get_latest/' + name)
-    branch = jd['branch']
-    revision = jd['revision']
-    return branch, revision
+    releases = get_releases()
+    for p, info in releases.items():
+        if p.find(name) != -1:
+            print(p)
+        else:
+            for dep in info.get('dependency_names', []):
+                if dep.find(name) != -1:
+                    print(f'Dependency {dep} found in wrap {p}')
+
+def get_latest_version(name: str) -> T.Tuple[str, str]:
+    releases = get_releases()
+    info = releases.get(name)
+    if not info:
+        raise WrapException(f'Wrap {name} not found in wrapdb')
+    latest_version = info['versions'][0]
+    version, revision = latest_version.rsplit('-', 1)
+    return version, revision
 
-def install(options):
+def install(options: 'argparse.Namespace') -> None:
     name = options.name
     if not os.path.isdir('subprojects'):
         raise SystemExit('Subprojects dir not found. Run this script in your source root directory.')
@@ -93,32 +96,43 @@
     wrapfile = os.path.join('subprojects', name + '.wrap')
     if os.path.exists(wrapfile):
         raise SystemExit('Wrap file already exists.')
-    (branch, revision) = get_latest_version(name)
-    u = open_wrapdburl(API_ROOT + 'projects/{}/{}/{}/get_wrap'.format(name, branch, revision))
-    data = u.read()
+    (version, revision) = get_latest_version(name)
+    url = urlopen(f'https://wrapdb.mesonbuild.com/v2/{name}_{version}-{revision}/{name}.wrap')
     with open(wrapfile, 'wb') as f:
-        f.write(data)
-    print('Installed', name, 'branch', branch, 'revision', revision)
+        f.write(url.read())
+    print(f'Installed {name} version {version} revision {revision}')
 
-def parse_patch_url(patch_url):
-    arr = patch_url.split('/')
-    return arr[-3], int(arr[-2])
+def parse_patch_url(patch_url: str) -> T.Tuple[str, str]:
+    u = urlparse(patch_url)
+    if u.netloc != 'wrapdb.mesonbuild.com':
+        raise WrapException(f'URL {patch_url} does not seems to be a wrapdb patch')
+    arr = u.path.strip('/').split('/')
+    if arr[0] == 'v1':
+        # e.g. https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.11/5/get_zip
+        return arr[-3], arr[-2]
+    elif arr[0] == 'v2':
+        # e.g. https://wrapdb.mesonbuild.com/v2/zlib_1.2.11-5/get_patch
+        tag = arr[-2]
+        _, version = tag.rsplit('_', 1)
+        version, revision = version.rsplit('-', 1)
+        return version, revision
+    else:
+        raise WrapException(f'Invalid wrapdb URL {patch_url}')
 
-def get_current_version(wrapfile):
-    cp = configparser.ConfigParser()
+def get_current_version(wrapfile: str) -> T.Tuple[str, str, str, str, str]:
+    cp = configparser.ConfigParser(interpolation=None)
     cp.read(wrapfile)
-    cp = cp['wrap-file']
-    patch_url = cp['patch_url']
+    wrap_data = cp['wrap-file']
+    patch_url = wrap_data['patch_url']
     branch, revision = parse_patch_url(patch_url)
-    return branch, revision, cp['directory'], cp['source_filename'], cp['patch_filename']
+    return branch, revision, wrap_data['directory'], wrap_data['source_filename'], wrap_data['patch_filename']
 
-def update_wrap_file(wrapfile, name, new_branch, new_revision):
-    u = open_wrapdburl(API_ROOT + 'projects/{}/{}/{}/get_wrap'.format(name, new_branch, new_revision))
-    data = u.read()
+def update_wrap_file(wrapfile: str, name: str, new_version: str, new_revision: str) -> None:
+    url = urlopen(f'https://wrapdb.mesonbuild.com/v2/{name}_{new_version}-{new_revision}/{name}.wrap')
     with open(wrapfile, 'wb') as f:
-        f.write(data)
+        f.write(url.read())
 
-def update(options):
+def update(options: 'argparse.Namespace') -> None:
     name = options.name
     if not os.path.isdir('subprojects'):
         raise SystemExit('Subprojects dir not found. Run this command in your source root directory.')
@@ -140,30 +154,30 @@
         os.unlink(os.path.join('subprojects/packagecache', patch_file))
     except FileNotFoundError:
         pass
-    print('Updated', name, 'to branch', new_branch, 'revision', new_revision)
+    print(f'Updated {name} version {new_branch} revision {new_revision}')
 
-def info(options):
+def info(options: 'argparse.Namespace') -> None:
     name = options.name
-    jd = get_result(API_ROOT + 'projects/' + name)
-    versions = jd['versions']
-    if not versions:
-        raise SystemExit('No available versions of' + name)
-    print('Available versions of {}:'.format(name))
-    for v in versions:
-        print(' ', v['branch'], v['revision'])
+    releases = get_releases()
+    info = releases.get(name)
+    if not info:
+        raise WrapException(f'Wrap {name} not found in wrapdb')
+    print(f'Available versions of {name}:')
+    for v in info['versions']:
+        print(' ', v)
 
-def do_promotion(from_path, spdir_name):
+def do_promotion(from_path: str, spdir_name: str) -> None:
     if os.path.isfile(from_path):
-        assert(from_path.endswith('.wrap'))
+        assert from_path.endswith('.wrap')
         shutil.copy(from_path, spdir_name)
     elif os.path.isdir(from_path):
         sproj_name = os.path.basename(from_path)
         outputdir = os.path.join(spdir_name, sproj_name)
         if os.path.exists(outputdir):
-            raise SystemExit('Output dir {} already exists. Will not overwrite.'.format(outputdir))
+            raise SystemExit(f'Output dir {outputdir} already exists. Will not overwrite.')
         shutil.copytree(from_path, outputdir, ignore=shutil.ignore_patterns('subprojects'))
 
-def promote(options):
+def promote(options: 'argparse.Namespace') -> None:
     argument = options.project_path
     spdir_name = 'subprojects'
     sprojs = mesonlib.detect_subprojects(spdir_name)
@@ -177,16 +191,16 @@
 
     # otherwise the argument is just a subproject basename which must be unambiguous
     if argument not in sprojs:
-        raise SystemExit('Subproject {} not found in directory tree.'.format(argument))
+        raise SystemExit(f'Subproject {argument} not found in directory tree.')
     matches = sprojs[argument]
     if len(matches) > 1:
-        print('There is more than one version of {} in tree. Please specify which one to promote:\n'.format(argument), file=sys.stderr)
+        print(f'There is more than one version of {argument} in tree. Please specify which one to promote:\n', file=sys.stderr)
         for s in matches:
             print(s, file=sys.stderr)
         raise SystemExit(1)
     do_promotion(matches[0], spdir_name)
 
-def status(options):
+def status(options: 'argparse.Namespace') -> None:
     print('Subproject status')
     for w in glob('subprojects/*.wrap'):
         name = os.path.basename(w)[:-5]
@@ -201,10 +215,10 @@
             print('Wrap file not from wrapdb.', file=sys.stderr)
             continue
         if current_branch == latest_branch and current_revision == latest_revision:
-            print('', name, 'up to date. Branch {}, revision {}.'.format(current_branch, current_revision))
+            print('', name, f'up to date. Branch {current_branch}, revision {current_revision}.')
         else:
-            print('', name, 'not up to date. Have {} {}, but {} {} is available.'.format(current_branch, current_revision, latest_branch, latest_revision))
+            print('', name, f'not up to date. Have {current_branch} {current_revision}, but {latest_branch} {latest_revision} is available.')
 
-def run(options):
+def run(options: 'argparse.Namespace') -> int:
     options.wrap_func(options)
     return 0
diff -Nru meson-0.53.2/meson.egg-info/PKG-INFO meson-0.61.2/meson.egg-info/PKG-INFO
--- meson-0.53.2/meson.egg-info/PKG-INFO	2020-02-25 16:01:43.000000000 +0000
+++ meson-0.61.2/meson.egg-info/PKG-INFO	2022-02-14 19:23:55.000000000 +0000
@@ -1,12 +1,11 @@
 Metadata-Version: 2.1
 Name: meson
-Version: 0.53.2
+Version: 0.61.2
 Summary: A high performance build system
 Home-page: https://mesonbuild.com
 Author: Jussi Pakkanen
 Author-email: jpakkane@gmail.com
 License: Apache License, Version 2.0
-Description: Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL.
 Keywords: meson,mesonbuild,build system,cmake
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
@@ -19,10 +18,16 @@
 Classifier: Operating System :: POSIX :: BSD
 Classifier: Operating System :: POSIX :: Linux
 Classifier: Programming Language :: Python :: 3 :: Only
-Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Classifier: Topic :: Software Development :: Build Tools
-Requires-Python: >=3.5.2
+Requires-Python: >=3.6
+Provides-Extra: ninja
 Provides-Extra: progress
+Provides-Extra: typing
+License-File: COPYING
+
+Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL.
+
diff -Nru meson-0.53.2/meson.egg-info/requires.txt meson-0.61.2/meson.egg-info/requires.txt
--- meson-0.53.2/meson.egg-info/requires.txt	2020-02-25 16:01:43.000000000 +0000
+++ meson-0.61.2/meson.egg-info/requires.txt	2022-02-14 19:23:55.000000000 +0000
@@ -1,3 +1,12 @@
 
+[ninja]
+ninja>=1.8.2
+
 [progress]
 tqdm
+
+[typing]
+mypy
+
+[typing:python_version < "3.8"]
+typing_extensions
diff -Nru meson-0.53.2/meson.egg-info/SOURCES.txt meson-0.61.2/meson.egg-info/SOURCES.txt
--- meson-0.53.2/meson.egg-info/SOURCES.txt	2020-02-25 16:01:43.000000000 +0000
+++ meson-0.61.2/meson.egg-info/SOURCES.txt	2022-02-14 19:23:55.000000000 +0000
@@ -1,8 +1,7 @@
 COPYING
 MANIFEST.in
 README.md
-__main__.py
-ghwt.py
+contributing.md
 meson.py
 pyproject.toml
 run_cross_test.py
@@ -12,20 +11,31 @@
 run_unittests.py
 setup.cfg
 setup.py
+cross/arm64cl.txt
 cross/armcc.txt
 cross/armclang-linux.txt
 cross/armclang.txt
+cross/c2000.txt
+cross/ccomp-armv7a.txt
 cross/ccrx.txt
 cross/iphone.txt
+cross/linux-mingw-w64-32bit.json
 cross/linux-mingw-w64-32bit.txt
+cross/linux-mingw-w64-64bit.json
 cross/linux-mingw-w64-64bit.txt
+cross/none.txt
 cross/ownstdlib.txt
 cross/tvos.txt
+cross/ubuntu-armhf.json
 cross/ubuntu-armhf.txt
 cross/ubuntu-faketarget.txt
 cross/wasm.txt
+cross/xc16.txt
+data/.coveragerc.in
 data/com.mesonbuild.install.policy
 data/macros.meson
+data/schema.xsd
+data/test.schema.json
 data/shell-completions/bash/meson
 data/shell-completions/zsh/_meson
 data/syntax-highlighting/emacs/meson.el
@@ -82,12 +92,6 @@
 manual tests/7 vala composite widgets/mywidget.vala
 manual tests/8 timeout/meson.build
 manual tests/8 timeout/sleepprog.c
-manual tests/9 nostdlib/meson.build
-manual tests/9 nostdlib/prog.c
-manual tests/9 nostdlib/subprojects/mylibc/libc.c
-manual tests/9 nostdlib/subprojects/mylibc/meson.build
-manual tests/9 nostdlib/subprojects/mylibc/stdio.h
-manual tests/9 nostdlib/subprojects/mylibc/stubstart.s
 meson.egg-info/PKG-INFO
 meson.egg-info/SOURCES.txt
 meson.egg-info/dependency_links.txt
@@ -95,17 +99,19 @@
 meson.egg-info/requires.txt
 meson.egg-info/top_level.txt
 mesonbuild/__init__.py
+mesonbuild/_pathlib.py
+mesonbuild/_typing.py
+mesonbuild/arglist.py
 mesonbuild/build.py
 mesonbuild/coredata.py
 mesonbuild/depfile.py
 mesonbuild/envconfig.py
 mesonbuild/environment.py
-mesonbuild/interpreter.py
-mesonbuild/interpreterbase.py
-mesonbuild/linkers.py
+mesonbuild/mcompile.py
 mesonbuild/mconf.py
+mesonbuild/mdevenv.py
 mesonbuild/mdist.py
-mesonbuild/mesonlib.py
+mesonbuild/mesondata.py
 mesonbuild/mesonmain.py
 mesonbuild/minit.py
 mesonbuild/minstall.py
@@ -117,6 +123,7 @@
 mesonbuild/mtest.py
 mesonbuild/munstable_coredata.py
 mesonbuild/optinterpreter.py
+mesonbuild/programs.py
 mesonbuild/rewriter.py
 mesonbuild/ast/__init__.py
 mesonbuild/ast/interpreter.py
@@ -128,9 +135,12 @@
 mesonbuild/backend/backends.py
 mesonbuild/backend/ninjabackend.py
 mesonbuild/backend/vs2010backend.py
+mesonbuild/backend/vs2012backend.py
+mesonbuild/backend/vs2013backend.py
 mesonbuild/backend/vs2015backend.py
 mesonbuild/backend/vs2017backend.py
 mesonbuild/backend/vs2019backend.py
+mesonbuild/backend/vs2022backend.py
 mesonbuild/backend/xcodebackend.py
 mesonbuild/cmake/__init__.py
 mesonbuild/cmake/client.py
@@ -139,9 +149,10 @@
 mesonbuild/cmake/fileapi.py
 mesonbuild/cmake/generator.py
 mesonbuild/cmake/interpreter.py
+mesonbuild/cmake/toolchain.py
 mesonbuild/cmake/traceparser.py
+mesonbuild/cmake/tracetargets.py
 mesonbuild/cmake/data/preload.cmake
-mesonbuild/cmake/data/run_ctgt.py
 mesonbuild/compilers/__init__.py
 mesonbuild/compilers/c.py
 mesonbuild/compilers/c_function_attributes.py
@@ -149,7 +160,9 @@
 mesonbuild/compilers/cpp.py
 mesonbuild/compilers/cs.py
 mesonbuild/compilers/cuda.py
+mesonbuild/compilers/cython.py
 mesonbuild/compilers/d.py
+mesonbuild/compilers/detect.py
 mesonbuild/compilers/fortran.py
 mesonbuild/compilers/java.py
 mesonbuild/compilers/objc.py
@@ -159,9 +172,11 @@
 mesonbuild/compilers/vala.py
 mesonbuild/compilers/mixins/__init__.py
 mesonbuild/compilers/mixins/arm.py
+mesonbuild/compilers/mixins/c2000.py
 mesonbuild/compilers/mixins/ccrx.py
 mesonbuild/compilers/mixins/clang.py
 mesonbuild/compilers/mixins/clike.py
+mesonbuild/compilers/mixins/compcert.py
 mesonbuild/compilers/mixins/elbrus.py
 mesonbuild/compilers/mixins/emscripten.py
 mesonbuild/compilers/mixins/gnu.py
@@ -169,21 +184,63 @@
 mesonbuild/compilers/mixins/islinker.py
 mesonbuild/compilers/mixins/pgi.py
 mesonbuild/compilers/mixins/visualstudio.py
+mesonbuild/compilers/mixins/xc16.py
 mesonbuild/dependencies/__init__.py
 mesonbuild/dependencies/base.py
 mesonbuild/dependencies/boost.py
+mesonbuild/dependencies/cmake.py
 mesonbuild/dependencies/coarrays.py
+mesonbuild/dependencies/configtool.py
 mesonbuild/dependencies/cuda.py
+mesonbuild/dependencies/detect.py
 mesonbuild/dependencies/dev.py
+mesonbuild/dependencies/dub.py
+mesonbuild/dependencies/factory.py
+mesonbuild/dependencies/framework.py
 mesonbuild/dependencies/hdf5.py
 mesonbuild/dependencies/misc.py
 mesonbuild/dependencies/mpi.py
+mesonbuild/dependencies/pkgconfig.py
 mesonbuild/dependencies/platform.py
+mesonbuild/dependencies/qt.py
 mesonbuild/dependencies/scalapack.py
 mesonbuild/dependencies/ui.py
 mesonbuild/dependencies/data/CMakeLists.txt
 mesonbuild/dependencies/data/CMakeListsLLVM.txt
 mesonbuild/dependencies/data/CMakePathInfo.txt
+mesonbuild/interpreter/__init__.py
+mesonbuild/interpreter/compiler.py
+mesonbuild/interpreter/dependencyfallbacks.py
+mesonbuild/interpreter/interpreter.py
+mesonbuild/interpreter/interpreterobjects.py
+mesonbuild/interpreter/kwargs.py
+mesonbuild/interpreter/mesonmain.py
+mesonbuild/interpreter/type_checking.py
+mesonbuild/interpreter/primitives/__init__.py
+mesonbuild/interpreter/primitives/array.py
+mesonbuild/interpreter/primitives/boolean.py
+mesonbuild/interpreter/primitives/dict.py
+mesonbuild/interpreter/primitives/integer.py
+mesonbuild/interpreter/primitives/range.py
+mesonbuild/interpreter/primitives/string.py
+mesonbuild/interpreterbase/__init__.py
+mesonbuild/interpreterbase/_unholder.py
+mesonbuild/interpreterbase/baseobjects.py
+mesonbuild/interpreterbase/decorators.py
+mesonbuild/interpreterbase/disabler.py
+mesonbuild/interpreterbase/exceptions.py
+mesonbuild/interpreterbase/helpers.py
+mesonbuild/interpreterbase/interpreterbase.py
+mesonbuild/interpreterbase/operator.py
+mesonbuild/linkers/__init__.py
+mesonbuild/linkers/detect.py
+mesonbuild/linkers/linkers.py
+mesonbuild/mesonlib/__init__.py
+mesonbuild/mesonlib/platform.py
+mesonbuild/mesonlib/posix.py
+mesonbuild/mesonlib/universal.py
+mesonbuild/mesonlib/vsenv.py
+mesonbuild/mesonlib/win32.py
 mesonbuild/modules/__init__.py
 mesonbuild/modules/cmake.py
 mesonbuild/modules/dlang.py
@@ -191,6 +248,8 @@
 mesonbuild/modules/gnome.py
 mesonbuild/modules/hotdoc.py
 mesonbuild/modules/i18n.py
+mesonbuild/modules/java.py
+mesonbuild/modules/keyval.py
 mesonbuild/modules/modtest.py
 mesonbuild/modules/pkgconfig.py
 mesonbuild/modules/python.py
@@ -198,55 +257,79 @@
 mesonbuild/modules/qt.py
 mesonbuild/modules/qt4.py
 mesonbuild/modules/qt5.py
+mesonbuild/modules/qt6.py
 mesonbuild/modules/rpm.py
 mesonbuild/modules/sourceset.py
 mesonbuild/modules/unstable_cuda.py
+mesonbuild/modules/unstable_external_project.py
 mesonbuild/modules/unstable_icestorm.py
-mesonbuild/modules/unstable_kconfig.py
+mesonbuild/modules/unstable_rust.py
 mesonbuild/modules/unstable_simd.py
 mesonbuild/modules/windows.py
 mesonbuild/scripts/__init__.py
 mesonbuild/scripts/clangformat.py
 mesonbuild/scripts/clangtidy.py
 mesonbuild/scripts/cleantrees.py
-mesonbuild/scripts/commandrunner.py
+mesonbuild/scripts/cmake_run_ctgt.py
+mesonbuild/scripts/cmd_or_ps.ps1
 mesonbuild/scripts/coverage.py
 mesonbuild/scripts/delwithsuffix.py
 mesonbuild/scripts/depfixer.py
+mesonbuild/scripts/depscan.py
 mesonbuild/scripts/dirchanger.py
+mesonbuild/scripts/externalproject.py
 mesonbuild/scripts/gettext.py
 mesonbuild/scripts/gtkdochelper.py
 mesonbuild/scripts/hotdochelper.py
 mesonbuild/scripts/meson_exe.py
 mesonbuild/scripts/msgfmthelper.py
 mesonbuild/scripts/regen_checker.py
+mesonbuild/scripts/run_tool.py
 mesonbuild/scripts/scanbuild.py
 mesonbuild/scripts/symbolextractor.py
 mesonbuild/scripts/tags.py
 mesonbuild/scripts/uninstall.py
 mesonbuild/scripts/vcstagger.py
-mesonbuild/scripts/yelphelper.py
 mesonbuild/templates/__init__.py
 mesonbuild/templates/cpptemplates.py
+mesonbuild/templates/cstemplates.py
 mesonbuild/templates/ctemplates.py
+mesonbuild/templates/cudatemplates.py
 mesonbuild/templates/dlangtemplates.py
 mesonbuild/templates/fortrantemplates.py
+mesonbuild/templates/javatemplates.py
+mesonbuild/templates/mesontemplates.py
+mesonbuild/templates/objcpptemplates.py
 mesonbuild/templates/objctemplates.py
 mesonbuild/templates/rusttemplates.py
+mesonbuild/templates/samplefactory.py
+mesonbuild/templates/sampleimpl.py
+mesonbuild/templates/valatemplates.py
 mesonbuild/wrap/__init__.py
 mesonbuild/wrap/wrap.py
 mesonbuild/wrap/wraptool.py
+packaging/License.rtf
+packaging/create_zipapp.py
+packaging/createmsi.py
+packaging/createpkg.py
+packaging/macpages/English.lproj/conclusion.html
+packaging/macpages/English.lproj/license.html
+packaging/macpages/English.lproj/welcome.html
 test cases/cmake/1 basic/main.cpp
 test cases/cmake/1 basic/meson.build
 test cases/cmake/1 basic/subprojects/cmMod/CMakeLists.txt
 test cases/cmake/1 basic/subprojects/cmMod/cmMod.cpp
 test cases/cmake/1 basic/subprojects/cmMod/cmMod.hpp
+test cases/cmake/1 basic/subprojects/cmMod/cpp_pch.hpp
 test cases/cmake/10 header only/main.cpp
 test cases/cmake/10 header only/meson.build
 test cases/cmake/10 header only/subprojects/cmMod/CMakeLists.txt
 test cases/cmake/10 header only/subprojects/cmMod/include/cmMod.hpp
 test cases/cmake/11 cmake_module_path/meson.build
+test cases/cmake/11 cmake_module_path/test.json
 test cases/cmake/11 cmake_module_path/cmake/FindSomethingLikePython.cmake
+test cases/cmake/11 cmake_module_path/subprojects/cmMod/CMakeLists.txt
+test cases/cmake/11 cmake_module_path/subprojects/cmMod/gen.py
 test cases/cmake/12 generator expressions/main.cpp
 test cases/cmake/12 generator expressions/meson.build
 test cases/cmake/12 generator expressions/subprojects/cmMod/CMakeLists.txt
@@ -269,22 +352,89 @@
 test cases/cmake/16 threads/main.cpp
 test cases/cmake/16 threads/meson.build
 test cases/cmake/16 threads/meson_options.txt
-test cases/cmake/16 threads/test_matrix.json
+test cases/cmake/16 threads/test.json
 test cases/cmake/16 threads/subprojects/cmMod/CMakeLists.txt
 test cases/cmake/16 threads/subprojects/cmMod/cmMod.cpp
 test cases/cmake/16 threads/subprojects/cmMod/cmMod.hpp
 test cases/cmake/16 threads/subprojects/cmMod/main.cpp
-test cases/cmake/2 advanced/installed_files.txt
+test cases/cmake/17 include path order/main.cpp
+test cases/cmake/17 include path order/meson.build
+test cases/cmake/17 include path order/subprojects/cmMod/CMakeLists.txt
+test cases/cmake/17 include path order/subprojects/cmMod/cmMod.cpp
+test cases/cmake/17 include path order/subprojects/cmMod/incA/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incB/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incC/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incD/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incE/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incF/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incG/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incH/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incI/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incJ/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incL/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incM/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incN/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incO/cmMod.hpp
+test cases/cmake/17 include path order/subprojects/cmMod/incP/cmMod.hpp
+test cases/cmake/18 skip include files/main.cpp
+test cases/cmake/18 skip include files/meson.build
+test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt
+test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp
+test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp
+test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt
+test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp
+test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp
+test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp
+test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp
+test cases/cmake/19 advanced options/main.cpp
+test cases/cmake/19 advanced options/meson.build
+test cases/cmake/19 advanced options/test.json
+test cases/cmake/19 advanced options/subprojects/cmOpts/CMakeLists.txt
+test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.cpp
+test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.hpp
+test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.cpp
+test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.hpp
+test cases/cmake/19 advanced options/subprojects/cmOpts/main.cpp
 test cases/cmake/2 advanced/main.cpp
 test cases/cmake/2 advanced/meson.build
+test cases/cmake/2 advanced/test.json
 test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt
 test cases/cmake/2 advanced/subprojects/cmMod/config.h.in
 test cases/cmake/2 advanced/subprojects/cmMod/main.cpp
 test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp
 test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.hpp
-test cases/cmake/3 advanced no dep/installed_files.txt
+test cases/cmake/20 cmake file/foolib.cmake.in
+test cases/cmake/20 cmake file/meson.build
+test cases/cmake/20 cmake file/test.json
+test cases/cmake/21 shared module/meson.build
+test cases/cmake/21 shared module/prog.c
+test cases/cmake/21 shared module/runtime.c
+test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt
+test cases/cmake/21 shared module/subprojects/cmMod/module/module.c
+test cases/cmake/21 shared module/subprojects/cmMod/module/module.h
+test cases/cmake/22 cmake module/meson.build
+test cases/cmake/22 cmake module/projectConfig.cmake.in
+test cases/cmake/22 cmake module/test.json
+test cases/cmake/22 cmake module/cmake_project/CMakeLists.txt
+test cases/cmake/23 cmake toolchain/CMakeToolchain.cmake
+test cases/cmake/23 cmake toolchain/meson.build
+test cases/cmake/23 cmake toolchain/nativefile.ini.in
+test cases/cmake/23 cmake toolchain/subprojects/cmMod/CMakeLists.txt
+test cases/cmake/23 cmake toolchain/subprojects/cmModFortran/CMakeLists.txt
+test cases/cmake/24 mixing languages/main.c
+test cases/cmake/24 mixing languages/meson.build
+test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt
+test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c
+test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h
+test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m
+test cases/cmake/25 assembler/main.c
+test cases/cmake/25 assembler/meson.build
+test cases/cmake/25 assembler/subprojects/cmTest/CMakeLists.txt
+test cases/cmake/25 assembler/subprojects/cmTest/cmTest.c
+test cases/cmake/25 assembler/subprojects/cmTest/cmTestAsm.s
 test cases/cmake/3 advanced no dep/main.cpp
 test cases/cmake/3 advanced no dep/meson.build
+test cases/cmake/3 advanced no dep/test.json
 test cases/cmake/3 advanced no dep/subprojects/cmMod/CMakeLists.txt
 test cases/cmake/3 advanced no dep/subprojects/cmMod/config.h.in
 test cases/cmake/3 advanced no dep/subprojects/cmMod/main.cpp
@@ -310,6 +460,7 @@
 test cases/cmake/6 object library no dep/subprojects/cmObjLib/libB.cpp
 test cases/cmake/6 object library no dep/subprojects/cmObjLib/libB.hpp
 test cases/cmake/7 cmake options/meson.build
+test cases/cmake/7 cmake options/test.json
 test cases/cmake/7 cmake options/subprojects/cmOpts/CMakeLists.txt
 test cases/cmake/8 custom command/main.cpp
 test cases/cmake/8 custom command/meson.build
@@ -320,102 +471,115 @@
 test cases/cmake/8 custom command/subprojects/cmMod/cp.cpp
 test cases/cmake/8 custom command/subprojects/cmMod/cpyBase.cpp.am
 test cases/cmake/8 custom command/subprojects/cmMod/cpyBase.hpp.am
+test cases/cmake/8 custom command/subprojects/cmMod/cpyInc.hpp.am
 test cases/cmake/8 custom command/subprojects/cmMod/cpyNext.cpp.am
 test cases/cmake/8 custom command/subprojects/cmMod/cpyNext.hpp.am
 test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp
+test cases/cmake/8 custom command/subprojects/cmMod/genMain.cpp
 test cases/cmake/8 custom command/subprojects/cmMod/macro_name.cpp
-test cases/cmake/8 custom command/subprojects/cmMod/main.cpp
 test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/CMakeLists.txt
 test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest.hpp
 test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest2.hpp
 test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest3.hpp
 test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest4.hpp
+test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest5.hpp
 test cases/cmake/9 disabled subproject/meson.build
 test cases/common/1 trivial/meson.build
 test cases/common/1 trivial/trivial.c
 test cases/common/10 man install/bar.2
 test cases/common/10 man install/baz.1.in
 test cases/common/10 man install/foo.1
-test cases/common/10 man install/installed_files.txt
+test cases/common/10 man install/foo.fr.1
 test cases/common/10 man install/meson.build
+test cases/common/10 man install/test.json
 test cases/common/10 man install/vanishing/meson.build
 test cases/common/10 man install/vanishing/vanishing.1
 test cases/common/10 man install/vanishing/vanishing.2
-test cases/common/100 stringdef/meson.build
-test cases/common/100 stringdef/stringdef.c
-test cases/common/101 find program path/meson.build
-test cases/common/101 find program path/program.py
-test cases/common/102 subproject subdir/meson.build
-test cases/common/102 subproject subdir/prog.c
-test cases/common/102 subproject subdir/subprojects/sub/meson.build
-test cases/common/102 subproject subdir/subprojects/sub/lib/meson.build
-test cases/common/102 subproject subdir/subprojects/sub/lib/sub.c
-test cases/common/102 subproject subdir/subprojects/sub/lib/sub.h
-test cases/common/103 postconf/meson.build
-test cases/common/103 postconf/postconf.py
-test cases/common/103 postconf/prog.c
-test cases/common/103 postconf/raw.dat
-test cases/common/104 postconf with args/meson.build
-test cases/common/104 postconf with args/postconf.py
-test cases/common/104 postconf with args/prog.c
-test cases/common/104 postconf with args/raw.dat
-test cases/common/105 testframework options/meson.build
-test cases/common/105 testframework options/meson_options.txt
-test cases/common/105 testframework options/test_args.txt
-test cases/common/106 extract same name/lib.c
-test cases/common/106 extract same name/main.c
-test cases/common/106 extract same name/meson.build
-test cases/common/106 extract same name/src/lib.c
-test cases/common/107 has header symbol/meson.build
-test cases/common/108 has arg/meson.build
-test cases/common/109 generatorcustom/catter.py
-test cases/common/109 generatorcustom/gen.py
-test cases/common/109 generatorcustom/main.c
-test cases/common/109 generatorcustom/meson.build
-test cases/common/109 generatorcustom/res1.txt
-test cases/common/109 generatorcustom/res2.txt
+test cases/common/100 postconf with args/meson.build
+test cases/common/100 postconf with args/postconf.py
+test cases/common/100 postconf with args/prog.c
+test cases/common/100 postconf with args/raw.dat
+test cases/common/101 testframework options/meson.build
+test cases/common/101 testframework options/meson_options.txt
+test cases/common/101 testframework options/test.json
+test cases/common/102 extract same name/lib.c
+test cases/common/102 extract same name/main.c
+test cases/common/102 extract same name/meson.build
+test cases/common/102 extract same name/src/lib.c
+test cases/common/103 has header symbol/meson.build
+test cases/common/104 has arg/meson.build
+test cases/common/105 generatorcustom/catter.py
+test cases/common/105 generatorcustom/gen-resx.py
+test cases/common/105 generatorcustom/gen.py
+test cases/common/105 generatorcustom/main.c
+test cases/common/105 generatorcustom/meson.build
+test cases/common/105 generatorcustom/res1.txt
+test cases/common/105 generatorcustom/res2.txt
+test cases/common/106 multiple dir configure file/meson.build
+test cases/common/106 multiple dir configure file/subdir/foo.txt
+test cases/common/106 multiple dir configure file/subdir/meson.build
+test cases/common/106 multiple dir configure file/subdir/someinput.in
+test cases/common/107 spaces backslash/comparer-end-notstring.c
+test cases/common/107 spaces backslash/comparer-end.c
+test cases/common/107 spaces backslash/comparer.c
+test cases/common/107 spaces backslash/meson.build
+test cases/common/107 spaces backslash/asm output/meson.build
+test cases/common/107 spaces backslash/include/comparer.h
+test cases/common/108 ternary/meson.build
+test cases/common/109 custom target capture/data_source.txt
+test cases/common/109 custom target capture/meson.build
+test cases/common/109 custom target capture/my_compiler.py
+test cases/common/109 custom target capture/test.json
 test cases/common/11 subdir/meson.build
 test cases/common/11 subdir/subdir/meson.build
 test cases/common/11 subdir/subdir/prog.c
-test cases/common/110 multiple dir configure file/meson.build
-test cases/common/110 multiple dir configure file/subdir/foo.txt
-test cases/common/110 multiple dir configure file/subdir/meson.build
-test cases/common/110 multiple dir configure file/subdir/someinput.in
-test cases/common/111 spaces backslash/comparer-end-notstring.c
-test cases/common/111 spaces backslash/comparer-end.c
-test cases/common/111 spaces backslash/comparer.c
-test cases/common/111 spaces backslash/meson.build
-test cases/common/111 spaces backslash/asm output/meson.build
-test cases/common/111 spaces backslash/include/comparer.h
-test cases/common/112 ternary/meson.build
-test cases/common/113 custom target capture/data_source.txt
-test cases/common/113 custom target capture/installed_files.txt
-test cases/common/113 custom target capture/meson.build
-test cases/common/113 custom target capture/my_compiler.py
-test cases/common/114 allgenerate/converter.py
-test cases/common/114 allgenerate/foobar.cpp.in
-test cases/common/114 allgenerate/meson.build
-test cases/common/115 pathjoin/meson.build
-test cases/common/116 subdir subproject/meson.build
-test cases/common/116 subdir subproject/prog/meson.build
-test cases/common/116 subdir subproject/prog/prog.c
-test cases/common/116 subdir subproject/subprojects/sub/meson.build
-test cases/common/116 subdir subproject/subprojects/sub/sub.c
-test cases/common/116 subdir subproject/subprojects/sub/sub.h
-test cases/common/117 interpreter copy mutable var on assignment/meson.build
-test cases/common/118 skip/meson.build
-test cases/common/119 subproject project arguments/exe.c
-test cases/common/119 subproject project arguments/exe.cpp
-test cases/common/119 subproject project arguments/meson.build
-test cases/common/119 subproject project arguments/subprojects/subexe/meson.build
-test cases/common/119 subproject project arguments/subprojects/subexe/subexe.c
+test cases/common/110 allgenerate/converter.py
+test cases/common/110 allgenerate/foobar.cpp.in
+test cases/common/110 allgenerate/meson.build
+test cases/common/111 pathjoin/meson.build
+test cases/common/112 subdir subproject/meson.build
+test cases/common/112 subdir subproject/prog/meson.build
+test cases/common/112 subdir subproject/prog/prog.c
+test cases/common/112 subdir subproject/subprojects/sub/meson.build
+test cases/common/112 subdir subproject/subprojects/sub/sub.c
+test cases/common/112 subdir subproject/subprojects/sub/sub.h
+test cases/common/113 interpreter copy mutable var on assignment/meson.build
+test cases/common/114 skip/meson.build
+test cases/common/115 subproject project arguments/exe.c
+test cases/common/115 subproject project arguments/exe.cpp
+test cases/common/115 subproject project arguments/meson.build
+test cases/common/115 subproject project arguments/subprojects/subexe/meson.build
+test cases/common/115 subproject project arguments/subprojects/subexe/subexe.c
+test cases/common/116 test skip/meson.build
+test cases/common/116 test skip/test_skip.c
+test cases/common/117 shared module/meson.build
+test cases/common/117 shared module/module.c
+test cases/common/117 shared module/nosyms.c
+test cases/common/117 shared module/prog.c
+test cases/common/117 shared module/runtime.c
+test cases/common/117 shared module/test.json
+test cases/common/118 llvm ir and assembly/main.c
+test cases/common/118 llvm ir and assembly/main.cpp
+test cases/common/118 llvm ir and assembly/meson.build
+test cases/common/118 llvm ir and assembly/square-aarch64.S
+test cases/common/118 llvm ir and assembly/square-arm.S
+test cases/common/118 llvm ir and assembly/square-x86.S
+test cases/common/118 llvm ir and assembly/square-x86_64.S
+test cases/common/118 llvm ir and assembly/square.ll
+test cases/common/118 llvm ir and assembly/symbol-underscore.h
+test cases/common/119 cpp and asm/meson.build
+test cases/common/119 cpp and asm/retval-arm.S
+test cases/common/119 cpp and asm/retval-x86.S
+test cases/common/119 cpp and asm/retval-x86_64.S
+test cases/common/119 cpp and asm/symbol-underscore.h
+test cases/common/119 cpp and asm/trivial.cc
 test cases/common/12 data/datafile.dat
 test cases/common/12 data/etcfile.dat
 test cases/common/12 data/fileobject_datafile.dat
-test cases/common/12 data/installed_files.txt
 test cases/common/12 data/meson.build
 test cases/common/12 data/runscript.sh
 test cases/common/12 data/somefile.txt
+test cases/common/12 data/test.json
 test cases/common/12 data/to_be_renamed_1.txt
 test cases/common/12 data/to_be_renamed_3.txt
 test cases/common/12 data/to_be_renamed_4.txt
@@ -423,59 +587,62 @@
 test cases/common/12 data/vanishing/to_be_renamed_2.txt
 test cases/common/12 data/vanishing/vanishing.dat
 test cases/common/12 data/vanishing/vanishing2.dat
-test cases/common/120 test skip/meson.build
-test cases/common/120 test skip/test_skip.c
-test cases/common/121 shared module/installed_files.txt
-test cases/common/121 shared module/meson.build
-test cases/common/121 shared module/module.c
-test cases/common/121 shared module/nosyms.c
-test cases/common/121 shared module/prog.c
-test cases/common/121 shared module/runtime.c
-test cases/common/122 llvm ir and assembly/main.c
-test cases/common/122 llvm ir and assembly/main.cpp
-test cases/common/122 llvm ir and assembly/meson.build
-test cases/common/122 llvm ir and assembly/square-arm.S
-test cases/common/122 llvm ir and assembly/square-x86.S
-test cases/common/122 llvm ir and assembly/square-x86_64.S
-test cases/common/122 llvm ir and assembly/square.ll
-test cases/common/122 llvm ir and assembly/symbol-underscore.h
-test cases/common/123 cpp and asm/meson.build
-test cases/common/123 cpp and asm/retval-arm.S
-test cases/common/123 cpp and asm/retval-x86.S
-test cases/common/123 cpp and asm/retval-x86_64.S
-test cases/common/123 cpp and asm/symbol-underscore.h
-test cases/common/123 cpp and asm/trivial.cc
-test cases/common/124 extract all shared library/extractor.h
-test cases/common/124 extract all shared library/four.c
-test cases/common/124 extract all shared library/func1234.def
-test cases/common/124 extract all shared library/meson.build
-test cases/common/124 extract all shared library/one.c
-test cases/common/124 extract all shared library/prog.c
-test cases/common/124 extract all shared library/three.c
-test cases/common/124 extract all shared library/two.c
-test cases/common/125 object only target/installed_files.txt
-test cases/common/125 object only target/meson.build
-test cases/common/125 object only target/obj_generator.py
-test cases/common/125 object only target/prog.c
-test cases/common/125 object only target/source.c
-test cases/common/125 object only target/source2.c
-test cases/common/125 object only target/source2.def
-test cases/common/125 object only target/source3.c
-test cases/common/126 no buildincdir/meson.build
-test cases/common/126 no buildincdir/prog.c
-test cases/common/126 no buildincdir/include/header.h
-test cases/common/127 custom target directory install/docgen.py
-test cases/common/127 custom target directory install/installed_files.txt
-test cases/common/127 custom target directory install/meson.build
-test cases/common/128 dependency file generation/main .c
-test cases/common/128 dependency file generation/meson.build
-test cases/common/129 configure file in generator/meson.build
-test cases/common/129 configure file in generator/inc/confdata.in
-test cases/common/129 configure file in generator/inc/meson.build
-test cases/common/129 configure file in generator/src/gen.py
-test cases/common/129 configure file in generator/src/main.c
-test cases/common/129 configure file in generator/src/meson.build
-test cases/common/129 configure file in generator/src/source
+test cases/common/120 extract all shared library/extractor.h
+test cases/common/120 extract all shared library/four.c
+test cases/common/120 extract all shared library/func1234.def
+test cases/common/120 extract all shared library/meson.build
+test cases/common/120 extract all shared library/one.c
+test cases/common/120 extract all shared library/prog.c
+test cases/common/120 extract all shared library/three.c
+test cases/common/120 extract all shared library/two.c
+test cases/common/121 object only target/meson.build
+test cases/common/121 object only target/obj_generator.py
+test cases/common/121 object only target/prog.c
+test cases/common/121 object only target/source.c
+test cases/common/121 object only target/source2.c
+test cases/common/121 object only target/source2.def
+test cases/common/121 object only target/source3.c
+test cases/common/121 object only target/test.json
+test cases/common/121 object only target/objdir/meson.build
+test cases/common/121 object only target/objdir/source4.c
+test cases/common/121 object only target/objdir/source5.c
+test cases/common/121 object only target/objdir/source6.c
+test cases/common/122 no buildincdir/meson.build
+test cases/common/122 no buildincdir/prog.c
+test cases/common/122 no buildincdir/include/header.h
+test cases/common/123 custom target directory install/docgen.py
+test cases/common/123 custom target directory install/meson.build
+test cases/common/123 custom target directory install/test.json
+test cases/common/124 dependency file generation/main .c
+test cases/common/124 dependency file generation/meson.build
+test cases/common/125 configure file in generator/meson.build
+test cases/common/125 configure file in generator/inc/confdata.in
+test cases/common/125 configure file in generator/inc/meson.build
+test cases/common/125 configure file in generator/src/gen.py
+test cases/common/125 configure file in generator/src/main.c
+test cases/common/125 configure file in generator/src/meson.build
+test cases/common/125 configure file in generator/src/source
+test cases/common/126 generated llvm ir/copyfile.py
+test cases/common/126 generated llvm ir/main.c
+test cases/common/126 generated llvm ir/meson.build
+test cases/common/126 generated llvm ir/square.ll.in
+test cases/common/127 generated assembly/copyfile.py
+test cases/common/127 generated assembly/empty.c
+test cases/common/127 generated assembly/main.c
+test cases/common/127 generated assembly/meson.build
+test cases/common/127 generated assembly/square-arm.S.in
+test cases/common/127 generated assembly/square-x86.S.in
+test cases/common/127 generated assembly/square-x86_64.S.in
+test cases/common/127 generated assembly/square.def
+test cases/common/127 generated assembly/symbol-underscore.h
+test cases/common/128 build by default targets in tests/main.c
+test cases/common/128 build by default targets in tests/meson.build
+test cases/common/128 build by default targets in tests/write_file.py
+test cases/common/129 build by default/checkexists.py
+test cases/common/129 build by default/foo.c
+test cases/common/129 build by default/meson.build
+test cases/common/129 build by default/mygen.py
+test cases/common/129 build by default/source.txt
 test cases/common/13 pch/meson.build
 test cases/common/13 pch/c/meson.build
 test cases/common/13 pch/c/prog.c
@@ -502,70 +669,84 @@
 test cases/common/13 pch/withIncludeDirectories/prog.c
 test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h
 test cases/common/13 pch/withIncludeDirectories/pch/prog.h
-test cases/common/130 generated llvm ir/copyfile.py
-test cases/common/130 generated llvm ir/main.c
-test cases/common/130 generated llvm ir/meson.build
-test cases/common/130 generated llvm ir/square.ll.in
-test cases/common/131 generated assembly/copyfile.py
-test cases/common/131 generated assembly/main.c
-test cases/common/131 generated assembly/meson.build
-test cases/common/131 generated assembly/square-arm.S.in
-test cases/common/131 generated assembly/square-x86.S.in
-test cases/common/131 generated assembly/square-x86_64.S.in
-test cases/common/131 generated assembly/symbol-underscore.h
-test cases/common/132 build by default targets in tests/main.c
-test cases/common/132 build by default targets in tests/meson.build
-test cases/common/132 build by default targets in tests/write_file.py
-test cases/common/133 build by default/checkexists.py
-test cases/common/133 build by default/foo.c
-test cases/common/133 build by default/meson.build
-test cases/common/133 build by default/mygen.py
-test cases/common/133 build by default/source.txt
-test cases/common/134 include order/meson.build
-test cases/common/134 include order/ordertest.c
-test cases/common/134 include order/ctsub/copyfile.py
-test cases/common/134 include order/ctsub/emptyfile.c
-test cases/common/134 include order/ctsub/main.h
-test cases/common/134 include order/ctsub/meson.build
-test cases/common/134 include order/inc1/hdr.h
-test cases/common/134 include order/inc2/hdr.h
-test cases/common/134 include order/sub1/main.h
-test cases/common/134 include order/sub1/meson.build
-test cases/common/134 include order/sub1/some.c
-test cases/common/134 include order/sub1/some.h
-test cases/common/134 include order/sub2/main.h
-test cases/common/134 include order/sub2/meson.build
-test cases/common/134 include order/sub3/main.h
-test cases/common/134 include order/sub3/meson.build
-test cases/common/134 include order/sub4/main.c
-test cases/common/134 include order/sub4/main.h
-test cases/common/134 include order/sub4/meson.build
-test cases/common/135 override options/four.c
-test cases/common/135 override options/meson.build
-test cases/common/135 override options/one.c
-test cases/common/135 override options/three.c
-test cases/common/135 override options/two.c
-test cases/common/136 get define/concat.h
-test cases/common/136 get define/meson.build
-test cases/common/136 get define/meson_options.txt
-test cases/common/137 c cpp and asm/main.c
-test cases/common/137 c cpp and asm/main.cpp
-test cases/common/137 c cpp and asm/meson.build
-test cases/common/137 c cpp and asm/retval-arm.S
-test cases/common/137 c cpp and asm/retval-x86.S
-test cases/common/137 c cpp and asm/retval-x86_64.S
-test cases/common/137 c cpp and asm/somelib.c
-test cases/common/137 c cpp and asm/symbol-underscore.h
-test cases/common/138 compute int/config.h.in
-test cases/common/138 compute int/foobar.h
-test cases/common/138 compute int/meson.build
-test cases/common/138 compute int/prog.c.in
-test cases/common/139 custom target object output/meson.build
-test cases/common/139 custom target object output/obj_generator.py
-test cases/common/139 custom target object output/objdir/meson.build
-test cases/common/139 custom target object output/objdir/source.c
-test cases/common/139 custom target object output/progdir/meson.build
-test cases/common/139 custom target object output/progdir/prog.c
+test cases/common/13 pch/withIncludeFile/meson.build
+test cases/common/13 pch/withIncludeFile/prog.c
+test cases/common/13 pch/withIncludeFile/pch/prog.h
+test cases/common/130 include order/meson.build
+test cases/common/130 include order/ordertest.c
+test cases/common/130 include order/ctsub/copyfile.py
+test cases/common/130 include order/ctsub/emptyfile.c
+test cases/common/130 include order/ctsub/main.h
+test cases/common/130 include order/ctsub/meson.build
+test cases/common/130 include order/inc1/hdr.h
+test cases/common/130 include order/inc2/hdr.h
+test cases/common/130 include order/sub1/main.h
+test cases/common/130 include order/sub1/meson.build
+test cases/common/130 include order/sub1/some.c
+test cases/common/130 include order/sub1/some.h
+test cases/common/130 include order/sub2/main.h
+test cases/common/130 include order/sub2/meson.build
+test cases/common/130 include order/sub3/main.h
+test cases/common/130 include order/sub3/meson.build
+test cases/common/130 include order/sub4/main.c
+test cases/common/130 include order/sub4/main.h
+test cases/common/130 include order/sub4/meson.build
+test cases/common/131 override options/four.c
+test cases/common/131 override options/meson.build
+test cases/common/131 override options/one.c
+test cases/common/131 override options/three.c
+test cases/common/131 override options/two.c
+test cases/common/132 get define/concat.h
+test cases/common/132 get define/meson.build
+test cases/common/132 get define/meson_options.txt
+test cases/common/133 c cpp and asm/main.c
+test cases/common/133 c cpp and asm/main.cpp
+test cases/common/133 c cpp and asm/meson.build
+test cases/common/133 c cpp and asm/retval-arm.S
+test cases/common/133 c cpp and asm/retval-x86.S
+test cases/common/133 c cpp and asm/retval-x86_64.S
+test cases/common/133 c cpp and asm/somelib.c
+test cases/common/133 c cpp and asm/symbol-underscore.h
+test cases/common/134 compute int/config.h.in
+test cases/common/134 compute int/foobar.h
+test cases/common/134 compute int/meson.build
+test cases/common/134 compute int/prog.c.in
+test cases/common/135 custom target object output/meson.build
+test cases/common/135 custom target object output/obj_generator.py
+test cases/common/135 custom target object output/objdir/meson.build
+test cases/common/135 custom target object output/objdir/source.c
+test cases/common/135 custom target object output/progdir/meson.build
+test cases/common/135 custom target object output/progdir/prog.c
+test cases/common/136 empty build file/meson.build
+test cases/common/136 empty build file/subdir/meson.build
+test cases/common/137 whole archive/func1.c
+test cases/common/137 whole archive/func2.c
+test cases/common/137 whole archive/meson.build
+test cases/common/137 whole archive/mylib.h
+test cases/common/137 whole archive/prog.c
+test cases/common/137 whole archive/exe/meson.build
+test cases/common/137 whole archive/exe2/meson.build
+test cases/common/137 whole archive/exe3/meson.build
+test cases/common/137 whole archive/exe4/meson.build
+test cases/common/137 whole archive/sh_func2_dep_func1/meson.build
+test cases/common/137 whole archive/sh_func2_linked_func1/meson.build
+test cases/common/137 whole archive/sh_func2_transdep_func1/meson.build
+test cases/common/137 whole archive/sh_only_link_whole/meson.build
+test cases/common/137 whole archive/st_func1/meson.build
+test cases/common/137 whole archive/st_func2/meson.build
+test cases/common/138 C and CPP link/dummy.c
+test cases/common/138 C and CPP link/foo.c
+test cases/common/138 C and CPP link/foo.cpp
+test cases/common/138 C and CPP link/foo.h
+test cases/common/138 C and CPP link/foo.hpp
+test cases/common/138 C and CPP link/foobar.c
+test cases/common/138 C and CPP link/foobar.h
+test cases/common/138 C and CPP link/meson.build
+test cases/common/138 C and CPP link/sub.c
+test cases/common/138 C and CPP link/sub.h
+test cases/common/139 mesonintrospect from scripts/check_env.py
+test cases/common/139 mesonintrospect from scripts/check_introspection.py
+test cases/common/139 mesonintrospect from scripts/meson.build
 test cases/common/14 configure file/basename.py
 test cases/common/14 configure file/check_file.py
 test cases/common/14 configure file/check_inputs.py
@@ -586,7 +767,6 @@
 test cases/common/14 configure file/generator-deps.py
 test cases/common/14 configure file/generator-without-input-file.py
 test cases/common/14 configure file/generator.py
-test cases/common/14 configure file/installed_files.txt
 test cases/common/14 configure file/invalid-utf8.bin.in
 test cases/common/14 configure file/meson.build
 test cases/common/14 configure file/nosubst-nocopy1.txt.in
@@ -600,878 +780,995 @@
 test cases/common/14 configure file/prog9.c
 test cases/common/14 configure file/sameafterbasename.in
 test cases/common/14 configure file/sameafterbasename.in2
+test cases/common/14 configure file/test.json
 test cases/common/14 configure file/test.py.in
 test cases/common/14 configure file/touch.py
 test cases/common/14 configure file/subdir/meson.build
-test cases/common/140 empty build file/meson.build
-test cases/common/140 empty build file/subdir/meson.build
-test cases/common/141 whole archive/func1.c
-test cases/common/141 whole archive/func2.c
-test cases/common/141 whole archive/meson.build
-test cases/common/141 whole archive/mylib.h
-test cases/common/141 whole archive/prog.c
-test cases/common/141 whole archive/exe/meson.build
-test cases/common/141 whole archive/exe2/meson.build
-test cases/common/141 whole archive/exe3/meson.build
-test cases/common/141 whole archive/exe4/meson.build
-test cases/common/141 whole archive/sh_func2_dep_func1/meson.build
-test cases/common/141 whole archive/sh_func2_linked_func1/meson.build
-test cases/common/141 whole archive/sh_func2_transdep_func1/meson.build
-test cases/common/141 whole archive/sh_only_link_whole/meson.build
-test cases/common/141 whole archive/st_func1/meson.build
-test cases/common/141 whole archive/st_func2/meson.build
-test cases/common/142 C and CPP link/dummy.c
-test cases/common/142 C and CPP link/foo.c
-test cases/common/142 C and CPP link/foo.cpp
-test cases/common/142 C and CPP link/foo.h
-test cases/common/142 C and CPP link/foo.hpp
-test cases/common/142 C and CPP link/foobar.c
-test cases/common/142 C and CPP link/foobar.h
-test cases/common/142 C and CPP link/meson.build
-test cases/common/142 C and CPP link/sub.c
-test cases/common/142 C and CPP link/sub.h
-test cases/common/143 mesonintrospect from scripts/check_env.py
-test cases/common/143 mesonintrospect from scripts/check_introspection.py
-test cases/common/143 mesonintrospect from scripts/meson.build
-test cases/common/144 custom target multiple outputs/generator.py
-test cases/common/144 custom target multiple outputs/installed_files.txt
-test cases/common/144 custom target multiple outputs/meson.build
-test cases/common/145 special characters/check_quoting.py
-test cases/common/145 special characters/installed_files.txt
-test cases/common/145 special characters/meson.build
-test cases/common/146 nested links/meson.build
-test cases/common/146 nested links/xephyr.c
-test cases/common/147 list of file sources/foo
-test cases/common/147 list of file sources/gen.py
-test cases/common/147 list of file sources/meson.build
-test cases/common/148 link depends custom target/foo.c
-test cases/common/148 link depends custom target/make_file.py
-test cases/common/148 link depends custom target/meson.build
-test cases/common/149 recursive linking/lib.h
-test cases/common/149 recursive linking/main.c
-test cases/common/149 recursive linking/meson.build
-test cases/common/149 recursive linking/3rdorderdeps/lib.c.in
-test cases/common/149 recursive linking/3rdorderdeps/main.c.in
-test cases/common/149 recursive linking/3rdorderdeps/meson.build
-test cases/common/149 recursive linking/circular/lib1.c
-test cases/common/149 recursive linking/circular/lib2.c
-test cases/common/149 recursive linking/circular/lib3.c
-test cases/common/149 recursive linking/circular/main.c
-test cases/common/149 recursive linking/circular/meson.build
-test cases/common/149 recursive linking/circular/prop1.c
-test cases/common/149 recursive linking/circular/prop2.c
-test cases/common/149 recursive linking/circular/prop3.c
-test cases/common/149 recursive linking/edge-cases/libsto.c
-test cases/common/149 recursive linking/edge-cases/meson.build
-test cases/common/149 recursive linking/edge-cases/shstmain.c
-test cases/common/149 recursive linking/edge-cases/stobuilt.c
-test cases/common/149 recursive linking/edge-cases/stomain.c
-test cases/common/149 recursive linking/shnodep/lib.c
-test cases/common/149 recursive linking/shnodep/meson.build
-test cases/common/149 recursive linking/shshdep/lib.c
-test cases/common/149 recursive linking/shshdep/meson.build
-test cases/common/149 recursive linking/shstdep/lib.c
-test cases/common/149 recursive linking/shstdep/meson.build
-test cases/common/149 recursive linking/stnodep/lib.c
-test cases/common/149 recursive linking/stnodep/meson.build
-test cases/common/149 recursive linking/stshdep/lib.c
-test cases/common/149 recursive linking/stshdep/meson.build
-test cases/common/149 recursive linking/ststdep/lib.c
-test cases/common/149 recursive linking/ststdep/meson.build
+test cases/common/140 custom target multiple outputs/generator.py
+test cases/common/140 custom target multiple outputs/meson.build
+test cases/common/140 custom target multiple outputs/test.json
+test cases/common/141 special characters/.editorconfig
+test cases/common/141 special characters/arg-char-test.c
+test cases/common/141 special characters/arg-string-test.c
+test cases/common/141 special characters/arg-unquoted-test.c
+test cases/common/141 special characters/check_quoting.py
+test cases/common/141 special characters/meson.build
+test cases/common/141 special characters/test.json
+test cases/common/142 nested links/meson.build
+test cases/common/142 nested links/xephyr.c
+test cases/common/143 list of file sources/foo
+test cases/common/143 list of file sources/gen.py
+test cases/common/143 list of file sources/meson.build
+test cases/common/144 link depends custom target/foo.c
+test cases/common/144 link depends custom target/make_file.py
+test cases/common/144 link depends custom target/meson.build
+test cases/common/145 recursive linking/lib.h
+test cases/common/145 recursive linking/main.c
+test cases/common/145 recursive linking/meson.build
+test cases/common/145 recursive linking/3rdorderdeps/lib.c.in
+test cases/common/145 recursive linking/3rdorderdeps/main.c.in
+test cases/common/145 recursive linking/3rdorderdeps/meson.build
+test cases/common/145 recursive linking/circular/lib1.c
+test cases/common/145 recursive linking/circular/lib2.c
+test cases/common/145 recursive linking/circular/lib3.c
+test cases/common/145 recursive linking/circular/main.c
+test cases/common/145 recursive linking/circular/meson.build
+test cases/common/145 recursive linking/circular/prop1.c
+test cases/common/145 recursive linking/circular/prop2.c
+test cases/common/145 recursive linking/circular/prop3.c
+test cases/common/145 recursive linking/edge-cases/libsto.c
+test cases/common/145 recursive linking/edge-cases/meson.build
+test cases/common/145 recursive linking/edge-cases/shstmain.c
+test cases/common/145 recursive linking/edge-cases/stobuilt.c
+test cases/common/145 recursive linking/edge-cases/stomain.c
+test cases/common/145 recursive linking/shnodep/lib.c
+test cases/common/145 recursive linking/shnodep/meson.build
+test cases/common/145 recursive linking/shshdep/lib.c
+test cases/common/145 recursive linking/shshdep/meson.build
+test cases/common/145 recursive linking/shstdep/lib.c
+test cases/common/145 recursive linking/shstdep/meson.build
+test cases/common/145 recursive linking/stnodep/lib.c
+test cases/common/145 recursive linking/stnodep/meson.build
+test cases/common/145 recursive linking/stshdep/lib.c
+test cases/common/145 recursive linking/stshdep/meson.build
+test cases/common/145 recursive linking/ststdep/lib.c
+test cases/common/145 recursive linking/ststdep/meson.build
+test cases/common/146 library at root/lib.c
+test cases/common/146 library at root/meson.build
+test cases/common/146 library at root/main/main.c
+test cases/common/146 library at root/main/meson.build
+test cases/common/147 simd/fallback.c
+test cases/common/147 simd/meson.build
+test cases/common/147 simd/simd_avx.c
+test cases/common/147 simd/simd_avx2.c
+test cases/common/147 simd/simd_mmx.c
+test cases/common/147 simd/simd_neon.c
+test cases/common/147 simd/simd_sse.c
+test cases/common/147 simd/simd_sse2.c
+test cases/common/147 simd/simd_sse3.c
+test cases/common/147 simd/simd_sse41.c
+test cases/common/147 simd/simd_sse42.c
+test cases/common/147 simd/simd_ssse3.c
+test cases/common/147 simd/simdchecker.c
+test cases/common/147 simd/simdfuncs.h
+test cases/common/147 simd/include/simdheader.h
+test cases/common/148 shared module resolving symbol in executable/meson.build
+test cases/common/148 shared module resolving symbol in executable/module.c
+test cases/common/148 shared module resolving symbol in executable/prog.c
+test cases/common/149 dotinclude/dotproc.c
+test cases/common/149 dotinclude/meson.build
+test cases/common/149 dotinclude/stdio.h
 test cases/common/15 if/meson.build
 test cases/common/15 if/prog.c
-test cases/common/150 library at root/lib.c
-test cases/common/150 library at root/meson.build
-test cases/common/150 library at root/main/main.c
-test cases/common/150 library at root/main/meson.build
-test cases/common/151 simd/fallback.c
-test cases/common/151 simd/meson.build
-test cases/common/151 simd/simd_avx.c
-test cases/common/151 simd/simd_avx2.c
-test cases/common/151 simd/simd_mmx.c
-test cases/common/151 simd/simd_neon.c
-test cases/common/151 simd/simd_sse.c
-test cases/common/151 simd/simd_sse2.c
-test cases/common/151 simd/simd_sse3.c
-test cases/common/151 simd/simd_sse41.c
-test cases/common/151 simd/simd_sse42.c
-test cases/common/151 simd/simd_ssse3.c
-test cases/common/151 simd/simdchecker.c
-test cases/common/151 simd/simdfuncs.h
-test cases/common/151 simd/include/simdheader.h
-test cases/common/152 shared module resolving symbol in executable/meson.build
-test cases/common/152 shared module resolving symbol in executable/module.c
-test cases/common/152 shared module resolving symbol in executable/prog.c
-test cases/common/153 dotinclude/dotproc.c
-test cases/common/153 dotinclude/meson.build
-test cases/common/153 dotinclude/stdio.h
-test cases/common/154 reserved targets/meson.build
-test cases/common/154 reserved targets/test.c
-test cases/common/154 reserved targets/all/meson.build
-test cases/common/154 reserved targets/benchmark/meson.build
-test cases/common/154 reserved targets/clean/meson.build
-test cases/common/154 reserved targets/clean-ctlist/meson.build
-test cases/common/154 reserved targets/clean-gcda/meson.build
-test cases/common/154 reserved targets/clean-gcno/meson.build
-test cases/common/154 reserved targets/coverage/meson.build
-test cases/common/154 reserved targets/coverage-html/meson.build
-test cases/common/154 reserved targets/coverage-text/meson.build
-test cases/common/154 reserved targets/coverage-xml/meson.build
-test cases/common/154 reserved targets/dist/meson.build
-test cases/common/154 reserved targets/distcheck/meson.build
-test cases/common/154 reserved targets/install/meson.build
-test cases/common/154 reserved targets/phony/meson.build
-test cases/common/154 reserved targets/reconfigure/meson.build
-test cases/common/154 reserved targets/runtarget/meson.build
-test cases/common/154 reserved targets/scan-build/meson.build
-test cases/common/154 reserved targets/test/meson.build
-test cases/common/154 reserved targets/uninstall/meson.build
-test cases/common/155 duplicate source names/meson.build
-test cases/common/155 duplicate source names/dir1/file.c
-test cases/common/155 duplicate source names/dir1/meson.build
-test cases/common/155 duplicate source names/dir2/file.c
-test cases/common/155 duplicate source names/dir2/meson.build
-test cases/common/155 duplicate source names/dir2/dir1/file.c
-test cases/common/155 duplicate source names/dir3/file.c
-test cases/common/155 duplicate source names/dir3/meson.build
-test cases/common/155 duplicate source names/dir3/dir1/file.c
-test cases/common/156 index customtarget/check_args.py
-test cases/common/156 index customtarget/gen_sources.py
-test cases/common/156 index customtarget/lib.c
-test cases/common/156 index customtarget/meson.build
-test cases/common/156 index customtarget/subdir/foo.c
-test cases/common/156 index customtarget/subdir/meson.build
-test cases/common/157 wrap file should not failed/meson.build
-test cases/common/157 wrap file should not failed/src/meson.build
-test cases/common/157 wrap file should not failed/src/subprojects/prog.c
-test cases/common/157 wrap file should not failed/src/subprojects/foo/prog2.c
-test cases/common/157 wrap file should not failed/subprojects/foo.wrap
-test cases/common/157 wrap file should not failed/subprojects/zlib.wrap
-test cases/common/157 wrap file should not failed/subprojects/foo-1.0/foo.c
-test cases/common/157 wrap file should not failed/subprojects/foo-1.0/meson.build
-test cases/common/157 wrap file should not failed/subprojects/packagecache/foo-1.0-patch.tar.xz
-test cases/common/157 wrap file should not failed/subprojects/packagecache/foo-1.0.tar.xz
-test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip
-test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz
-test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/foo.c
-test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/meson.build
-test cases/common/158 includedir subproj/meson.build
-test cases/common/158 includedir subproj/prog.c
-test cases/common/158 includedir subproj/subprojects/inctest/meson.build
-test cases/common/158 includedir subproj/subprojects/inctest/include/incfile.h
-test cases/common/159 subproject dir name collision/a.c
-test cases/common/159 subproject dir name collision/meson.build
-test cases/common/159 subproject dir name collision/custom_subproject_dir/B/b.c
-test cases/common/159 subproject dir name collision/custom_subproject_dir/B/meson.build
-test cases/common/159 subproject dir name collision/custom_subproject_dir/C/c.c
-test cases/common/159 subproject dir name collision/custom_subproject_dir/C/meson.build
-test cases/common/159 subproject dir name collision/other_subdir/meson.build
-test cases/common/159 subproject dir name collision/other_subdir/custom_subproject_dir/other.c
-test cases/common/16 else/meson.build
-test cases/common/16 else/prog.c
-test cases/common/160 config tool variable/meson.build
-test cases/common/161 custom target subdir depend files/copyfile.py
-test cases/common/161 custom target subdir depend files/meson.build
-test cases/common/161 custom target subdir depend files/subdir/dep.dat
-test cases/common/161 custom target subdir depend files/subdir/foo.c.in
-test cases/common/161 custom target subdir depend files/subdir/meson.build
-test cases/common/162 external program shebang parsing/input.txt
-test cases/common/162 external program shebang parsing/main.c
-test cases/common/162 external program shebang parsing/meson.build
-test cases/common/162 external program shebang parsing/script.int.in
-test cases/common/163 disabler/meson.build
-test cases/common/164 array option/meson.build
-test cases/common/164 array option/meson_options.txt
-test cases/common/165 custom target template substitution/checkcopy.py
-test cases/common/165 custom target template substitution/foo.c.in
-test cases/common/165 custom target template substitution/meson.build
-test cases/common/166 not-found dependency/meson.build
-test cases/common/166 not-found dependency/testlib.c
-test cases/common/166 not-found dependency/sub/meson.build
-test cases/common/166 not-found dependency/subprojects/trivial/meson.build
-test cases/common/166 not-found dependency/subprojects/trivial/trivial.c
-test cases/common/167 subdir if_found/meson.build
-test cases/common/167 subdir if_found/subdir/meson.build
-test cases/common/168 default options prefix dependent defaults/meson.build
-test cases/common/169 dependency factory/meson.build
-test cases/common/17 comparison/meson.build
-test cases/common/17 comparison/prog.c
-test cases/common/170 get project license/bar.c
-test cases/common/170 get project license/meson.build
-test cases/common/171 yield/meson.build
-test cases/common/171 yield/meson_options.txt
-test cases/common/171 yield/subprojects/sub/meson.build
-test cases/common/171 yield/subprojects/sub/meson_options.txt
-test cases/common/172 subproject nested subproject dirs/meson.build
-test cases/common/172 subproject nested subproject dirs/prog.c
-test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/a.c
-test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build
-test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here
-test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/b.c
-test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/meson.build
-test cases/common/173 preserve gendir/base.inp
-test cases/common/173 preserve gendir/genprog.py
-test cases/common/173 preserve gendir/meson.build
-test cases/common/173 preserve gendir/testprog.c
-test cases/common/173 preserve gendir/com/mesonbuild/subbie.inp
-test cases/common/174 source in dep/bar.cpp
-test cases/common/174 source in dep/foo.c
-test cases/common/174 source in dep/meson.build
-test cases/common/174 source in dep/generated/funname
-test cases/common/174 source in dep/generated/genheader.py
-test cases/common/174 source in dep/generated/main.c
-test cases/common/174 source in dep/generated/meson.build
-test cases/common/175 generator link whole/export.h
-test cases/common/175 generator link whole/generator.py
-test cases/common/175 generator link whole/main.c
-test cases/common/175 generator link whole/meson.build
-test cases/common/175 generator link whole/meson_test_function.tmpl
-test cases/common/175 generator link whole/pull_meson_test_function.c
-test cases/common/176 initial c_args/meson.build
-test cases/common/176 initial c_args/test_args.txt
-test cases/common/177 identical target name in subproject flat layout/foo.c
-test cases/common/177 identical target name in subproject flat layout/main.c
-test cases/common/177 identical target name in subproject flat layout/meson.build
-test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/foo.c
-test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/meson.build
-test cases/common/178 as-needed/config.h
-test cases/common/178 as-needed/libA.cpp
-test cases/common/178 as-needed/libA.h
-test cases/common/178 as-needed/libB.cpp
-test cases/common/178 as-needed/main.cpp
-test cases/common/178 as-needed/meson.build
-test cases/common/179 ndebug if-release enabled/main.c
-test cases/common/179 ndebug if-release enabled/meson.build
-test cases/common/18 array/func.c
-test cases/common/18 array/meson.build
-test cases/common/18 array/prog.c
-test cases/common/180 ndebug if-release disabled/main.c
-test cases/common/180 ndebug if-release disabled/meson.build
-test cases/common/181 subproject version/meson.build
-test cases/common/181 subproject version/subprojects/a/meson.build
-test cases/common/182 subdir_done/meson.build
-test cases/common/183 bothlibraries/libfile.c
-test cases/common/183 bothlibraries/main.c
-test cases/common/183 bothlibraries/meson.build
-test cases/common/183 bothlibraries/mylib.h
-test cases/common/184 escape and unicode/file.c.in
-test cases/common/184 escape and unicode/file.py
-test cases/common/184 escape and unicode/find.py
-test cases/common/184 escape and unicode/fun.c
-test cases/common/184 escape and unicode/main.c
-test cases/common/184 escape and unicode/meson.build
-test cases/common/185 has link arg/meson.build
-test cases/common/186 same target name flat layout/foo.c
-test cases/common/186 same target name flat layout/main.c
-test cases/common/186 same target name flat layout/meson.build
-test cases/common/186 same target name flat layout/subdir/foo.c
-test cases/common/186 same target name flat layout/subdir/meson.build
-test cases/common/187 find override/meson.build
-test cases/common/187 find override/otherdir/main.c
-test cases/common/187 find override/otherdir/main2.c
-test cases/common/187 find override/otherdir/meson.build
-test cases/common/187 find override/otherdir/source.desc
-test cases/common/187 find override/otherdir/source2.desc
-test cases/common/187 find override/subdir/converter.py
-test cases/common/187 find override/subdir/gencodegen.py.in
-test cases/common/187 find override/subdir/meson.build
-test cases/common/188 partial dependency/meson.build
-test cases/common/188 partial dependency/declare_dependency/main.c
-test cases/common/188 partial dependency/declare_dependency/meson.build
-test cases/common/188 partial dependency/declare_dependency/other.c
-test cases/common/188 partial dependency/declare_dependency/headers/foo.c
-test cases/common/188 partial dependency/declare_dependency/headers/foo.h
-test cases/common/189 openmp/main.c
-test cases/common/189 openmp/main.cpp
-test cases/common/189 openmp/main.f90
-test cases/common/189 openmp/meson.build
-test cases/common/19 includedir/meson.build
-test cases/common/19 includedir/include/func.h
-test cases/common/19 includedir/src/func.c
-test cases/common/19 includedir/src/meson.build
-test cases/common/19 includedir/src/prog.c
-test cases/common/190 same target name/file.c
-test cases/common/190 same target name/meson.build
-test cases/common/190 same target name/sub/file2.c
-test cases/common/190 same target name/sub/meson.build
-test cases/common/191 test depends/gen.py
-test cases/common/191 test depends/main.c
-test cases/common/191 test depends/meson.build
-test cases/common/191 test depends/test.py
-test cases/common/192 args flattening/meson.build
-test cases/common/193 dict/meson.build
-test cases/common/193 dict/prog.c
-test cases/common/194 check header/meson.build
-test cases/common/194 check header/ouagadougou.h
-test cases/common/195 install_mode/config.h.in
-test cases/common/195 install_mode/data_source.txt
-test cases/common/195 install_mode/foo.1
-test cases/common/195 install_mode/installed_files.txt
-test cases/common/195 install_mode/meson.build
-test cases/common/195 install_mode/rootdir.h
-test cases/common/195 install_mode/runscript.sh
-test cases/common/195 install_mode/stat.c
-test cases/common/195 install_mode/trivial.c
-test cases/common/195 install_mode/sub1/second.dat
-test cases/common/195 install_mode/sub2/stub
-test cases/common/196 subproject array version/meson.build
-test cases/common/196 subproject array version/subprojects/foo/meson.build
-test cases/common/197 feature option/meson.build
-test cases/common/197 feature option/meson_options.txt
-test cases/common/198 feature option disabled/meson.build
-test cases/common/198 feature option disabled/meson_options.txt
-test cases/common/199 static threads/lib1.c
-test cases/common/199 static threads/lib2.c
-test cases/common/199 static threads/meson.build
-test cases/common/199 static threads/prog.c
+test cases/common/150 reserved targets/meson.build
+test cases/common/150 reserved targets/test.c
+test cases/common/150 reserved targets/all/meson.build
+test cases/common/150 reserved targets/benchmark/meson.build
+test cases/common/150 reserved targets/clean/meson.build
+test cases/common/150 reserved targets/clean-ctlist/meson.build
+test cases/common/150 reserved targets/clean-gcda/meson.build
+test cases/common/150 reserved targets/clean-gcno/meson.build
+test cases/common/150 reserved targets/coverage/meson.build
+test cases/common/150 reserved targets/coverage-html/meson.build
+test cases/common/150 reserved targets/coverage-sonarqube/meson.build
+test cases/common/150 reserved targets/coverage-text/meson.build
+test cases/common/150 reserved targets/coverage-xml/meson.build
+test cases/common/150 reserved targets/dist/meson.build
+test cases/common/150 reserved targets/distcheck/meson.build
+test cases/common/150 reserved targets/install/meson.build
+test cases/common/150 reserved targets/phony/meson.build
+test cases/common/150 reserved targets/reconfigure/meson.build
+test cases/common/150 reserved targets/runtarget/echo.py
+test cases/common/150 reserved targets/runtarget/meson.build
+test cases/common/150 reserved targets/scan-build/meson.build
+test cases/common/150 reserved targets/test/meson.build
+test cases/common/150 reserved targets/uninstall/meson.build
+test cases/common/151 duplicate source names/meson.build
+test cases/common/151 duplicate source names/dir1/file.c
+test cases/common/151 duplicate source names/dir1/meson.build
+test cases/common/151 duplicate source names/dir2/file.c
+test cases/common/151 duplicate source names/dir2/meson.build
+test cases/common/151 duplicate source names/dir2/dir1/file.c
+test cases/common/151 duplicate source names/dir3/file.c
+test cases/common/151 duplicate source names/dir3/meson.build
+test cases/common/151 duplicate source names/dir3/dir1/file.c
+test cases/common/152 index customtarget/check_args.py
+test cases/common/152 index customtarget/gen_sources.py
+test cases/common/152 index customtarget/lib.c
+test cases/common/152 index customtarget/meson.build
+test cases/common/152 index customtarget/subdir/foo.c
+test cases/common/152 index customtarget/subdir/meson.build
+test cases/common/153 wrap file should not failed/meson.build
+test cases/common/153 wrap file should not failed/src/meson.build
+test cases/common/153 wrap file should not failed/src/test.c
+test cases/common/153 wrap file should not failed/src/subprojects/prog.c
+test cases/common/153 wrap file should not failed/src/subprojects/foo/prog2.c
+test cases/common/153 wrap file should not failed/subprojects/.gitignore
+test cases/common/153 wrap file should not failed/subprojects/bar.wrap
+test cases/common/153 wrap file should not failed/subprojects/foo.wrap
+test cases/common/153 wrap file should not failed/subprojects/patchdir.wrap
+test cases/common/153 wrap file should not failed/subprojects/zlib.wrap
+test cases/common/153 wrap file should not failed/subprojects/bar-1.0/bar.c
+test cases/common/153 wrap file should not failed/subprojects/bar-1.0/meson.build
+test cases/common/153 wrap file should not failed/subprojects/foo-1.0/foo.c
+test cases/common/153 wrap file should not failed/subprojects/foo-1.0/meson.build
+test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/foo.c
+test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/meson.build
+test cases/common/153 wrap file should not failed/subprojects/packagecache/foo-1.0-patch.tar.xz
+test cases/common/153 wrap file should not failed/subprojects/packagecache/foo-1.0.tar.xz
+test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip
+test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz
+test cases/common/153 wrap file should not failed/subprojects/packagefiles/bar-1.0-patch.tar.xz
+test cases/common/153 wrap file should not failed/subprojects/packagefiles/bar-1.0.tar.xz
+test cases/common/153 wrap file should not failed/subprojects/packagefiles/foo-1.0/meson.build
+test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/foo.c
+test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/meson.build
+test cases/common/154 includedir subproj/meson.build
+test cases/common/154 includedir subproj/prog.c
+test cases/common/154 includedir subproj/subprojects/inctest/meson.build
+test cases/common/154 includedir subproj/subprojects/inctest/include/incfile.h
+test cases/common/155 subproject dir name collision/a.c
+test cases/common/155 subproject dir name collision/meson.build
+test cases/common/155 subproject dir name collision/custom_subproject_dir/B/b.c
+test cases/common/155 subproject dir name collision/custom_subproject_dir/B/meson.build
+test cases/common/155 subproject dir name collision/custom_subproject_dir/C/c.c
+test cases/common/155 subproject dir name collision/custom_subproject_dir/C/meson.build
+test cases/common/155 subproject dir name collision/other_subdir/meson.build
+test cases/common/155 subproject dir name collision/other_subdir/custom_subproject_dir/other.c
+test cases/common/156 config tool variable/meson.build
+test cases/common/157 custom target subdir depend files/copyfile.py
+test cases/common/157 custom target subdir depend files/meson.build
+test cases/common/157 custom target subdir depend files/subdir/dep.dat
+test cases/common/157 custom target subdir depend files/subdir/foo.c.in
+test cases/common/157 custom target subdir depend files/subdir/meson.build
+test cases/common/158 disabler/meson.build
+test cases/common/159 array option/meson.build
+test cases/common/159 array option/meson_options.txt
+test cases/common/16 comparison/meson.build
+test cases/common/16 comparison/prog.c
+test cases/common/160 custom target template substitution/checkcopy.py
+test cases/common/160 custom target template substitution/foo.c.in
+test cases/common/160 custom target template substitution/meson.build
+test cases/common/161 not-found dependency/meson.build
+test cases/common/161 not-found dependency/testlib.c
+test cases/common/161 not-found dependency/sub/meson.build
+test cases/common/161 not-found dependency/subprojects/trivial/meson.build
+test cases/common/161 not-found dependency/subprojects/trivial/trivial.c
+test cases/common/162 subdir if_found/meson.build
+test cases/common/162 subdir if_found/subdir/meson.build
+test cases/common/163 default options prefix dependent defaults/meson.build
+test cases/common/164 dependency factory/meson.build
+test cases/common/165 get project license/bar.c
+test cases/common/165 get project license/meson.build
+test cases/common/166 yield/meson.build
+test cases/common/166 yield/meson_options.txt
+test cases/common/166 yield/subprojects/sub/meson.build
+test cases/common/166 yield/subprojects/sub/meson_options.txt
+test cases/common/167 subproject nested subproject dirs/meson.build
+test cases/common/167 subproject nested subproject dirs/prog.c
+test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/a.c
+test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build
+test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here
+test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/b.c
+test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/meson.build
+test cases/common/168 preserve gendir/base.inp
+test cases/common/168 preserve gendir/genprog.py
+test cases/common/168 preserve gendir/meson.build
+test cases/common/168 preserve gendir/testprog.c
+test cases/common/168 preserve gendir/com/mesonbuild/subbie.inp
+test cases/common/169 source in dep/bar.cpp
+test cases/common/169 source in dep/foo.c
+test cases/common/169 source in dep/meson.build
+test cases/common/169 source in dep/generated/funname
+test cases/common/169 source in dep/generated/genheader.py
+test cases/common/169 source in dep/generated/main.c
+test cases/common/169 source in dep/generated/meson.build
+test cases/common/17 array/func.c
+test cases/common/17 array/meson.build
+test cases/common/17 array/prog.c
+test cases/common/170 generator link whole/export.h
+test cases/common/170 generator link whole/generator.py
+test cases/common/170 generator link whole/main.c
+test cases/common/170 generator link whole/meson.build
+test cases/common/170 generator link whole/meson_test_function.tmpl
+test cases/common/170 generator link whole/pull_meson_test_function.c
+test cases/common/171 initial c_args/meson.build
+test cases/common/171 initial c_args/test.json
+test cases/common/172 identical target name in subproject flat layout/foo.c
+test cases/common/172 identical target name in subproject flat layout/main.c
+test cases/common/172 identical target name in subproject flat layout/meson.build
+test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/foo.c
+test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/meson.build
+test cases/common/173 as-needed/config.h
+test cases/common/173 as-needed/libA.cpp
+test cases/common/173 as-needed/libA.h
+test cases/common/173 as-needed/libB.cpp
+test cases/common/173 as-needed/main.cpp
+test cases/common/173 as-needed/meson.build
+test cases/common/174 ndebug if-release enabled/main.c
+test cases/common/174 ndebug if-release enabled/meson.build
+test cases/common/175 ndebug if-release disabled/main.c
+test cases/common/175 ndebug if-release disabled/meson.build
+test cases/common/176 subproject version/meson.build
+test cases/common/176 subproject version/subprojects/a/meson.build
+test cases/common/177 subdir_done/meson.build
+test cases/common/178 bothlibraries/dummy.py
+test cases/common/178 bothlibraries/libfile.c
+test cases/common/178 bothlibraries/main.c
+test cases/common/178 bothlibraries/meson.build
+test cases/common/178 bothlibraries/mylib.h
+test cases/common/179 escape and unicode/file.c.in
+test cases/common/179 escape and unicode/file.py
+test cases/common/179 escape and unicode/find.py
+test cases/common/179 escape and unicode/fun.c
+test cases/common/179 escape and unicode/main.c
+test cases/common/179 escape and unicode/meson.build
+test cases/common/18 includedir/meson.build
+test cases/common/18 includedir/include/func.h
+test cases/common/18 includedir/src/func.c
+test cases/common/18 includedir/src/meson.build
+test cases/common/18 includedir/src/prog.c
+test cases/common/180 has link arg/meson.build
+test cases/common/181 same target name flat layout/foo.c
+test cases/common/181 same target name flat layout/main.c
+test cases/common/181 same target name flat layout/meson.build
+test cases/common/181 same target name flat layout/subdir/foo.c
+test cases/common/181 same target name flat layout/subdir/meson.build
+test cases/common/182 find override/meson.build
+test cases/common/182 find override/otherdir/main.c
+test cases/common/182 find override/otherdir/main2.c
+test cases/common/182 find override/otherdir/meson.build
+test cases/common/182 find override/otherdir/source.desc
+test cases/common/182 find override/otherdir/source2.desc
+test cases/common/182 find override/subdir/converter.py
+test cases/common/182 find override/subdir/gencodegen.py.in
+test cases/common/182 find override/subdir/meson.build
+test cases/common/182 find override/subprojects/sub.wrap
+test cases/common/182 find override/subprojects/sub/meson.build
+test cases/common/183 partial dependency/meson.build
+test cases/common/183 partial dependency/declare_dependency/main.c
+test cases/common/183 partial dependency/declare_dependency/meson.build
+test cases/common/183 partial dependency/declare_dependency/other.c
+test cases/common/183 partial dependency/declare_dependency/headers/foo.c
+test cases/common/183 partial dependency/declare_dependency/headers/foo.h
+test cases/common/184 openmp/main.c
+test cases/common/184 openmp/main.cpp
+test cases/common/184 openmp/main.f90
+test cases/common/184 openmp/meson.build
+test cases/common/185 same target name/file.c
+test cases/common/185 same target name/meson.build
+test cases/common/185 same target name/sub/file2.c
+test cases/common/185 same target name/sub/meson.build
+test cases/common/186 test depends/gen.py
+test cases/common/186 test depends/main.c
+test cases/common/186 test depends/meson.build
+test cases/common/186 test depends/test.py
+test cases/common/187 args flattening/meson.build
+test cases/common/188 dict/meson.build
+test cases/common/188 dict/prog.c
+test cases/common/189 check header/meson.build
+test cases/common/189 check header/ouagadougou.h
+test cases/common/19 header in file list/header.h
+test cases/common/19 header in file list/meson.build
+test cases/common/19 header in file list/prog.c
+test cases/common/190 install_mode/config.h.in
+test cases/common/190 install_mode/data_source.txt
+test cases/common/190 install_mode/foo.1
+test cases/common/190 install_mode/meson.build
+test cases/common/190 install_mode/rootdir.h
+test cases/common/190 install_mode/runscript.sh
+test cases/common/190 install_mode/stat.c
+test cases/common/190 install_mode/test.json
+test cases/common/190 install_mode/trivial.c
+test cases/common/190 install_mode/sub1/second.dat
+test cases/common/190 install_mode/sub2/stub
+test cases/common/191 subproject array version/meson.build
+test cases/common/191 subproject array version/subprojects/foo/meson.build
+test cases/common/192 feature option/meson.build
+test cases/common/192 feature option/meson_options.txt
+test cases/common/193 feature option disabled/meson.build
+test cases/common/193 feature option disabled/meson_options.txt
+test cases/common/194 static threads/lib1.c
+test cases/common/194 static threads/lib2.c
+test cases/common/194 static threads/meson.build
+test cases/common/194 static threads/prog.c
+test cases/common/195 generator in subdir/meson.build
+test cases/common/195 generator in subdir/com/mesonbuild/genprog.py
+test cases/common/195 generator in subdir/com/mesonbuild/meson.build
+test cases/common/195 generator in subdir/com/mesonbuild/subbie.inp
+test cases/common/195 generator in subdir/com/mesonbuild/testprog.c
+test cases/common/196 subproject with features/meson.build
+test cases/common/196 subproject with features/meson_options.txt
+test cases/common/196 subproject with features/nothing.c
+test cases/common/196 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build
+test cases/common/196 subproject with features/subprojects/disabled_sub/meson.build
+test cases/common/196 subproject with features/subprojects/disabled_sub/lib/meson.build
+test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.c
+test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.h
+test cases/common/196 subproject with features/subprojects/sub/meson.build
+test cases/common/196 subproject with features/subprojects/sub/lib/meson.build
+test cases/common/196 subproject with features/subprojects/sub/lib/sub.c
+test cases/common/196 subproject with features/subprojects/sub/lib/sub.h
+test cases/common/197 function attributes/meson.build
+test cases/common/197 function attributes/meson_options.txt
+test cases/common/197 function attributes/test.json
+test cases/common/198 broken subproject/meson.build
+test cases/common/198 broken subproject/subprojects/broken/broken.c
+test cases/common/198 broken subproject/subprojects/broken/meson.build
+test cases/common/199 argument syntax/meson.build
+test cases/common/2 cpp/VERSIONFILE
+test cases/common/2 cpp/cpp.C
 test cases/common/2 cpp/meson.build
 test cases/common/2 cpp/something.txt
 test cases/common/2 cpp/trivial.cc
-test cases/common/20 header in file list/header.h
-test cases/common/20 header in file list/meson.build
-test cases/common/20 header in file list/prog.c
-test cases/common/200 generator in subdir/meson.build
-test cases/common/200 generator in subdir/com/mesonbuild/genprog.py
-test cases/common/200 generator in subdir/com/mesonbuild/meson.build
-test cases/common/200 generator in subdir/com/mesonbuild/subbie.inp
-test cases/common/200 generator in subdir/com/mesonbuild/testprog.c
-test cases/common/201 override with exe/main2.input
-test cases/common/201 override with exe/meson.build
-test cases/common/201 override with exe/subprojects/sub/foobar.c
-test cases/common/201 override with exe/subprojects/sub/meson.build
-test cases/common/202 subproject with features/meson.build
-test cases/common/202 subproject with features/meson_options.txt
-test cases/common/202 subproject with features/nothing.c
-test cases/common/202 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build
-test cases/common/202 subproject with features/subprojects/disabled_sub/meson.build
-test cases/common/202 subproject with features/subprojects/disabled_sub/lib/meson.build
-test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.c
-test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.h
-test cases/common/202 subproject with features/subprojects/sub/meson.build
-test cases/common/202 subproject with features/subprojects/sub/lib/meson.build
-test cases/common/202 subproject with features/subprojects/sub/lib/sub.c
-test cases/common/202 subproject with features/subprojects/sub/lib/sub.h
-test cases/common/203 function attributes/meson.build
-test cases/common/204 broken subproject/meson.build
-test cases/common/204 broken subproject/subprojects/broken/broken.c
-test cases/common/204 broken subproject/subprojects/broken/meson.build
-test cases/common/205 argument syntax/meson.build
-test cases/common/206 install name_prefix name_suffix/installed_files.txt
-test cases/common/206 install name_prefix name_suffix/libfile.c
-test cases/common/206 install name_prefix name_suffix/meson.build
-test cases/common/207 kwarg entry/installed_files.txt
-test cases/common/207 kwarg entry/meson.build
-test cases/common/207 kwarg entry/prog.c
-test cases/common/207 kwarg entry/inc/prog.h
-test cases/common/208 custom target build by default/docgen.py
-test cases/common/208 custom target build by default/installed_files.txt
-test cases/common/208 custom target build by default/meson.build
-test cases/common/209 find_library and headers/foo.h
-test cases/common/209 find_library and headers/meson.build
-test cases/common/21 global arg/meson.build
-test cases/common/21 global arg/prog.c
-test cases/common/21 global arg/prog.cc
-test cases/common/210 line continuation/meson.build
-test cases/common/211 cmake module/installed_files.txt
-test cases/common/211 cmake module/meson.build
-test cases/common/211 cmake module/projectConfig.cmake.in
-test cases/common/211 cmake module/cmake_project/CMakeLists.txt
-test cases/common/212 native file path override/installed_files.txt
-test cases/common/212 native file path override/main.cpp
-test cases/common/212 native file path override/meson.build
-test cases/common/212 native file path override/nativefile.ini
-test cases/common/213 tap tests/meson.build
-test cases/common/213 tap tests/tester.c
-test cases/common/214 warning level 0/main.cpp
-test cases/common/214 warning level 0/meson.build
-test cases/common/215 link custom/custom_stlib.py
-test cases/common/215 link custom/lib.c
-test cases/common/215 link custom/meson.build
-test cases/common/215 link custom/prog.c
-test cases/common/216 link custom_i single from multiple/generate_conflicting_stlibs.py
-test cases/common/216 link custom_i single from multiple/meson.build
-test cases/common/216 link custom_i single from multiple/prog.c
-test cases/common/217 link custom_i multiple from multiple/generate_stlibs.py
-test cases/common/217 link custom_i multiple from multiple/meson.build
-test cases/common/217 link custom_i multiple from multiple/prog.c
-test cases/common/218 dependency get_variable method/meson.build
-test cases/common/219 source set configuration_data/a.c
-test cases/common/219 source set configuration_data/all.h
-test cases/common/219 source set configuration_data/f.c
-test cases/common/219 source set configuration_data/g.c
-test cases/common/219 source set configuration_data/meson.build
-test cases/common/219 source set configuration_data/nope.c
-test cases/common/219 source set configuration_data/subdir/b.c
-test cases/common/219 source set configuration_data/subdir/meson.build
-test cases/common/22 target arg/func.c
-test cases/common/22 target arg/func2.c
-test cases/common/22 target arg/meson.build
-test cases/common/22 target arg/prog.cc
-test cases/common/22 target arg/prog2.cc
-test cases/common/220 source set dictionary/a.c
-test cases/common/220 source set dictionary/all.h
-test cases/common/220 source set dictionary/f.c
-test cases/common/220 source set dictionary/g.c
-test cases/common/220 source set dictionary/meson.build
-test cases/common/220 source set dictionary/nope.c
-test cases/common/220 source set dictionary/subdir/b.c
-test cases/common/220 source set dictionary/subdir/meson.build
-test cases/common/221 source set custom target/a.c
-test cases/common/221 source set custom target/all.h
-test cases/common/221 source set custom target/cp.py
-test cases/common/221 source set custom target/f.c
-test cases/common/221 source set custom target/g.c
-test cases/common/221 source set custom target/meson.build
-test cases/common/222 source set realistic example/common.h
-test cases/common/222 source set realistic example/main.cc
-test cases/common/222 source set realistic example/meson.build
-test cases/common/222 source set realistic example/not-found.cc
-test cases/common/222 source set realistic example/was-found.cc
-test cases/common/222 source set realistic example/zlib.cc
-test cases/common/222 source set realistic example/boards/meson.build
-test cases/common/222 source set realistic example/boards/arm/aarch64.cc
-test cases/common/222 source set realistic example/boards/arm/arm.cc
-test cases/common/222 source set realistic example/boards/arm/arm.h
-test cases/common/222 source set realistic example/boards/arm/arm32.cc
-test cases/common/222 source set realistic example/boards/arm/versatilepb.cc
-test cases/common/222 source set realistic example/boards/arm/virt.cc
-test cases/common/222 source set realistic example/boards/arm/xlnx_zcu102.cc
-test cases/common/222 source set realistic example/boards/x86/pc.cc
-test cases/common/222 source set realistic example/config/aarch64
-test cases/common/222 source set realistic example/config/arm
-test cases/common/222 source set realistic example/config/x86
-test cases/common/222 source set realistic example/devices/meson.build
-test cases/common/222 source set realistic example/devices/virtio-mmio.cc
-test cases/common/222 source set realistic example/devices/virtio-pci.cc
-test cases/common/222 source set realistic example/devices/virtio.cc
-test cases/common/222 source set realistic example/devices/virtio.h
-test cases/common/223 custom target input extracted objects/check_object.py
-test cases/common/223 custom target input extracted objects/meson.build
-test cases/common/223 custom target input extracted objects/libdir/meson.build
-test cases/common/223 custom target input extracted objects/libdir/source.c
-test cases/common/224 test priorities/meson.build
-test cases/common/224 test priorities/testprog.py
-test cases/common/225 include_dir dot/meson.build
-test cases/common/225 include_dir dot/rone.h
-test cases/common/225 include_dir dot/src/main.c
-test cases/common/225 include_dir dot/src/meson.build
-test cases/common/225 include_dir dot/src/rone.c
-test cases/common/226 include_type dependency/meson.build
-test cases/common/226 include_type dependency/subprojects/subDep/meson.build
-test cases/common/227 fs module/a_symlink
-test cases/common/227 fs module/meson.build
-test cases/common/227 fs module/subdir/meson.build
-test cases/common/227 fs module/subdir/subdirfile.txt
-test cases/common/227 fs module/subprojects/subbie/meson.build
-test cases/common/227 fs module/subprojects/subbie/subprojectfile.txt
-test cases/common/227 fs module/subprojects/subbie/subsub/meson.build
-test cases/common/227 fs module/subprojects/subbie/subsub/subsubfile.txt
-test cases/common/23 object extraction/lib.c
-test cases/common/23 object extraction/lib2.c
-test cases/common/23 object extraction/main.c
-test cases/common/23 object extraction/meson.build
-test cases/common/23 object extraction/src/lib.c
-test cases/common/24 endian/meson.build
-test cases/common/24 endian/prog.c
-test cases/common/25 library versions/installed_files.txt
-test cases/common/25 library versions/lib.c
-test cases/common/25 library versions/meson.build
-test cases/common/25 library versions/subdir/meson.build
-test cases/common/26 config subdir/meson.build
-test cases/common/26 config subdir/include/config.h.in
-test cases/common/26 config subdir/include/meson.build
-test cases/common/26 config subdir/src/meson.build
-test cases/common/26 config subdir/src/prog.c
-test cases/common/27 pipeline/input_src.dat
-test cases/common/27 pipeline/meson.build
-test cases/common/27 pipeline/prog.c
-test cases/common/27 pipeline/srcgen.c
-test cases/common/27 pipeline/depends/copyrunner.py
-test cases/common/27 pipeline/depends/filecopier.c
-test cases/common/27 pipeline/depends/libsrc.c.in
-test cases/common/27 pipeline/depends/meson.build
-test cases/common/27 pipeline/depends/prog.c
-test cases/common/27 pipeline/src/input_src.dat
-test cases/common/27 pipeline/src/meson.build
-test cases/common/27 pipeline/src/prog.c
-test cases/common/27 pipeline/src/srcgen.c
-test cases/common/28 find program/meson.build
-test cases/common/28 find program/print-version-with-prefix.py
-test cases/common/28 find program/print-version.py
-test cases/common/28 find program/source.in
-test cases/common/28 find program/scripts/test_subdir.py
-test cases/common/29 multiline string/meson.build
+test cases/common/20 global arg/meson.build
+test cases/common/20 global arg/prog.c
+test cases/common/20 global arg/prog.cc
+test cases/common/200 install name_prefix name_suffix/libfile.c
+test cases/common/200 install name_prefix name_suffix/meson.build
+test cases/common/200 install name_prefix name_suffix/test.json
+test cases/common/201 kwarg entry/meson.build
+test cases/common/201 kwarg entry/prog.c
+test cases/common/201 kwarg entry/test.json
+test cases/common/201 kwarg entry/inc/prog.h
+test cases/common/202 custom target build by default/docgen.py
+test cases/common/202 custom target build by default/meson.build
+test cases/common/202 custom target build by default/test.json
+test cases/common/203 find_library and headers/foo.h
+test cases/common/203 find_library and headers/meson.build
+test cases/common/204 line continuation/meson.build
+test cases/common/205 native file path override/main.cpp
+test cases/common/205 native file path override/meson.build
+test cases/common/205 native file path override/nativefile.ini
+test cases/common/205 native file path override/test.json
+test cases/common/206 tap tests/cat.c
+test cases/common/206 tap tests/issue7515.txt
+test cases/common/206 tap tests/meson.build
+test cases/common/206 tap tests/tester.c
+test cases/common/207 warning level 0/main.cpp
+test cases/common/207 warning level 0/meson.build
+test cases/common/208 link custom/custom_stlib.py
+test cases/common/208 link custom/custom_target.c
+test cases/common/208 link custom/custom_target.py
+test cases/common/208 link custom/dummy.c
+test cases/common/208 link custom/lib.c
+test cases/common/208 link custom/meson.build
+test cases/common/208 link custom/outerlib.c
+test cases/common/208 link custom/prog.c
+test cases/common/209 link custom_i single from multiple/generate_conflicting_stlibs.py
+test cases/common/209 link custom_i single from multiple/meson.build
+test cases/common/209 link custom_i single from multiple/prog.c
+test cases/common/21 target arg/func.c
+test cases/common/21 target arg/func2.c
+test cases/common/21 target arg/meson.build
+test cases/common/21 target arg/prog.cc
+test cases/common/21 target arg/prog2.cc
+test cases/common/210 link custom_i multiple from multiple/generate_stlibs.py
+test cases/common/210 link custom_i multiple from multiple/meson.build
+test cases/common/210 link custom_i multiple from multiple/prog.c
+test cases/common/211 dependency get_variable method/meson.build
+test cases/common/211 dependency get_variable method/test.json
+test cases/common/212 source set configuration_data/a.c
+test cases/common/212 source set configuration_data/all.h
+test cases/common/212 source set configuration_data/f.c
+test cases/common/212 source set configuration_data/g.c
+test cases/common/212 source set configuration_data/meson.build
+test cases/common/212 source set configuration_data/nope.c
+test cases/common/212 source set configuration_data/subdir/b.c
+test cases/common/212 source set configuration_data/subdir/meson.build
+test cases/common/213 source set dictionary/a.c
+test cases/common/213 source set dictionary/all.h
+test cases/common/213 source set dictionary/f.c
+test cases/common/213 source set dictionary/g.c
+test cases/common/213 source set dictionary/meson.build
+test cases/common/213 source set dictionary/nope.c
+test cases/common/213 source set dictionary/subdir/b.c
+test cases/common/213 source set dictionary/subdir/meson.build
+test cases/common/214 source set custom target/a.c
+test cases/common/214 source set custom target/all.h
+test cases/common/214 source set custom target/cp.py
+test cases/common/214 source set custom target/f.c
+test cases/common/214 source set custom target/g.c
+test cases/common/214 source set custom target/meson.build
+test cases/common/215 source set realistic example/common.h
+test cases/common/215 source set realistic example/main.cc
+test cases/common/215 source set realistic example/meson.build
+test cases/common/215 source set realistic example/not-found.cc
+test cases/common/215 source set realistic example/was-found.cc
+test cases/common/215 source set realistic example/zlib.cc
+test cases/common/215 source set realistic example/boards/meson.build
+test cases/common/215 source set realistic example/boards/arm/aarch64.cc
+test cases/common/215 source set realistic example/boards/arm/arm.cc
+test cases/common/215 source set realistic example/boards/arm/arm.h
+test cases/common/215 source set realistic example/boards/arm/arm32.cc
+test cases/common/215 source set realistic example/boards/arm/versatilepb.cc
+test cases/common/215 source set realistic example/boards/arm/virt.cc
+test cases/common/215 source set realistic example/boards/arm/xlnx_zcu102.cc
+test cases/common/215 source set realistic example/boards/x86/pc.cc
+test cases/common/215 source set realistic example/config/aarch64
+test cases/common/215 source set realistic example/config/arm
+test cases/common/215 source set realistic example/config/x86
+test cases/common/215 source set realistic example/devices/meson.build
+test cases/common/215 source set realistic example/devices/virtio-mmio.cc
+test cases/common/215 source set realistic example/devices/virtio-pci.cc
+test cases/common/215 source set realistic example/devices/virtio.cc
+test cases/common/215 source set realistic example/devices/virtio.h
+test cases/common/216 custom target input extracted objects/check_object.py
+test cases/common/216 custom target input extracted objects/meson.build
+test cases/common/216 custom target input extracted objects/libdir/meson.build
+test cases/common/216 custom target input extracted objects/libdir/source.c
+test cases/common/217 test priorities/meson.build
+test cases/common/217 test priorities/testprog.py
+test cases/common/218 include_dir dot/meson.build
+test cases/common/218 include_dir dot/rone.h
+test cases/common/218 include_dir dot/src/main.c
+test cases/common/218 include_dir dot/src/meson.build
+test cases/common/218 include_dir dot/src/rone.c
+test cases/common/219 include_type dependency/main.cpp
+test cases/common/219 include_type dependency/meson.build
+test cases/common/219 include_type dependency/pch/test.hpp
+test cases/common/219 include_type dependency/subprojects/subDep/meson.build
+test cases/common/22 object extraction/check-obj.py
+test cases/common/22 object extraction/create-source.py
+test cases/common/22 object extraction/header.h
+test cases/common/22 object extraction/lib.c
+test cases/common/22 object extraction/lib2.c
+test cases/common/22 object extraction/main.c
+test cases/common/22 object extraction/meson.build
+test cases/common/22 object extraction/src/lib.c
+test cases/common/220 fs module/meson.build
+test cases/common/220 fs module/subdir/meson.build
+test cases/common/220 fs module/subdir/subdirfile.txt
+test cases/common/220 fs module/subprojects/subbie/meson.build
+test cases/common/220 fs module/subprojects/subbie/subprojectfile.txt
+test cases/common/220 fs module/subprojects/subbie/subsub/meson.build
+test cases/common/220 fs module/subprojects/subbie/subsub/subsubfile.txt
+test cases/common/221 zlib/meson.build
+test cases/common/222 native prop/crossfile.ini
+test cases/common/222 native prop/meson.build
+test cases/common/222 native prop/nativefile.ini
+test cases/common/223 persubproject options/foo.c
+test cases/common/223 persubproject options/meson.build
+test cases/common/223 persubproject options/test.json
+test cases/common/223 persubproject options/subprojects/sub1/foo.c
+test cases/common/223 persubproject options/subprojects/sub1/meson.build
+test cases/common/223 persubproject options/subprojects/sub2/foo.c
+test cases/common/223 persubproject options/subprojects/sub2/meson.build
+test cases/common/224 arithmetic operators/meson.build
+test cases/common/225 link language/c_linkage.cpp
+test cases/common/225 link language/c_linkage.h
+test cases/common/225 link language/lib.cpp
+test cases/common/225 link language/main.c
+test cases/common/225 link language/meson.build
+test cases/common/226 link depends indexed custom target/check_arch.py
+test cases/common/226 link depends indexed custom target/foo.c
+test cases/common/226 link depends indexed custom target/make_file.py
+test cases/common/226 link depends indexed custom target/meson.build
+test cases/common/227 very long commmand line/codegen.py
+test cases/common/227 very long commmand line/main.c
+test cases/common/227 very long commmand line/meson.build
+test cases/common/227 very long commmand line/name_gen.py
+test cases/common/228 custom_target source/a
+test cases/common/228 custom_target source/meson.build
+test cases/common/228 custom_target source/x.py
+test cases/common/229 disabler array addition/meson.build
+test cases/common/229 disabler array addition/test.c
+test cases/common/23 endian/meson.build
+test cases/common/23 endian/prog.c
+test cases/common/230 external project/app.c
+test cases/common/230 external project/func.c
+test cases/common/230 external project/func.h
+test cases/common/230 external project/meson.build
+test cases/common/230 external project/test.json
+test cases/common/230 external project/libfoo/configure
+test cases/common/230 external project/libfoo/libfoo.c
+test cases/common/230 external project/libfoo/libfoo.h
+test cases/common/230 external project/libfoo/meson.build
+test cases/common/231 subdir files/meson.build
+test cases/common/231 subdir files/subdir/meson.build
+test cases/common/231 subdir files/subdir/prog.c
+test cases/common/232 dependency allow_fallback/meson.build
+test cases/common/232 dependency allow_fallback/subprojects/foob/meson.build
+test cases/common/232 dependency allow_fallback/subprojects/foob3/meson.build
+test cases/common/233 wrap case/meson.build
+test cases/common/233 wrap case/prog.c
+test cases/common/233 wrap case/subprojects/up_down.wrap
+test cases/common/233 wrap case/subprojects/up_down/meson.build
+test cases/common/233 wrap case/subprojects/up_down/up_down.h
+test cases/common/234 get_file_contents/.gitattributes
+test cases/common/234 get_file_contents/VERSION
+test cases/common/234 get_file_contents/meson.build
+test cases/common/234 get_file_contents/utf-16-text
+test cases/common/234 get_file_contents/other/meson.build
+test cases/common/235 invalid standard overriden to valid/main.c
+test cases/common/235 invalid standard overriden to valid/meson.build
+test cases/common/235 invalid standard overriden to valid/test.json
+test cases/common/236 proper args splitting/main.c
+test cases/common/236 proper args splitting/meson.build
+test cases/common/236 proper args splitting/test.json
+test cases/common/237 fstrings/meson.build
+test cases/common/238 dependency include_type inconsistency/meson.build
+test cases/common/238 dependency include_type inconsistency/bar/meson.build
+test cases/common/238 dependency include_type inconsistency/subprojects/baz.wrap
+test cases/common/238 dependency include_type inconsistency/subprojects/foo.wrap
+test cases/common/238 dependency include_type inconsistency/subprojects/baz/meson.build
+test cases/common/238 dependency include_type inconsistency/subprojects/foo/meson.build
+test cases/common/239 includedir violation/meson.build
+test cases/common/239 includedir violation/test.json
+test cases/common/239 includedir violation/subprojects/sub/meson.build
+test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h
+test cases/common/24 library versions/lib.c
+test cases/common/24 library versions/meson.build
+test cases/common/24 library versions/test.json
+test cases/common/24 library versions/subdir/meson.build
+test cases/common/240 dependency native host == build/meson.build
+test cases/common/240 dependency native host == build/test.json
+test cases/common/241 set and get variable/meson.build
+test cases/common/241 set and get variable/test1.txt
+test cases/common/241 set and get variable/test2.txt
+test cases/common/242 custom target feed/data_source.txt
+test cases/common/242 custom target feed/meson.build
+test cases/common/242 custom target feed/my_compiler.py
+test cases/common/242 custom target feed/test.json
+test cases/common/243 escape++/meson.build
+test cases/common/243 escape++/test.c
+test cases/common/244 variable scope/meson.build
+test cases/common/245 custom target index source/code_source.c
+test cases/common/245 custom target index source/copyfile.py
+test cases/common/245 custom target index source/copyfile2.py
+test cases/common/245 custom target index source/header_source.h
+test cases/common/245 custom target index source/main.c
+test cases/common/245 custom target index source/meson.build
+test cases/common/246 dependency fallbacks/meson.build
+test cases/common/246 dependency fallbacks/subprojects/png/meson.build
+test cases/common/247 deprecated option/meson.build
+test cases/common/247 deprecated option/meson_options.txt
+test cases/common/247 deprecated option/test.json
+test cases/common/248 install_emptydir/meson.build
+test cases/common/248 install_emptydir/test.json
+test cases/common/249 install_symlink/datafile.dat
+test cases/common/249 install_symlink/meson.build
+test cases/common/249 install_symlink/test.json
+test cases/common/25 config subdir/meson.build
+test cases/common/25 config subdir/include/config.h.in
+test cases/common/25 config subdir/include/meson.build
+test cases/common/25 config subdir/src/meson.build
+test cases/common/25 config subdir/src/prog.c
+test cases/common/250 system include dir/main.cpp
+test cases/common/250 system include dir/meson.build
+test cases/common/250 system include dir/lib/lib.hpp
+test cases/common/26 find program/meson.build
+test cases/common/26 find program/print-version-with-prefix.py
+test cases/common/26 find program/print-version.py
+test cases/common/26 find program/source.in
+test cases/common/26 find program/scripts/test_subdir.py
+test cases/common/27 multiline string/meson.build
+test cases/common/28 try compile/invalid.c
+test cases/common/28 try compile/meson.build
+test cases/common/28 try compile/valid.c
+test cases/common/29 compiler id/meson.build
 test cases/common/3 static/libfile.c
 test cases/common/3 static/libfile2.c
 test cases/common/3 static/meson.build
 test cases/common/3 static/meson_options.txt
-test cases/common/30 try compile/invalid.c
-test cases/common/30 try compile/meson.build
-test cases/common/30 try compile/valid.c
-test cases/common/31 compiler id/meson.build
-test cases/common/32 sizeof/config.h.in
-test cases/common/32 sizeof/meson.build
-test cases/common/32 sizeof/prog.c.in
-test cases/common/33 define10/config.h.in
-test cases/common/33 define10/meson.build
-test cases/common/33 define10/prog.c
-test cases/common/34 has header/meson.build
-test cases/common/34 has header/ouagadougou.h
-test cases/common/35 run program/get-version.py
-test cases/common/35 run program/meson.build
-test cases/common/35 run program/scripts/hello.bat
-test cases/common/35 run program/scripts/hello.sh
-test cases/common/36 tryrun/error.c
-test cases/common/36 tryrun/meson.build
-test cases/common/36 tryrun/no_compile.c
-test cases/common/36 tryrun/ok.c
-test cases/common/37 logic ops/meson.build
-test cases/common/38 string operations/meson.build
-test cases/common/39 has function/meson.build
+test cases/common/30 sizeof/config.h.in
+test cases/common/30 sizeof/meson.build
+test cases/common/30 sizeof/prog.c.in
+test cases/common/31 define10/config.h.in
+test cases/common/31 define10/meson.build
+test cases/common/31 define10/prog.c
+test cases/common/32 has header/meson.build
+test cases/common/32 has header/ouagadougou.h
+test cases/common/33 run program/check-env.py
+test cases/common/33 run program/get-version.py
+test cases/common/33 run program/meson.build
+test cases/common/33 run program/scripts/hello.bat
+test cases/common/33 run program/scripts/hello.sh
+test cases/common/34 logic ops/meson.build
+test cases/common/35 string operations/meson.build
+test cases/common/36 has function/meson.build
+test cases/common/37 has member/meson.build
+test cases/common/38 alignment/meson.build
+test cases/common/39 library chain/main.c
+test cases/common/39 library chain/meson.build
+test cases/common/39 library chain/test.json
+test cases/common/39 library chain/subdir/lib1.c
+test cases/common/39 library chain/subdir/meson.build
+test cases/common/39 library chain/subdir/subdir2/lib2.c
+test cases/common/39 library chain/subdir/subdir2/meson.build
+test cases/common/39 library chain/subdir/subdir3/lib3.c
+test cases/common/39 library chain/subdir/subdir3/meson.build
 test cases/common/4 shared/libfile.c
 test cases/common/4 shared/meson.build
-test cases/common/40 has member/meson.build
-test cases/common/41 alignment/meson.build
-test cases/common/42 library chain/installed_files.txt
-test cases/common/42 library chain/main.c
-test cases/common/42 library chain/meson.build
-test cases/common/42 library chain/subdir/lib1.c
-test cases/common/42 library chain/subdir/meson.build
-test cases/common/42 library chain/subdir/subdir2/lib2.c
-test cases/common/42 library chain/subdir/subdir2/meson.build
-test cases/common/42 library chain/subdir/subdir3/lib3.c
-test cases/common/42 library chain/subdir/subdir3/meson.build
-test cases/common/43 options/meson.build
-test cases/common/43 options/meson_options.txt
-test cases/common/44 test args/cmd_args.c
-test cases/common/44 test args/copyfile.py
-test cases/common/44 test args/env2vars.c
-test cases/common/44 test args/envvars.c
-test cases/common/44 test args/meson.build
-test cases/common/44 test args/tester.c
-test cases/common/44 test args/tester.py
-test cases/common/44 test args/testfile.txt
-test cases/common/45 subproject/installed_files.txt
-test cases/common/45 subproject/meson.build
-test cases/common/45 subproject/user.c
-test cases/common/45 subproject/subprojects/sublib/meson.build
-test cases/common/45 subproject/subprojects/sublib/simpletest.c
-test cases/common/45 subproject/subprojects/sublib/sublib.c
-test cases/common/45 subproject/subprojects/sublib/include/subdefs.h
-test cases/common/46 subproject options/meson.build
-test cases/common/46 subproject options/meson_options.txt
-test cases/common/46 subproject options/subprojects/subproject/meson.build
-test cases/common/46 subproject options/subprojects/subproject/meson_options.txt
-test cases/common/47 pkgconfig-gen/installed_files.txt
-test cases/common/47 pkgconfig-gen/meson.build
-test cases/common/47 pkgconfig-gen/simple.c
-test cases/common/47 pkgconfig-gen/simple.h
-test cases/common/47 pkgconfig-gen/dependencies/custom.c
-test cases/common/47 pkgconfig-gen/dependencies/exposed.c
-test cases/common/47 pkgconfig-gen/dependencies/internal.c
-test cases/common/47 pkgconfig-gen/dependencies/meson.build
-test cases/common/48 custom install dirs/datafile.cat
-test cases/common/48 custom install dirs/installed_files.txt
-test cases/common/48 custom install dirs/meson.build
-test cases/common/48 custom install dirs/prog.1
-test cases/common/48 custom install dirs/prog.c
-test cases/common/48 custom install dirs/sample.h
-test cases/common/48 custom install dirs/subdir/datafile.dog
-test cases/common/49 subproject subproject/meson.build
-test cases/common/49 subproject subproject/prog.c
-test cases/common/49 subproject subproject/subprojects/a/a.c
-test cases/common/49 subproject subproject/subprojects/a/meson.build
-test cases/common/49 subproject subproject/subprojects/b/b.c
-test cases/common/49 subproject subproject/subprojects/b/meson.build
-test cases/common/49 subproject subproject/subprojects/c/meson.build
+test cases/common/40 options/meson.build
+test cases/common/40 options/meson_options.txt
+test cases/common/41 test args/cmd_args.c
+test cases/common/41 test args/copyfile.py
+test cases/common/41 test args/env2vars.c
+test cases/common/41 test args/envvars.c
+test cases/common/41 test args/meson.build
+test cases/common/41 test args/tester.c
+test cases/common/41 test args/tester.py
+test cases/common/41 test args/testfile.txt
+test cases/common/42 subproject/meson.build
+test cases/common/42 subproject/test.json
+test cases/common/42 subproject/user.c
+test cases/common/42 subproject/subprojects/sublib/meson.build
+test cases/common/42 subproject/subprojects/sublib/simpletest.c
+test cases/common/42 subproject/subprojects/sublib/sublib.c
+test cases/common/42 subproject/subprojects/sublib/include/subdefs.h
+test cases/common/43 subproject options/meson.build
+test cases/common/43 subproject options/meson_options.txt
+test cases/common/43 subproject options/subprojects/subproject/meson.build
+test cases/common/43 subproject options/subprojects/subproject/meson_options.txt
+test cases/common/44 pkgconfig-gen/answer.c
+test cases/common/44 pkgconfig-gen/foo.c
+test cases/common/44 pkgconfig-gen/meson.build
+test cases/common/44 pkgconfig-gen/simple.c
+test cases/common/44 pkgconfig-gen/simple.h
+test cases/common/44 pkgconfig-gen/simple5.c
+test cases/common/44 pkgconfig-gen/test.json
+test cases/common/44 pkgconfig-gen/dependencies/custom.c
+test cases/common/44 pkgconfig-gen/dependencies/exposed.c
+test cases/common/44 pkgconfig-gen/dependencies/internal.c
+test cases/common/44 pkgconfig-gen/dependencies/main.c
+test cases/common/44 pkgconfig-gen/dependencies/meson.build
+test cases/common/45 custom install dirs/datafile.cat
+test cases/common/45 custom install dirs/meson.build
+test cases/common/45 custom install dirs/prog.1
+test cases/common/45 custom install dirs/prog.c
+test cases/common/45 custom install dirs/sample.h
+test cases/common/45 custom install dirs/test.json
+test cases/common/45 custom install dirs/subdir/datafile.dog
+test cases/common/46 subproject subproject/meson.build
+test cases/common/46 subproject subproject/prog.c
+test cases/common/46 subproject subproject/subprojects/a/a.c
+test cases/common/46 subproject subproject/subprojects/a/meson.build
+test cases/common/46 subproject subproject/subprojects/b/b.c
+test cases/common/46 subproject subproject/subprojects/b/meson.build
+test cases/common/46 subproject subproject/subprojects/c/meson.build
+test cases/common/47 same file name/meson.build
+test cases/common/47 same file name/prog.c
+test cases/common/47 same file name/d1/file.c
+test cases/common/47 same file name/d2/file.c
+test cases/common/48 file grabber/a.c
+test cases/common/48 file grabber/b.c
+test cases/common/48 file grabber/c.c
+test cases/common/48 file grabber/grabber.bat
+test cases/common/48 file grabber/grabber.sh
+test cases/common/48 file grabber/grabber2.bat
+test cases/common/48 file grabber/meson.build
+test cases/common/48 file grabber/prog.c
+test cases/common/48 file grabber/subdir/meson.build
+test cases/common/48 file grabber/subdir/suba.c
+test cases/common/48 file grabber/subdir/subb.c
+test cases/common/48 file grabber/subdir/subc.c
+test cases/common/48 file grabber/subdir/subprog.c
+test cases/common/49 custom target/data_source.txt
+test cases/common/49 custom target/meson.build
+test cases/common/49 custom target/my_compiler.py
+test cases/common/49 custom target/test.json
+test cases/common/49 custom target/depfile/dep.py
+test cases/common/49 custom target/depfile/meson.build
 test cases/common/5 linkstatic/libfile.c
 test cases/common/5 linkstatic/libfile2.c
 test cases/common/5 linkstatic/libfile3.c
 test cases/common/5 linkstatic/libfile4.c
 test cases/common/5 linkstatic/main.c
 test cases/common/5 linkstatic/meson.build
-test cases/common/50 same file name/meson.build
-test cases/common/50 same file name/prog.c
-test cases/common/50 same file name/d1/file.c
-test cases/common/50 same file name/d2/file.c
-test cases/common/51 file grabber/a.c
-test cases/common/51 file grabber/b.c
-test cases/common/51 file grabber/c.c
-test cases/common/51 file grabber/grabber.bat
-test cases/common/51 file grabber/grabber.sh
-test cases/common/51 file grabber/grabber2.bat
-test cases/common/51 file grabber/meson.build
-test cases/common/51 file grabber/prog.c
-test cases/common/51 file grabber/subdir/meson.build
-test cases/common/51 file grabber/subdir/suba.c
-test cases/common/51 file grabber/subdir/subb.c
-test cases/common/51 file grabber/subdir/subc.c
-test cases/common/51 file grabber/subdir/subprog.c
-test cases/common/52 custom target/data_source.txt
-test cases/common/52 custom target/installed_files.txt
-test cases/common/52 custom target/meson.build
-test cases/common/52 custom target/my_compiler.py
-test cases/common/52 custom target/depfile/dep.py
-test cases/common/52 custom target/depfile/meson.build
-test cases/common/53 custom target chain/data_source.txt
-test cases/common/53 custom target chain/installed_files.txt
-test cases/common/53 custom target chain/meson.build
-test cases/common/53 custom target chain/my_compiler.py
-test cases/common/53 custom target chain/my_compiler2.py
-test cases/common/53 custom target chain/usetarget/meson.build
-test cases/common/53 custom target chain/usetarget/myexe.c
-test cases/common/53 custom target chain/usetarget/subcomp.py
-test cases/common/54 run target/check_exists.py
-test cases/common/54 run target/configure.in
-test cases/common/54 run target/converter.py
-test cases/common/54 run target/fakeburner.py
-test cases/common/54 run target/helloprinter.c
-test cases/common/54 run target/meson.build
-test cases/common/55 object generator/meson.build
-test cases/common/55 object generator/obj_generator.py
-test cases/common/55 object generator/prog.c
-test cases/common/55 object generator/source.c
-test cases/common/55 object generator/source2.c
-test cases/common/55 object generator/source3.c
-test cases/common/56 install script/installed_files.txt
-test cases/common/56 install script/meson.build
-test cases/common/56 install script/myinstall.py
-test cases/common/56 install script/no-installed-files
-test cases/common/56 install script/prog.c
-test cases/common/56 install script/src/meson.build
-test cases/common/56 install script/src/myinstall.py
-test cases/common/57 custom target source output/generator.py
-test cases/common/57 custom target source output/main.c
-test cases/common/57 custom target source output/meson.build
-test cases/common/58 exe static shared/meson.build
-test cases/common/58 exe static shared/prog.c
-test cases/common/58 exe static shared/shlib2.c
-test cases/common/58 exe static shared/stat.c
-test cases/common/58 exe static shared/stat2.c
-test cases/common/58 exe static shared/subdir/exports.h
-test cases/common/58 exe static shared/subdir/meson.build
-test cases/common/58 exe static shared/subdir/shlib.c
-test cases/common/59 array methods/meson.build
+test cases/common/50 custom target chain/data_source.txt
+test cases/common/50 custom target chain/meson.build
+test cases/common/50 custom target chain/my_compiler.py
+test cases/common/50 custom target chain/my_compiler2.py
+test cases/common/50 custom target chain/test.json
+test cases/common/50 custom target chain/usetarget/meson.build
+test cases/common/50 custom target chain/usetarget/myexe.c
+test cases/common/50 custom target chain/usetarget/subcomp.py
+test cases/common/51 run target/check-env.py
+test cases/common/51 run target/check_exists.py
+test cases/common/51 run target/configure.in
+test cases/common/51 run target/converter.py
+test cases/common/51 run target/fakeburner.py
+test cases/common/51 run target/helloprinter.c
+test cases/common/51 run target/meson.build
+test cases/common/51 run target/subdir/textprinter.py
+test cases/common/52 object generator/meson.build
+test cases/common/52 object generator/obj_generator.py
+test cases/common/52 object generator/prog.c
+test cases/common/52 object generator/source.c
+test cases/common/52 object generator/source2.c
+test cases/common/52 object generator/source3.c
+test cases/common/53 install script/customtarget.py
+test cases/common/53 install script/meson.build
+test cases/common/53 install script/myinstall.py
+test cases/common/53 install script/prog.c
+test cases/common/53 install script/test.json
+test cases/common/53 install script/src/a file.txt
+test cases/common/53 install script/src/foo.c
+test cases/common/53 install script/src/meson.build
+test cases/common/53 install script/src/myinstall.py
+test cases/common/54 custom target source output/generator.py
+test cases/common/54 custom target source output/main.c
+test cases/common/54 custom target source output/meson.build
+test cases/common/55 exe static shared/meson.build
+test cases/common/55 exe static shared/prog.c
+test cases/common/55 exe static shared/shlib2.c
+test cases/common/55 exe static shared/stat.c
+test cases/common/55 exe static shared/stat2.c
+test cases/common/55 exe static shared/subdir/exports.h
+test cases/common/55 exe static shared/subdir/meson.build
+test cases/common/55 exe static shared/subdir/shlib.c
+test cases/common/56 array methods/a.txt
+test cases/common/56 array methods/b.txt
+test cases/common/56 array methods/c.txt
+test cases/common/56 array methods/meson.build
+test cases/common/57 custom header generator/input.def
+test cases/common/57 custom header generator/makeheader.py
+test cases/common/57 custom header generator/meson.build
+test cases/common/57 custom header generator/prog.c
+test cases/common/57 custom header generator/somefile.txt
+test cases/common/58 multiple generators/data2.dat
+test cases/common/58 multiple generators/main.cpp
+test cases/common/58 multiple generators/meson.build
+test cases/common/58 multiple generators/mygen.py
+test cases/common/58 multiple generators/subdir/data.dat
+test cases/common/58 multiple generators/subdir/meson.build
+test cases/common/59 install subdir/meson.build
+test cases/common/59 install subdir/test.json
+test cases/common/59 install subdir/nested_elided/sub/eighth.dat
+test cases/common/59 install subdir/nested_elided/sub/dircheck/ninth.dat
+test cases/common/59 install subdir/sub/sub1/third.dat
+test cases/common/59 install subdir/sub1/second.dat
+test cases/common/59 install subdir/sub2/excluded-three.dat
+test cases/common/59 install subdir/sub2/one.dat
+test cases/common/59 install subdir/sub2/dircheck/excluded-three.dat
+test cases/common/59 install subdir/sub2/excluded/two.dat
+test cases/common/59 install subdir/sub_elided/fourth.dat
+test cases/common/59 install subdir/sub_elided/dircheck/fifth.dat
+test cases/common/59 install subdir/subdir/meson.build
+test cases/common/59 install subdir/subdir/sub1/data1.dat
+test cases/common/59 install subdir/subdir/sub1/sub2/data2.dat
+test cases/common/59 install subdir/subdir/sub_elided/sixth.dat
+test cases/common/59 install subdir/subdir/sub_elided/dircheck/seventh.dat
 test cases/common/6 linkshared/cpplib.cpp
+test cases/common/6 linkshared/cpplib.h
 test cases/common/6 linkshared/cppmain.cpp
-test cases/common/6 linkshared/installed_files.txt
 test cases/common/6 linkshared/libfile.c
 test cases/common/6 linkshared/main.c
 test cases/common/6 linkshared/meson.build
-test cases/common/60 custom header generator/input.def
-test cases/common/60 custom header generator/makeheader.py
-test cases/common/60 custom header generator/meson.build
-test cases/common/60 custom header generator/prog.c
-test cases/common/60 custom header generator/somefile.txt
-test cases/common/61 multiple generators/data2.dat
-test cases/common/61 multiple generators/main.cpp
-test cases/common/61 multiple generators/meson.build
-test cases/common/61 multiple generators/mygen.py
-test cases/common/61 multiple generators/subdir/data.dat
-test cases/common/61 multiple generators/subdir/meson.build
-test cases/common/62 install subdir/installed_files.txt
-test cases/common/62 install subdir/meson.build
-test cases/common/62 install subdir/nested_elided/sub/eighth.dat
-test cases/common/62 install subdir/nested_elided/sub/dircheck/ninth.dat
-test cases/common/62 install subdir/sub/sub1/third.dat
-test cases/common/62 install subdir/sub1/second.dat
-test cases/common/62 install subdir/sub2/excluded-three.dat
-test cases/common/62 install subdir/sub2/one.dat
-test cases/common/62 install subdir/sub2/dircheck/excluded-three.dat
-test cases/common/62 install subdir/sub2/excluded/two.dat
-test cases/common/62 install subdir/sub_elided/fourth.dat
-test cases/common/62 install subdir/sub_elided/dircheck/fifth.dat
-test cases/common/62 install subdir/subdir/meson.build
-test cases/common/62 install subdir/subdir/sub1/data1.dat
-test cases/common/62 install subdir/subdir/sub1/sub2/data2.dat
-test cases/common/62 install subdir/subdir/sub_elided/sixth.dat
-test cases/common/62 install subdir/subdir/sub_elided/dircheck/seventh.dat
-test cases/common/63 foreach/installed_files.txt
-test cases/common/63 foreach/meson.build
-test cases/common/63 foreach/prog1.c
-test cases/common/63 foreach/prog2.c
-test cases/common/63 foreach/prog3.c
-test cases/common/64 number arithmetic/meson.build
-test cases/common/65 string arithmetic/meson.build
-test cases/common/66 array arithmetic/meson.build
-test cases/common/67 arithmetic bidmas/meson.build
-test cases/common/68 build always/main.c
-test cases/common/68 build always/meson.build
-test cases/common/68 build always/version.c.in
-test cases/common/68 build always/version.h
-test cases/common/68 build always/version_gen.py
-test cases/common/69 vcstag/meson.build
-test cases/common/69 vcstag/tagprog.c
-test cases/common/69 vcstag/vcstag.c.in
+test cases/common/6 linkshared/test.json
+test cases/common/60 foreach/meson.build
+test cases/common/60 foreach/prog1.c
+test cases/common/60 foreach/prog2.c
+test cases/common/60 foreach/prog3.c
+test cases/common/60 foreach/test.json
+test cases/common/61 number arithmetic/meson.build
+test cases/common/62 string arithmetic/meson.build
+test cases/common/63 array arithmetic/meson.build
+test cases/common/64 arithmetic bidmas/meson.build
+test cases/common/65 build always/main.c
+test cases/common/65 build always/meson.build
+test cases/common/65 build always/version.c.in
+test cases/common/65 build always/version.h
+test cases/common/65 build always/version_gen.py
+test cases/common/66 vcstag/meson.build
+test cases/common/66 vcstag/tagprog.c
+test cases/common/66 vcstag/vcstag.c.in
+test cases/common/67 modules/meson.build
+test cases/common/67 modules/meson_options.txt
+test cases/common/68 should fail/failing.c
+test cases/common/68 should fail/meson.build
+test cases/common/69 configure file in custom target/meson.build
+test cases/common/69 configure file in custom target/inc/confdata.in
+test cases/common/69 configure file in custom target/inc/meson.build
+test cases/common/69 configure file in custom target/src/meson.build
+test cases/common/69 configure file in custom target/src/mycompiler.py
 test cases/common/7 mixed/func.c
 test cases/common/7 mixed/main.cc
 test cases/common/7 mixed/meson.build
-test cases/common/70 modules/meson.build
-test cases/common/71 should fail/failing.c
-test cases/common/71 should fail/meson.build
-test cases/common/72 configure file in custom target/meson.build
-test cases/common/72 configure file in custom target/inc/confdata.in
-test cases/common/72 configure file in custom target/inc/meson.build
-test cases/common/72 configure file in custom target/src/meson.build
-test cases/common/72 configure file in custom target/src/mycompiler.py
-test cases/common/73 external test program/meson.build
-test cases/common/73 external test program/mytest.py
-test cases/common/74 ctarget dependency/gen1.py
-test cases/common/74 ctarget dependency/gen2.py
-test cases/common/74 ctarget dependency/input.dat
-test cases/common/74 ctarget dependency/meson.build
-test cases/common/75 shared subproject/a.c
-test cases/common/75 shared subproject/meson.build
-test cases/common/75 shared subproject/subprojects/B/b.c
-test cases/common/75 shared subproject/subprojects/B/meson.build
-test cases/common/75 shared subproject/subprojects/C/c.c
-test cases/common/75 shared subproject/subprojects/C/meson.build
-test cases/common/76 shared subproject 2/a.c
-test cases/common/76 shared subproject 2/meson.build
-test cases/common/76 shared subproject 2/subprojects/B/b.c
-test cases/common/76 shared subproject 2/subprojects/B/meson.build
-test cases/common/76 shared subproject 2/subprojects/C/c.c
-test cases/common/76 shared subproject 2/subprojects/C/meson.build
-test cases/common/77 file object/lib.c
-test cases/common/77 file object/meson.build
-test cases/common/77 file object/prog.c
-test cases/common/77 file object/subdir1/lib.c
-test cases/common/77 file object/subdir1/meson.build
-test cases/common/77 file object/subdir1/prog.c
-test cases/common/77 file object/subdir2/lib.c
-test cases/common/77 file object/subdir2/meson.build
-test cases/common/77 file object/subdir2/prog.c
-test cases/common/78 custom subproject dir/a.c
-test cases/common/78 custom subproject dir/meson.build
-test cases/common/78 custom subproject dir/custom_subproject_dir/B/b.c
-test cases/common/78 custom subproject dir/custom_subproject_dir/B/meson.build
-test cases/common/78 custom subproject dir/custom_subproject_dir/C/c.c
-test cases/common/78 custom subproject dir/custom_subproject_dir/C/meson.build
-test cases/common/79 has type/meson.build
-test cases/common/8 install/installed_files.txt
+test cases/common/70 external test program/meson.build
+test cases/common/70 external test program/mytest.py
+test cases/common/71 ctarget dependency/gen1.py
+test cases/common/71 ctarget dependency/gen2.py
+test cases/common/71 ctarget dependency/input.dat
+test cases/common/71 ctarget dependency/meson.build
+test cases/common/72 shared subproject/a.c
+test cases/common/72 shared subproject/meson.build
+test cases/common/72 shared subproject/subprojects/B/b.c
+test cases/common/72 shared subproject/subprojects/B/meson.build
+test cases/common/72 shared subproject/subprojects/C/c.c
+test cases/common/72 shared subproject/subprojects/C/meson.build
+test cases/common/73 shared subproject 2/a.c
+test cases/common/73 shared subproject 2/meson.build
+test cases/common/73 shared subproject 2/subprojects/B/b.c
+test cases/common/73 shared subproject 2/subprojects/B/meson.build
+test cases/common/73 shared subproject 2/subprojects/C/c.c
+test cases/common/73 shared subproject 2/subprojects/C/meson.build
+test cases/common/74 file object/lib.c
+test cases/common/74 file object/meson.build
+test cases/common/74 file object/prog.c
+test cases/common/74 file object/subdir1/lib.c
+test cases/common/74 file object/subdir1/meson.build
+test cases/common/74 file object/subdir1/prog.c
+test cases/common/74 file object/subdir2/lib.c
+test cases/common/74 file object/subdir2/meson.build
+test cases/common/74 file object/subdir2/prog.c
+test cases/common/75 custom subproject dir/a.c
+test cases/common/75 custom subproject dir/meson.build
+test cases/common/75 custom subproject dir/custom_subproject_dir/B/b.c
+test cases/common/75 custom subproject dir/custom_subproject_dir/B/meson.build
+test cases/common/75 custom subproject dir/custom_subproject_dir/C/c.c
+test cases/common/75 custom subproject dir/custom_subproject_dir/C/meson.build
+test cases/common/76 has type/meson.build
+test cases/common/77 extract from nested subdir/meson.build
+test cases/common/77 extract from nested subdir/src/meson.build
+test cases/common/77 extract from nested subdir/src/first/lib_first.c
+test cases/common/77 extract from nested subdir/src/first/meson.build
+test cases/common/77 extract from nested subdir/tst/meson.build
+test cases/common/77 extract from nested subdir/tst/first/exe_first.c
+test cases/common/77 extract from nested subdir/tst/first/meson.build
+test cases/common/78 internal dependency/meson.build
+test cases/common/78 internal dependency/proj1/meson.build
+test cases/common/78 internal dependency/proj1/proj1f1.c
+test cases/common/78 internal dependency/proj1/proj1f2.c
+test cases/common/78 internal dependency/proj1/proj1f3.c
+test cases/common/78 internal dependency/proj1/include/proj1.h
+test cases/common/78 internal dependency/src/main.c
+test cases/common/78 internal dependency/src/meson.build
+test cases/common/79 same basename/exe1.c
+test cases/common/79 same basename/exe2.c
+test cases/common/79 same basename/lib.c
+test cases/common/79 same basename/meson.build
+test cases/common/79 same basename/sharedsub/meson.build
+test cases/common/79 same basename/staticsub/meson.build
+test cases/common/8 install/gendir.py
 test cases/common/8 install/meson.build
 test cases/common/8 install/prog.c
 test cases/common/8 install/stat.c
-test cases/common/80 extract from nested subdir/meson.build
-test cases/common/80 extract from nested subdir/src/meson.build
-test cases/common/80 extract from nested subdir/src/first/lib_first.c
-test cases/common/80 extract from nested subdir/src/first/meson.build
-test cases/common/80 extract from nested subdir/tst/meson.build
-test cases/common/80 extract from nested subdir/tst/first/exe_first.c
-test cases/common/80 extract from nested subdir/tst/first/meson.build
-test cases/common/81 internal dependency/meson.build
-test cases/common/81 internal dependency/proj1/meson.build
-test cases/common/81 internal dependency/proj1/proj1f1.c
-test cases/common/81 internal dependency/proj1/proj1f2.c
-test cases/common/81 internal dependency/proj1/proj1f3.c
-test cases/common/81 internal dependency/proj1/include/proj1.h
-test cases/common/81 internal dependency/src/main.c
-test cases/common/81 internal dependency/src/meson.build
-test cases/common/82 same basename/exe1.c
-test cases/common/82 same basename/exe2.c
-test cases/common/82 same basename/lib.c
-test cases/common/82 same basename/meson.build
-test cases/common/82 same basename/sharedsub/meson.build
-test cases/common/82 same basename/staticsub/meson.build
-test cases/common/83 declare dep/main.c
-test cases/common/83 declare dep/meson.build
-test cases/common/83 declare dep/entity/entity.h
-test cases/common/83 declare dep/entity/entity1.c
-test cases/common/83 declare dep/entity/entity2.c
-test cases/common/83 declare dep/entity/meson.build
-test cases/common/84 extract all/extractor.h
-test cases/common/84 extract all/four.c
-test cases/common/84 extract all/meson.build
-test cases/common/84 extract all/one.c
-test cases/common/84 extract all/prog.c
-test cases/common/84 extract all/three.c
-test cases/common/84 extract all/two.c
-test cases/common/85 add language/meson.build
-test cases/common/85 add language/prog.c
-test cases/common/85 add language/prog.cc
-test cases/common/86 identical target name in subproject/bar.c
-test cases/common/86 identical target name in subproject/meson.build
-test cases/common/86 identical target name in subproject/subprojects/foo/bar.c
-test cases/common/86 identical target name in subproject/subprojects/foo/meson.build
-test cases/common/87 plusassign/meson.build
-test cases/common/88 skip subdir/meson.build
-test cases/common/88 skip subdir/subdir1/meson.build
-test cases/common/88 skip subdir/subdir1/subdir2/meson.build
-test cases/common/89 private include/meson.build
-test cases/common/89 private include/stlib/compiler.py
-test cases/common/89 private include/stlib/foo1.def
-test cases/common/89 private include/stlib/foo2.def
-test cases/common/89 private include/stlib/meson.build
-test cases/common/89 private include/user/libuser.c
-test cases/common/89 private include/user/meson.build
-test cases/common/9 header install/installed_files.txt
+test cases/common/8 install/test.json
+test cases/common/80 declare dep/main.c
+test cases/common/80 declare dep/meson.build
+test cases/common/80 declare dep/entity/entity.h
+test cases/common/80 declare dep/entity/entity1.c
+test cases/common/80 declare dep/entity/entity2.c
+test cases/common/80 declare dep/entity/meson.build
+test cases/common/81 extract all/extractor.h
+test cases/common/81 extract all/four.c
+test cases/common/81 extract all/meson.build
+test cases/common/81 extract all/one.c
+test cases/common/81 extract all/prog.c
+test cases/common/81 extract all/three.c
+test cases/common/81 extract all/two.c
+test cases/common/82 add language/meson.build
+test cases/common/82 add language/prog.c
+test cases/common/82 add language/prog.cc
+test cases/common/83 identical target name in subproject/bar.c
+test cases/common/83 identical target name in subproject/meson.build
+test cases/common/83 identical target name in subproject/true.py
+test cases/common/83 identical target name in subproject/subprojects/foo/bar.c
+test cases/common/83 identical target name in subproject/subprojects/foo/meson.build
+test cases/common/83 identical target name in subproject/subprojects/foo/true.py
+test cases/common/84 plusassign/meson.build
+test cases/common/85 skip subdir/meson.build
+test cases/common/85 skip subdir/subdir1/meson.build
+test cases/common/85 skip subdir/subdir1/subdir2/meson.build
+test cases/common/86 private include/meson.build
+test cases/common/86 private include/stlib/compiler.py
+test cases/common/86 private include/stlib/foo1.def
+test cases/common/86 private include/stlib/foo2.def
+test cases/common/86 private include/stlib/meson.build
+test cases/common/86 private include/user/libuser.c
+test cases/common/86 private include/user/meson.build
+test cases/common/87 default options/meson.build
+test cases/common/87 default options/subprojects/sub1/meson.build
+test cases/common/87 default options/subprojects/sub1/meson_options.txt
+test cases/common/88 dep fallback/gensrc.py
+test cases/common/88 dep fallback/meson.build
+test cases/common/88 dep fallback/tester.c
+test cases/common/88 dep fallback/subprojects/boblib/bob.c
+test cases/common/88 dep fallback/subprojects/boblib/bob.h
+test cases/common/88 dep fallback/subprojects/boblib/genbob.py
+test cases/common/88 dep fallback/subprojects/boblib/meson.build
+test cases/common/88 dep fallback/subprojects/dummylib/meson.build
+test cases/common/89 default library/ef.cpp
+test cases/common/89 default library/ef.h
+test cases/common/89 default library/eftest.cpp
+test cases/common/89 default library/meson.build
 test cases/common/9 header install/meson.build
 test cases/common/9 header install/rootdir.h
 test cases/common/9 header install/subdir.h
+test cases/common/9 header install/test.json
 test cases/common/9 header install/sub/fileheader.h
 test cases/common/9 header install/sub/meson.build
 test cases/common/9 header install/vanishing_subdir/meson.build
 test cases/common/9 header install/vanishing_subdir/vanished.h
-test cases/common/90 default options/meson.build
-test cases/common/91 dep fallback/gensrc.py
-test cases/common/91 dep fallback/meson.build
-test cases/common/91 dep fallback/tester.c
-test cases/common/91 dep fallback/subprojects/boblib/bob.c
-test cases/common/91 dep fallback/subprojects/boblib/bob.h
-test cases/common/91 dep fallback/subprojects/boblib/genbob.py
-test cases/common/91 dep fallback/subprojects/boblib/meson.build
-test cases/common/91 dep fallback/subprojects/dummylib/meson.build
-test cases/common/92 default library/ef.cpp
-test cases/common/92 default library/ef.h
-test cases/common/92 default library/eftest.cpp
-test cases/common/92 default library/meson.build
-test cases/common/93 selfbuilt custom/data.dat
-test cases/common/93 selfbuilt custom/mainprog.cpp
-test cases/common/93 selfbuilt custom/meson.build
-test cases/common/93 selfbuilt custom/tool.cpp
-test cases/common/94 gen extra/meson.build
-test cases/common/94 gen extra/name.dat
-test cases/common/94 gen extra/name.l
-test cases/common/94 gen extra/plain.c
-test cases/common/94 gen extra/srcgen.py
-test cases/common/94 gen extra/srcgen2.py
-test cases/common/94 gen extra/srcgen3.py
-test cases/common/94 gen extra/upper.c
-test cases/common/95 benchmark/delayer.c
-test cases/common/95 benchmark/meson.build
-test cases/common/96 test workdir/meson.build
-test cases/common/96 test workdir/opener.c
-test cases/common/96 test workdir/subdir/checker.py
-test cases/common/96 test workdir/subdir/meson.build
-test cases/common/97 suites/exe1.c
-test cases/common/97 suites/exe2.c
-test cases/common/97 suites/meson.build
-test cases/common/97 suites/subprojects/sub/meson.build
-test cases/common/97 suites/subprojects/sub/sub1.c
-test cases/common/97 suites/subprojects/sub/sub2.c
-test cases/common/98 threads/meson.build
-test cases/common/98 threads/threadprog.c
-test cases/common/98 threads/threadprog.cpp
-test cases/common/99 manygen/depuser.c
-test cases/common/99 manygen/meson.build
-test cases/common/99 manygen/subdir/funcinfo.def
-test cases/common/99 manygen/subdir/manygen.py
-test cases/common/99 manygen/subdir/meson.build
-test cases/csharp/1 basic/installed_files.txt
+test cases/common/90 gen extra/meson.build
+test cases/common/90 gen extra/name.dat
+test cases/common/90 gen extra/name.l
+test cases/common/90 gen extra/plain.c
+test cases/common/90 gen extra/srcgen.py
+test cases/common/90 gen extra/srcgen2.py
+test cases/common/90 gen extra/srcgen3.py
+test cases/common/90 gen extra/upper.c
+test cases/common/91 benchmark/delayer.c
+test cases/common/91 benchmark/meson.build
+test cases/common/92 test workdir/meson.build
+test cases/common/92 test workdir/opener.c
+test cases/common/92 test workdir/subdir/checker.py
+test cases/common/92 test workdir/subdir/meson.build
+test cases/common/93 suites/exe1.c
+test cases/common/93 suites/exe2.c
+test cases/common/93 suites/meson.build
+test cases/common/93 suites/subprojects/sub/meson.build
+test cases/common/93 suites/subprojects/sub/sub1.c
+test cases/common/93 suites/subprojects/sub/sub2.c
+test cases/common/94 threads/meson.build
+test cases/common/94 threads/threadprog.c
+test cases/common/94 threads/threadprog.cpp
+test cases/common/95 manygen/depuser.c
+test cases/common/95 manygen/meson.build
+test cases/common/95 manygen/subdir/funcinfo.def
+test cases/common/95 manygen/subdir/manygen.py
+test cases/common/95 manygen/subdir/meson.build
+test cases/common/96 stringdef/meson.build
+test cases/common/96 stringdef/stringdef.c
+test cases/common/97 find program path/meson.build
+test cases/common/97 find program path/program.py
+test cases/common/98 subproject subdir/meson.build
+test cases/common/98 subproject subdir/prog.c
+test cases/common/98 subproject subdir/test.json
+test cases/common/98 subproject subdir/subprojects/sub_implicit.wrap
+test cases/common/98 subproject subdir/subprojects/sub/meson.build
+test cases/common/98 subproject subdir/subprojects/sub/lib/meson.build
+test cases/common/98 subproject subdir/subprojects/sub/lib/sub.c
+test cases/common/98 subproject subdir/subprojects/sub/lib/sub.h
+test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build
+test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt
+test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/foo.h
+test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/meson.build
+test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/subsubsub.wrap
+test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/packagefiles/subsubsub-1.0.zip
+test cases/common/98 subproject subdir/subprojects/sub_novar/meson.build
+test cases/common/98 subproject subdir/subprojects/sub_static/meson.build
+test cases/common/99 postconf/meson.build
+test cases/common/99 postconf/postconf.py
+test cases/common/99 postconf/prog.c
+test cases/common/99 postconf/raw.dat
 test cases/csharp/1 basic/meson.build
 test cases/csharp/1 basic/prog.cs
+test cases/csharp/1 basic/test.json
 test cases/csharp/1 basic/text.cs
 test cases/csharp/2 library/helper.cs
-test cases/csharp/2 library/installed_files.txt
 test cases/csharp/2 library/meson.build
 test cases/csharp/2 library/prog.cs
+test cases/csharp/2 library/test.json
 test cases/csharp/3 resource/TestRes.resx
 test cases/csharp/3 resource/meson.build
 test cases/csharp/3 resource/resprog.cs
 test cases/csharp/4 external dep/hello.txt
-test cases/csharp/4 external dep/installed_files.txt
 test cases/csharp/4 external dep/meson.build
 test cases/csharp/4 external dep/prog.cs
+test cases/csharp/4 external dep/test.json
 test cases/cuda/1 simple/meson.build
 test cases/cuda/1 simple/prog.cu
 test cases/cuda/10 cuda dependency/meson.build
@@ -1491,6 +1788,15 @@
 test cases/cuda/12 cuda dependency (mixed)/kernel.cu
 test cases/cuda/12 cuda dependency (mixed)/meson.build
 test cases/cuda/12 cuda dependency (mixed)/prog.cpp
+test cases/cuda/13 cuda compiler setting/meson.build
+test cases/cuda/13 cuda compiler setting/nativefile.ini
+test cases/cuda/13 cuda compiler setting/prog.cu
+test cases/cuda/14 cuda has header symbol/meson.build
+test cases/cuda/15 sanitizer/meson.build
+test cases/cuda/15 sanitizer/prog.cu
+test cases/cuda/16 multistd/lib.cu
+test cases/cuda/16 multistd/main.cu
+test cases/cuda/16 multistd/meson.build
 test cases/cuda/2 split/lib.cu
 test cases/cuda/2 split/main.cpp
 test cases/cuda/2 split/meson.build
@@ -1518,9 +1824,25 @@
 test cases/cuda/8 release/meson.build
 test cases/cuda/9 optimize for space/main.cu
 test cases/cuda/9 optimize for space/meson.build
+test cases/cython/1 basic/cytest.py
+test cases/cython/1 basic/meson.build
+test cases/cython/1 basic/test.json
+test cases/cython/1 basic/libdir/cstorer.pxd
+test cases/cython/1 basic/libdir/meson.build
+test cases/cython/1 basic/libdir/storer.c
+test cases/cython/1 basic/libdir/storer.h
+test cases/cython/1 basic/libdir/storer.pyx
+test cases/cython/2 generated sources/configure.pyx.in
+test cases/cython/2 generated sources/g.in
+test cases/cython/2 generated sources/gen.py
+test cases/cython/2 generated sources/generator.py
+test cases/cython/2 generated sources/meson.build
+test cases/cython/2 generated sources/test.py
+test cases/cython/2 generated sources/libdir/gen.py
+test cases/cython/2 generated sources/libdir/meson.build
 test cases/d/1 simple/app.d
-test cases/d/1 simple/installed_files.txt
 test cases/d/1 simple/meson.build
+test cases/d/1 simple/test.json
 test cases/d/1 simple/utils.d
 test cases/d/10 d cpp/cppmain.cpp
 test cases/d/10 d cpp/dmain.d
@@ -1529,33 +1851,40 @@
 test cases/d/10 d cpp/meson.build
 test cases/d/11 dub/meson.build
 test cases/d/11 dub/test.d
+test cases/d/12 root include directory/meson.build
+test cases/d/12 root include directory/some/meson.build
+test cases/d/12 root include directory/some/dlang/code.d
+test cases/d/12 root include directory/some/dlang/meson.build
 test cases/d/2 static library/app.d
-test cases/d/2 static library/installed_files.txt
 test cases/d/2 static library/libstuff.d
 test cases/d/2 static library/meson.build
+test cases/d/2 static library/test.json
 test cases/d/3 shared library/app.d
-test cases/d/3 shared library/installed_files.txt
 test cases/d/3 shared library/libstuff.d
 test cases/d/3 shared library/libstuff.di
+test cases/d/3 shared library/lld-test.py
 test cases/d/3 shared library/meson.build
-test cases/d/4 library versions/installed_files.txt
+test cases/d/3 shared library/test.json
+test cases/d/3 shared library/sub/libstuff.d
+test cases/d/3 shared library/sub/meson.build
 test cases/d/4 library versions/lib.d
 test cases/d/4 library versions/meson.build
+test cases/d/4 library versions/test.json
 test cases/d/5 mixed/app.d
-test cases/d/5 mixed/installed_files.txt
 test cases/d/5 mixed/libstuff.c
 test cases/d/5 mixed/meson.build
+test cases/d/5 mixed/test.json
 test cases/d/6 unittest/app.d
-test cases/d/6 unittest/installed_files.txt
 test cases/d/6 unittest/meson.build
 test cases/d/6 unittest/second_unit.d
+test cases/d/6 unittest/test.json
 test cases/d/7 multilib/app.d
-test cases/d/7 multilib/installed_files.txt
 test cases/d/7 multilib/meson.build
 test cases/d/7 multilib/say1.d
 test cases/d/7 multilib/say1.di
 test cases/d/7 multilib/say2.d
 test cases/d/7 multilib/say2.di
+test cases/d/7 multilib/test.json
 test cases/d/8 has multi arguments/meson.build
 test cases/d/9 features/app.d
 test cases/d/9 features/extra.d
@@ -1580,6 +1909,8 @@
 test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt
 test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp
 test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp
+test cases/failing build/5 failed pickled/false.py
+test cases/failing build/5 failed pickled/meson.build
 test cases/failing test/1 trivial/main.c
 test cases/failing test/1 trivial/meson.build
 test cases/failing test/2 signal/main.c
@@ -1591,195 +1922,356 @@
 test cases/failing test/4 hard error/meson.build
 test cases/failing test/5 tap tests/meson.build
 test cases/failing test/5 tap tests/tester.c
+test cases/failing test/5 tap tests/tester_with_status.c
 test cases/failing test/6 xpass/meson.build
 test cases/failing test/6 xpass/xpass.c
 test cases/failing/1 project not first/meson.build
 test cases/failing/1 project not first/prog.c
+test cases/failing/1 project not first/test.json
 test cases/failing/10 out of bounds/meson.build
+test cases/failing/10 out of bounds/test.json
+test cases/failing/100 no lang/main.c
+test cases/failing/100 no lang/meson.build
+test cases/failing/100 no lang/test.json
+test cases/failing/101 no glib-compile-resources/meson.build
+test cases/failing/101 no glib-compile-resources/test.json
+test cases/failing/101 no glib-compile-resources/trivial.gresource.xml
+test cases/failing/102 number in combo/meson.build
+test cases/failing/102 number in combo/nativefile.ini
+test cases/failing/102 number in combo/test.json
+test cases/failing/103 bool in combo/meson.build
+test cases/failing/103 bool in combo/meson_options.txt
+test cases/failing/103 bool in combo/nativefile.ini
+test cases/failing/103 bool in combo/test.json
+test cases/failing/104 compiler no lang/meson.build
+test cases/failing/104 compiler no lang/test.json
+test cases/failing/105 no fallback/meson.build
+test cases/failing/105 no fallback/test.json
+test cases/failing/105 no fallback/subprojects/foob/meson.build
+test cases/failing/106 feature require/meson.build
+test cases/failing/106 feature require/meson_options.txt
+test cases/failing/106 feature require/test.json
+test cases/failing/107 feature require.bis/meson.build
+test cases/failing/107 feature require.bis/meson_options.txt
+test cases/failing/107 feature require.bis/test.json
+test cases/failing/108 no build get_external_property/meson.build
+test cases/failing/108 no build get_external_property/test.json
+test cases/failing/109 enter subdir twice/meson.build
+test cases/failing/109 enter subdir twice/test.json
+test cases/failing/109 enter subdir twice/sub/meson.build
 test cases/failing/11 object arithmetic/meson.build
+test cases/failing/11 object arithmetic/test.json
+test cases/failing/111 invalid fstring/meson.build
+test cases/failing/111 invalid fstring/test.json
+test cases/failing/111 invalid fstring/109 invalid fstring/meson.build
+test cases/failing/111 invalid fstring/109 invalid fstring/test.json
+test cases/failing/112 compiler argument checking/meson.build
+test cases/failing/112 compiler argument checking/test.json
+test cases/failing/113 empty fallback/meson.build
+test cases/failing/113 empty fallback/test.json
+test cases/failing/113 empty fallback/subprojects/foo/meson.build
+test cases/failing/114 cmake executable dependency/meson.build
+test cases/failing/114 cmake executable dependency/test.json
+test cases/failing/114 cmake executable dependency/subprojects/cmlib/CMakeLists.txt
+test cases/failing/114 cmake executable dependency/subprojects/cmlib/main.c
+test cases/failing/115 allow_fallback with fallback/meson.build
+test cases/failing/115 allow_fallback with fallback/test.json
+test cases/failing/116 nonsensical bindgen/meson.build
+test cases/failing/116 nonsensical bindgen/test.json
+test cases/failing/116 nonsensical bindgen/src/header.h
+test cases/failing/116 nonsensical bindgen/src/source.c
+test cases/failing/117 run_target in test/meson.build
+test cases/failing/117 run_target in test/test.json
+test cases/failing/117 run_target in test/trivial.c
+test cases/failing/118 run_target in add_install_script/meson.build
+test cases/failing/118 run_target in add_install_script/test.json
+test cases/failing/118 run_target in add_install_script/trivial.c
+test cases/failing/119 pathsep in install_symlink/meson.build
+test cases/failing/119 pathsep in install_symlink/test.json
 test cases/failing/12 string arithmetic/meson.build
+test cases/failing/12 string arithmetic/test.json
 test cases/failing/13 array arithmetic/meson.build
+test cases/failing/13 array arithmetic/test.json
 test cases/failing/14 invalid option name/meson.build
 test cases/failing/14 invalid option name/meson_options.txt
+test cases/failing/14 invalid option name/test.json
 test cases/failing/15 kwarg before arg/meson.build
 test cases/failing/15 kwarg before arg/prog.c
+test cases/failing/15 kwarg before arg/test.json
 test cases/failing/16 extract from subproject/main.c
 test cases/failing/16 extract from subproject/meson.build
+test cases/failing/16 extract from subproject/test.json
 test cases/failing/16 extract from subproject/subprojects/sub_project/meson.build
 test cases/failing/16 extract from subproject/subprojects/sub_project/sub_lib.c
 test cases/failing/17 same target/file.c
 test cases/failing/17 same target/meson.build
+test cases/failing/17 same target/test.json
 test cases/failing/18 wrong plusassign/meson.build
+test cases/failing/18 wrong plusassign/test.json
 test cases/failing/19 target clash/clash.c
 test cases/failing/19 target clash/meson.build
+test cases/failing/19 target clash/test.json
 test cases/failing/2 missing file/meson.build
+test cases/failing/2 missing file/test.json
 test cases/failing/20 version/meson.build
+test cases/failing/20 version/test.json
 test cases/failing/21 subver/meson.build
+test cases/failing/21 subver/test.json
 test cases/failing/21 subver/subprojects/foo/meson.build
 test cases/failing/22 assert/meson.build
+test cases/failing/22 assert/test.json
 test cases/failing/23 rel testdir/meson.build
 test cases/failing/23 rel testdir/simple.c
+test cases/failing/23 rel testdir/test.json
 test cases/failing/24 int conversion/meson.build
+test cases/failing/24 int conversion/test.json
 test cases/failing/25 badlang/meson.build
+test cases/failing/25 badlang/test.json
 test cases/failing/26 output subdir/foo.in
 test cases/failing/26 output subdir/meson.build
+test cases/failing/26 output subdir/test.json
 test cases/failing/26 output subdir/subdir/dummy.txt
 test cases/failing/27 noprog use/meson.build
+test cases/failing/27 noprog use/test.json
 test cases/failing/28 no crossprop/meson.build
+test cases/failing/28 no crossprop/test.json
 test cases/failing/29 nested ternary/meson.build
+test cases/failing/29 nested ternary/test.json
 test cases/failing/3 missing subdir/meson.build
+test cases/failing/3 missing subdir/test.json
+test cases/failing/30 invalid man extension/foo.a1
 test cases/failing/30 invalid man extension/meson.build
+test cases/failing/30 invalid man extension/test.json
+test cases/failing/31 no man extension/foo
 test cases/failing/31 no man extension/meson.build
+test cases/failing/31 no man extension/test.json
 test cases/failing/32 exe static shared/meson.build
 test cases/failing/32 exe static shared/prog.c
 test cases/failing/32 exe static shared/shlib2.c
 test cases/failing/32 exe static shared/stat.c
+test cases/failing/32 exe static shared/test.json
 test cases/failing/33 non-root subproject/meson.build
+test cases/failing/33 non-root subproject/test.json
 test cases/failing/33 non-root subproject/some/meson.build
 test cases/failing/34 dependency not-required then required/meson.build
+test cases/failing/34 dependency not-required then required/test.json
 test cases/failing/35 project argument after target/exe.c
 test cases/failing/35 project argument after target/meson.build
+test cases/failing/35 project argument after target/test.json
 test cases/failing/36 pkgconfig dependency impossible conditions/meson.build
+test cases/failing/36 pkgconfig dependency impossible conditions/test.json
 test cases/failing/37 has function external dependency/meson.build
 test cases/failing/37 has function external dependency/mylib.c
+test cases/failing/37 has function external dependency/test.json
 test cases/failing/38 libdir must be inside prefix/meson.build
+test cases/failing/38 libdir must be inside prefix/test.json
 test cases/failing/39 prefix absolute/meson.build
+test cases/failing/39 prefix absolute/test.json
 test cases/failing/4 missing meson.build/meson.build
+test cases/failing/4 missing meson.build/test.json
 test cases/failing/4 missing meson.build/subdir/dummy.txt
 test cases/failing/40 kwarg assign/dummy.c
 test cases/failing/40 kwarg assign/meson.build
 test cases/failing/40 kwarg assign/prog.c
+test cases/failing/40 kwarg assign/test.json
 test cases/failing/41 custom target plainname many inputs/1.txt
 test cases/failing/41 custom target plainname many inputs/2.txt
 test cases/failing/41 custom target plainname many inputs/catfiles.py
 test cases/failing/41 custom target plainname many inputs/meson.build
+test cases/failing/41 custom target plainname many inputs/test.json
 test cases/failing/42 custom target outputs not matching install_dirs/generator.py
-test cases/failing/42 custom target outputs not matching install_dirs/installed_files.txt
 test cases/failing/42 custom target outputs not matching install_dirs/meson.build
+test cases/failing/42 custom target outputs not matching install_dirs/test.json
 test cases/failing/43 project name colon/meson.build
+test cases/failing/43 project name colon/test.json
 test cases/failing/44 abs subdir/meson.build
+test cases/failing/44 abs subdir/test.json
 test cases/failing/44 abs subdir/bob/meson.build
 test cases/failing/45 abspath to srcdir/meson.build
+test cases/failing/45 abspath to srcdir/test.json
 test cases/failing/46 pkgconfig variables reserved/meson.build
 test cases/failing/46 pkgconfig variables reserved/simple.c
 test cases/failing/46 pkgconfig variables reserved/simple.h
+test cases/failing/46 pkgconfig variables reserved/test.json
 test cases/failing/47 pkgconfig variables zero length/meson.build
 test cases/failing/47 pkgconfig variables zero length/simple.c
 test cases/failing/47 pkgconfig variables zero length/simple.h
+test cases/failing/47 pkgconfig variables zero length/test.json
 test cases/failing/48 pkgconfig variables zero length value/meson.build
 test cases/failing/48 pkgconfig variables zero length value/simple.c
 test cases/failing/48 pkgconfig variables zero length value/simple.h
+test cases/failing/48 pkgconfig variables zero length value/test.json
 test cases/failing/49 pkgconfig variables not key value/meson.build
 test cases/failing/49 pkgconfig variables not key value/simple.c
 test cases/failing/49 pkgconfig variables not key value/simple.h
+test cases/failing/49 pkgconfig variables not key value/test.json
 test cases/failing/5 misplaced option/meson.build
+test cases/failing/5 misplaced option/test.json
 test cases/failing/50 executable comparison/meson.build
 test cases/failing/50 executable comparison/prog.c
+test cases/failing/50 executable comparison/test.json
 test cases/failing/51 inconsistent comparison/meson.build
+test cases/failing/51 inconsistent comparison/test.json
 test cases/failing/52 slashname/meson.build
+test cases/failing/52 slashname/test.json
 test cases/failing/52 slashname/sub/meson.build
 test cases/failing/52 slashname/sub/prog.c
 test cases/failing/53 reserved meson prefix/meson.build
+test cases/failing/53 reserved meson prefix/test.json
 test cases/failing/53 reserved meson prefix/meson-foo/meson.build
 test cases/failing/54 wrong shared crate type/foo.rs
 test cases/failing/54 wrong shared crate type/meson.build
+test cases/failing/54 wrong shared crate type/test.json
 test cases/failing/55 wrong static crate type/foo.rs
 test cases/failing/55 wrong static crate type/meson.build
+test cases/failing/55 wrong static crate type/test.json
 test cases/failing/56 or on new line/meson.build
 test cases/failing/56 or on new line/meson_options.txt
-test cases/failing/57 kwarg in module/meson.build
-test cases/failing/58 link with executable/meson.build
-test cases/failing/58 link with executable/module.c
-test cases/failing/58 link with executable/prog.c
-test cases/failing/59 assign custom target index/meson.build
+test cases/failing/56 or on new line/test.json
+test cases/failing/57 link with executable/meson.build
+test cases/failing/57 link with executable/module.c
+test cases/failing/57 link with executable/prog.c
+test cases/failing/57 link with executable/test.json
+test cases/failing/58 assign custom target index/meson.build
+test cases/failing/58 assign custom target index/test.json
+test cases/failing/59 getoption prefix/meson.build
+test cases/failing/59 getoption prefix/test.json
+test cases/failing/59 getoption prefix/subprojects/abc/meson.build
+test cases/failing/59 getoption prefix/subprojects/abc/meson_options.txt
 test cases/failing/6 missing incdir/meson.build
-test cases/failing/60 getoption prefix/meson.build
-test cases/failing/60 getoption prefix/subprojects/abc/meson.build
-test cases/failing/60 getoption prefix/subprojects/abc/meson_options.txt
-test cases/failing/61 bad option argument/meson.build
-test cases/failing/61 bad option argument/meson_options.txt
-test cases/failing/62 subproj filegrab/meson.build
-test cases/failing/62 subproj filegrab/prog.c
-test cases/failing/62 subproj filegrab/subprojects/a/meson.build
-test cases/failing/63 grab subproj/meson.build
-test cases/failing/63 grab subproj/subprojects/foo/meson.build
-test cases/failing/63 grab subproj/subprojects/foo/sub.c
-test cases/failing/64 grab sibling/meson.build
-test cases/failing/64 grab sibling/subprojects/a/meson.build
-test cases/failing/64 grab sibling/subprojects/b/meson.build
-test cases/failing/64 grab sibling/subprojects/b/sneaky.c
-test cases/failing/65 string as link target/meson.build
-test cases/failing/65 string as link target/prog.c
-test cases/failing/66 dependency not-found and required/meson.build
-test cases/failing/67 subproj different versions/main.c
-test cases/failing/67 subproj different versions/meson.build
-test cases/failing/67 subproj different versions/subprojects/a/a.c
-test cases/failing/67 subproj different versions/subprojects/a/a.h
-test cases/failing/67 subproj different versions/subprojects/a/meson.build
-test cases/failing/67 subproj different versions/subprojects/b/b.c
-test cases/failing/67 subproj different versions/subprojects/b/b.h
-test cases/failing/67 subproj different versions/subprojects/b/meson.build
-test cases/failing/67 subproj different versions/subprojects/c/c.h
-test cases/failing/67 subproj different versions/subprojects/c/meson.build
-test cases/failing/68 wrong boost module/meson.build
-test cases/failing/69 install_data rename bad size/file1.txt
-test cases/failing/69 install_data rename bad size/file2.txt
-test cases/failing/69 install_data rename bad size/meson.build
+test cases/failing/6 missing incdir/test.json
+test cases/failing/60 bad option argument/meson.build
+test cases/failing/60 bad option argument/meson_options.txt
+test cases/failing/60 bad option argument/test.json
+test cases/failing/61 subproj filegrab/meson.build
+test cases/failing/61 subproj filegrab/prog.c
+test cases/failing/61 subproj filegrab/test.json
+test cases/failing/61 subproj filegrab/subprojects/a/meson.build
+test cases/failing/62 grab subproj/meson.build
+test cases/failing/62 grab subproj/test.json
+test cases/failing/62 grab subproj/subprojects/foo/meson.build
+test cases/failing/62 grab subproj/subprojects/foo/sub.c
+test cases/failing/63 grab sibling/meson.build
+test cases/failing/63 grab sibling/test.json
+test cases/failing/63 grab sibling/subprojects/a/meson.build
+test cases/failing/63 grab sibling/subprojects/b/meson.build
+test cases/failing/63 grab sibling/subprojects/b/sneaky.c
+test cases/failing/64 string as link target/meson.build
+test cases/failing/64 string as link target/prog.c
+test cases/failing/64 string as link target/test.json
+test cases/failing/65 dependency not-found and required/meson.build
+test cases/failing/65 dependency not-found and required/test.json
+test cases/failing/66 subproj different versions/main.c
+test cases/failing/66 subproj different versions/meson.build
+test cases/failing/66 subproj different versions/test.json
+test cases/failing/66 subproj different versions/subprojects/a/a.c
+test cases/failing/66 subproj different versions/subprojects/a/a.h
+test cases/failing/66 subproj different versions/subprojects/a/meson.build
+test cases/failing/66 subproj different versions/subprojects/b/b.c
+test cases/failing/66 subproj different versions/subprojects/b/b.h
+test cases/failing/66 subproj different versions/subprojects/b/meson.build
+test cases/failing/66 subproj different versions/subprojects/c/c.h
+test cases/failing/66 subproj different versions/subprojects/c/meson.build
+test cases/failing/67 wrong boost module/meson.build
+test cases/failing/67 wrong boost module/test.json
+test cases/failing/68 install_data rename bad size/file1.txt
+test cases/failing/68 install_data rename bad size/file2.txt
+test cases/failing/68 install_data rename bad size/meson.build
+test cases/failing/68 install_data rename bad size/test.json
+test cases/failing/69 skip only subdir/meson.build
+test cases/failing/69 skip only subdir/test.json
+test cases/failing/69 skip only subdir/subdir/meson.build
 test cases/failing/7 go to subproject/meson.build
+test cases/failing/7 go to subproject/test.json
 test cases/failing/7 go to subproject/subprojects/meson.build
-test cases/failing/70 skip only subdir/meson.build
-test cases/failing/70 skip only subdir/subdir/meson.build
-test cases/failing/71 invalid escape char/meson.build
-test cases/failing/72 dual override/meson.build
-test cases/failing/72 dual override/overrides.py
-test cases/failing/73 override used/meson.build
-test cases/failing/73 override used/other.py
-test cases/failing/73 override used/something.py
-test cases/failing/74 run_command unclean exit/meson.build
-test cases/failing/74 run_command unclean exit/returncode.py
-test cases/failing/75 int literal leading zero/meson.build
-test cases/failing/76 configuration immutable/input
-test cases/failing/76 configuration immutable/meson.build
-test cases/failing/77 link with shared module on osx/meson.build
-test cases/failing/77 link with shared module on osx/module.c
-test cases/failing/77 link with shared module on osx/prog.c
-test cases/failing/78 non ascii in ascii encoded configure file/config9.h.in
-test cases/failing/78 non ascii in ascii encoded configure file/meson.build
-test cases/failing/79 subproj dependency not-found and required/meson.build
+test cases/failing/70 dual override/meson.build
+test cases/failing/70 dual override/overrides.py
+test cases/failing/70 dual override/test.json
+test cases/failing/71 override used/meson.build
+test cases/failing/71 override used/other.py
+test cases/failing/71 override used/something.py
+test cases/failing/71 override used/test.json
+test cases/failing/72 run_command unclean exit/meson.build
+test cases/failing/72 run_command unclean exit/returncode.py
+test cases/failing/72 run_command unclean exit/test.json
+test cases/failing/73 int literal leading zero/meson.build
+test cases/failing/73 int literal leading zero/test.json
+test cases/failing/74 configuration immutable/input
+test cases/failing/74 configuration immutable/meson.build
+test cases/failing/74 configuration immutable/test.json
+test cases/failing/75 link with shared module on osx/meson.build
+test cases/failing/75 link with shared module on osx/module.c
+test cases/failing/75 link with shared module on osx/prog.c
+test cases/failing/75 link with shared module on osx/test.json
+test cases/failing/76 non ascii in ascii encoded configure file/config9.h.in
+test cases/failing/76 non ascii in ascii encoded configure file/meson.build
+test cases/failing/76 non ascii in ascii encoded configure file/test.json
+test cases/failing/77 subproj dependency not-found and required/meson.build
+test cases/failing/77 subproj dependency not-found and required/test.json
+test cases/failing/78 unfound run/meson.build
+test cases/failing/78 unfound run/test.json
+test cases/failing/79 framework dependency with version/meson.build
+test cases/failing/79 framework dependency with version/test.json
 test cases/failing/8 recursive/meson.build
+test cases/failing/8 recursive/test.json
 test cases/failing/8 recursive/subprojects/a/meson.build
 test cases/failing/8 recursive/subprojects/b/meson.build
-test cases/failing/80 unfound run/meson.build
-test cases/failing/81 framework dependency with version/meson.build
-test cases/failing/82 override exe config/foo.c
-test cases/failing/82 override exe config/meson.build
-test cases/failing/83 gl dependency with version/meson.build
-test cases/failing/84 threads dependency with version/meson.build
-test cases/failing/85 gtest dependency with version/meson.build
-test cases/failing/86 dub libray/meson.build
-test cases/failing/87 dub executable/meson.build
-test cases/failing/88 dub compiler/meson.build
-test cases/failing/89 subproj not-found dep/meson.build
-test cases/failing/89 subproj not-found dep/subprojects/somesubproj/meson.build
+test cases/failing/80 override exe config/foo.c
+test cases/failing/80 override exe config/meson.build
+test cases/failing/80 override exe config/test.json
+test cases/failing/81 gl dependency with version/meson.build
+test cases/failing/81 gl dependency with version/test.json
+test cases/failing/82 threads dependency with version/meson.build
+test cases/failing/82 threads dependency with version/test.json
+test cases/failing/83 gtest dependency with version/meson.build
+test cases/failing/83 gtest dependency with version/test.json
+test cases/failing/84 dub libray/meson.build
+test cases/failing/84 dub libray/test.json
+test cases/failing/85 dub executable/meson.build
+test cases/failing/85 dub executable/test.json
+test cases/failing/86 dub compiler/meson.build
+test cases/failing/86 dub compiler/test.json
+test cases/failing/87 subproj not-found dep/meson.build
+test cases/failing/87 subproj not-found dep/test.json
+test cases/failing/87 subproj not-found dep/subprojects/somesubproj/meson.build
+test cases/failing/88 invalid configure file/input
+test cases/failing/88 invalid configure file/meson.build
+test cases/failing/88 invalid configure file/test.json
+test cases/failing/89 kwarg dupe/meson.build
+test cases/failing/89 kwarg dupe/prog.c
+test cases/failing/89 kwarg dupe/test.json
 test cases/failing/9 missing extra file/meson.build
 test cases/failing/9 missing extra file/prog.c
-test cases/failing/90 invalid configure file/input
-test cases/failing/90 invalid configure file/meson.build
-test cases/failing/91 kwarg dupe/meson.build
-test cases/failing/91 kwarg dupe/prog.c
-test cases/failing/92 missing pch file/meson.build
-test cases/failing/92 missing pch file/prog.c
-test cases/failing/93 pch source different folder/meson.build
-test cases/failing/93 pch source different folder/prog.c
-test cases/failing/93 pch source different folder/include/pch.h
-test cases/failing/93 pch source different folder/src/pch.c
-test cases/failing/94 vala without c/meson.build
-test cases/failing/95 unknown config tool/meson.build
-test cases/failing/96 custom target install data/Info.plist.cpp
-test cases/failing/96 custom target install data/meson.build
-test cases/failing/96 custom target install data/preproc.py
-test cases/failing/97 add dict non string key/meson.build
-test cases/failing/98 add dict duplicate keys/meson.build
+test cases/failing/9 missing extra file/test.json
+test cases/failing/90 missing pch file/meson.build
+test cases/failing/90 missing pch file/prog.c
+test cases/failing/90 missing pch file/test.json
+test cases/failing/91 pch source different folder/meson.build
+test cases/failing/91 pch source different folder/prog.c
+test cases/failing/91 pch source different folder/test.json
+test cases/failing/91 pch source different folder/include/pch.h
+test cases/failing/91 pch source different folder/src/pch.c
+test cases/failing/92 unknown config tool/meson.build
+test cases/failing/92 unknown config tool/test.json
+test cases/failing/93 custom target install data/Info.plist.cpp
+test cases/failing/93 custom target install data/meson.build
+test cases/failing/93 custom target install data/preproc.py
+test cases/failing/93 custom target install data/test.json
+test cases/failing/94 add dict non string key/meson.build
+test cases/failing/94 add dict non string key/test.json
+test cases/failing/95 add dict duplicate keys/meson.build
+test cases/failing/95 add dict duplicate keys/test.json
+test cases/failing/96 no host get_external_property/meson.build
+test cases/failing/96 no host get_external_property/test.json
+test cases/failing/97 no native compiler/main.c
+test cases/failing/97 no native compiler/meson.build
+test cases/failing/97 no native compiler/test.json
+test cases/failing/98 subdir parse error/meson.build
+test cases/failing/98 subdir parse error/test.json
+test cases/failing/98 subdir parse error/subdir/meson.build
+test cases/failing/99 invalid option file/meson.build
+test cases/failing/99 invalid option file/meson_options.txt
+test cases/failing/99 invalid option file/test.json
 test cases/fortran/1 basic/meson.build
 test cases/fortran/1 basic/simple.f90
 test cases/fortran/10 find library/gzip.f90
@@ -1802,12 +2294,15 @@
 test cases/fortran/15 include/inc2.f90
 test cases/fortran/15 include/include_hierarchy.f90
 test cases/fortran/15 include/include_syntax.f90
-test cases/fortran/15 include/include_tests.f90
 test cases/fortran/15 include/meson.build
 test cases/fortran/15 include/timestwo.f90
+test cases/fortran/15 include/subprojects/cmake_inc/CMakeLists.txt
+test cases/fortran/15 include/subprojects/cmake_inc/main.f90
+test cases/fortran/15 include/subprojects/cmake_inc/thousand.f90
 test cases/fortran/16 openmp/main.f90
 test cases/fortran/16 openmp/meson.build
 test cases/fortran/17 add_languages/meson.build
+test cases/fortran/18 first_arg/main.f90
 test cases/fortran/18 first_arg/meson.build
 test cases/fortran/19 fortran_std/legacy.f
 test cases/fortran/19 fortran_std/meson.build
@@ -1817,10 +2312,16 @@
 test cases/fortran/19 fortran_std/std95.f90
 test cases/fortran/2 modules/comment_mod.f90
 test cases/fortran/2 modules/meson.build
-test cases/fortran/2 modules/mymod.f90
+test cases/fortran/2 modules/mymod.F90
 test cases/fortran/2 modules/prog.f90
 test cases/fortran/20 buildtype/main.f90
 test cases/fortran/20 buildtype/meson.build
+test cases/fortran/21 install static/main.f90
+test cases/fortran/21 install static/main_lib.f90
+test cases/fortran/21 install static/meson.build
+test cases/fortran/21 install static/test.json
+test cases/fortran/21 install static/subprojects/static_hello/meson.build
+test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90
 test cases/fortran/3 module procedure/meson.build
 test cases/fortran/3 module procedure/use_syntax.f90
 test cases/fortran/4 self dependency/meson.build
@@ -1837,12 +2338,14 @@
 test cases/fortran/7 generated/meson.build
 test cases/fortran/7 generated/mod1.fpp
 test cases/fortran/7 generated/mod2.fpp
+test cases/fortran/7 generated/mod3.f90
 test cases/fortran/7 generated/prog.f90
 test cases/fortran/8 module names/meson.build
 test cases/fortran/8 module names/mod1.f90
 test cases/fortran/8 module names/mod2.f90
 test cases/fortran/8 module names/test.f90
 test cases/fortran/9 cpp/fortran.f
+test cases/fortran/9 cpp/main.c
 test cases/fortran/9 cpp/main.cpp
 test cases/fortran/9 cpp/meson.build
 test cases/fpga/1 simple/meson.build
@@ -1851,20 +2354,27 @@
 test cases/frameworks/1 boost/extralib.cpp
 test cases/frameworks/1 boost/linkexe.cc
 test cases/frameworks/1 boost/meson.build
+test cases/frameworks/1 boost/meson_options.txt
 test cases/frameworks/1 boost/nomod.cpp
 test cases/frameworks/1 boost/python_module.cpp
+test cases/frameworks/1 boost/test.json
 test cases/frameworks/1 boost/test_python_module.py
 test cases/frameworks/1 boost/unit_test.cpp
 test cases/frameworks/1 boost/partial_dep/foo.cpp
 test cases/frameworks/1 boost/partial_dep/foo.hpp
 test cases/frameworks/1 boost/partial_dep/main.cpp
 test cases/frameworks/1 boost/partial_dep/meson.build
-test cases/frameworks/10 gtk-doc/installed_files.txt
+test cases/frameworks/10 gtk-doc/foo.c
 test cases/frameworks/10 gtk-doc/meson.build
+test cases/frameworks/10 gtk-doc/test.json
 test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml
 test cases/frameworks/10 gtk-doc/doc/meson.build
 test cases/frameworks/10 gtk-doc/doc/version.xml.in
+test cases/frameworks/10 gtk-doc/doc/foobar1/baz.jpg
+test cases/frameworks/10 gtk-doc/doc/foobar1/baz.png.in
 test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml
+test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-sections.txt
+test cases/frameworks/10 gtk-doc/doc/foobar1/foobar.types
 test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build
 test cases/frameworks/10 gtk-doc/doc/foobar2/foobar-docs.sgml
 test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build
@@ -1876,8 +2386,8 @@
 test cases/frameworks/10 gtk-doc/include/foo.h
 test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py
 test cases/frameworks/10 gtk-doc/include/meson.build
-test cases/frameworks/11 gir subproject/installed_files.txt
 test cases/frameworks/11 gir subproject/meson.build
+test cases/frameworks/11 gir subproject/test.json
 test cases/frameworks/11 gir subproject/gir/meson-subsample.c
 test cases/frameworks/11 gir subproject/gir/meson-subsample.h
 test cases/frameworks/11 gir subproject/gir/meson.build
@@ -1886,8 +2396,8 @@
 test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.c
 test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.h
 test cases/frameworks/11 gir subproject/subprojects/mesongir/meson.build
-test cases/frameworks/12 multiple gir/installed_files.txt
 test cases/frameworks/12 multiple gir/meson.build
+test cases/frameworks/12 multiple gir/test.json
 test cases/frameworks/12 multiple gir/gir/meson-subsample.c
 test cases/frameworks/12 multiple gir/gir/meson-subsample.h
 test cases/frameworks/12 multiple gir/gir/meson.build
@@ -1895,79 +2405,143 @@
 test cases/frameworks/12 multiple gir/mesongir/meson-sample.c
 test cases/frameworks/12 multiple gir/mesongir/meson-sample.h.in
 test cases/frameworks/12 multiple gir/mesongir/meson.build
-test cases/frameworks/13 yelp/installed_files.txt
 test cases/frameworks/13 yelp/meson.build
+test cases/frameworks/13 yelp/test.json
 test cases/frameworks/13 yelp/help/LINGUAS
 test cases/frameworks/13 yelp/help/meson.build
 test cases/frameworks/13 yelp/help/C/index.page
+test cases/frameworks/13 yelp/help/C/index2.page
+test cases/frameworks/13 yelp/help/C/index3.page
 test cases/frameworks/13 yelp/help/C/media/test.txt
 test cases/frameworks/13 yelp/help/de/de.po
 test cases/frameworks/13 yelp/help/es/es.po
 test cases/frameworks/13 yelp/help/es/media/test.txt
-test cases/frameworks/14 doxygen/installed_files.txt
 test cases/frameworks/14 doxygen/meson.build
+test cases/frameworks/14 doxygen/test.json
 test cases/frameworks/14 doxygen/doc/Doxyfile.in
 test cases/frameworks/14 doxygen/doc/meson.build
 test cases/frameworks/14 doxygen/include/comedian.h
 test cases/frameworks/14 doxygen/include/spede.h
 test cases/frameworks/14 doxygen/src/spede.cpp
 test cases/frameworks/15 llvm/meson.build
+test cases/frameworks/15 llvm/meson_options.txt
 test cases/frameworks/15 llvm/sum.c
+test cases/frameworks/15 llvm/test.json
 test cases/frameworks/16 sdl2/meson.build
+test cases/frameworks/16 sdl2/meson_options.txt
 test cases/frameworks/16 sdl2/sdl2prog.c
+test cases/frameworks/16 sdl2/test.json
 test cases/frameworks/17 mpi/main.c
 test cases/frameworks/17 mpi/main.cpp
 test cases/frameworks/17 mpi/main.f90
 test cases/frameworks/17 mpi/meson.build
+test cases/frameworks/17 mpi/meson_options.txt
+test cases/frameworks/17 mpi/test.json
 test cases/frameworks/18 vulkan/meson.build
+test cases/frameworks/18 vulkan/test.json
 test cases/frameworks/18 vulkan/vulkanprog.c
 test cases/frameworks/19 pcap/meson.build
 test cases/frameworks/19 pcap/pcap_prog.c
+test cases/frameworks/19 pcap/test.json
 test cases/frameworks/2 gtest/meson.build
 test cases/frameworks/2 gtest/test.cc
+test cases/frameworks/2 gtest/test.json
 test cases/frameworks/2 gtest/test_nomain.cc
 test cases/frameworks/20 cups/cups_prog.c
 test cases/frameworks/20 cups/meson.build
+test cases/frameworks/20 cups/test.json
 test cases/frameworks/21 libwmf/libwmf_prog.c
 test cases/frameworks/21 libwmf/meson.build
+test cases/frameworks/21 libwmf/test.json
 test cases/frameworks/22 gir link order/meson-sample.c
 test cases/frameworks/22 gir link order/meson-sample.h
 test cases/frameworks/22 gir link order/meson.build
+test cases/frameworks/22 gir link order/test.json
 test cases/frameworks/22 gir link order/fake-gthread/fake-gthread.c
 test cases/frameworks/22 gir link order/fake-gthread/fake-gthread.h
 test cases/frameworks/22 gir link order/fake-gthread/meson.build
 test cases/frameworks/22 gir link order/get-prgname/get-prgname.c
 test cases/frameworks/22 gir link order/get-prgname/get-prgname.h
 test cases/frameworks/22 gir link order/get-prgname/meson.build
-test cases/frameworks/23 hotdoc/installed_files.txt
 test cases/frameworks/23 hotdoc/meson.build
+test cases/frameworks/23 hotdoc/test.json
 test cases/frameworks/23 hotdoc/doc/index.md
 test cases/frameworks/23 hotdoc/doc/meson.build
 test cases/frameworks/23 hotdoc/doc/sitemap.txt
 test cases/frameworks/24 libgcrypt/libgcrypt_prog.c
 test cases/frameworks/24 libgcrypt/meson.build
+test cases/frameworks/24 libgcrypt/test.json
 test cases/frameworks/25 hdf5/main.c
 test cases/frameworks/25 hdf5/main.cpp
 test cases/frameworks/25 hdf5/main.f90
 test cases/frameworks/25 hdf5/meson.build
+test cases/frameworks/25 hdf5/meson_options.txt
+test cases/frameworks/25 hdf5/test.json
 test cases/frameworks/26 netcdf/main.c
 test cases/frameworks/26 netcdf/main.cpp
 test cases/frameworks/26 netcdf/main.f90
 test cases/frameworks/26 netcdf/meson.build
+test cases/frameworks/26 netcdf/test.json
 test cases/frameworks/27 gpgme/gpgme_prog.c
 test cases/frameworks/27 gpgme/meson.build
+test cases/frameworks/27 gpgme/test.json
 test cases/frameworks/28 gir link order 2/meson-sample.c
 test cases/frameworks/28 gir link order 2/meson-sample.h
 test cases/frameworks/28 gir link order 2/meson.build
+test cases/frameworks/28 gir link order 2/test.json
 test cases/frameworks/28 gir link order 2/samelibname/meson.build
 test cases/frameworks/29 blocks/main.c
 test cases/frameworks/29 blocks/meson.build
+test cases/frameworks/29 blocks/test.json
 test cases/frameworks/3 gmock/gmocktest.cc
 test cases/frameworks/3 gmock/meson.build
+test cases/frameworks/3 gmock/test.json
 test cases/frameworks/30 scalapack/main.c
 test cases/frameworks/30 scalapack/main.f90
 test cases/frameworks/30 scalapack/meson.build
+test cases/frameworks/30 scalapack/test.json
 test cases/frameworks/30 scalapack/cmake/FindSCALAPACK.cmake
+test cases/frameworks/31 curses/main.c
+test cases/frameworks/31 curses/meson.build
+test cases/frameworks/31 curses/meson_options.txt
+test cases/frameworks/31 curses/test.json
+test cases/frameworks/32 boost root/meson.build
+test cases/frameworks/32 boost root/nativefile.ini.in
+test cases/frameworks/32 boost root/boost/include/boost/version.hpp
+test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x32-0_1.lib
+test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x64-0_1.lib
+test cases/frameworks/32 boost root/boost/lib/libboost_regex.so.0.1.0
+test cases/frameworks/33 boost split root/meson.build
+test cases/frameworks/33 boost split root/nativefile.ini.in
+test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp
+test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x32-0_2.lib
+test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x64-0_2.lib
+test cases/frameworks/33 boost split root/boost/lib/libboost_regex.so.0.2.0
+test cases/frameworks/34 gir static lib/meson.build
+test cases/frameworks/34 gir static lib/test.json
+test cases/frameworks/34 gir static lib/statichelper/meson-sample.c
+test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in
+test cases/frameworks/34 gir static lib/statichelper/meson.build
+test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c
+test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h
+test cases/frameworks/34 gir static lib/subdir/gir/meson.build
+test cases/frameworks/34 gir static lib/subdir/gir/prog.c
+test cases/frameworks/35 boost symlinks/meson.build
+test cases/frameworks/35 boost symlinks/nativefile.ini.in
+test cases/frameworks/35 boost symlinks/boost/Cellar/boost-python/0.3.0/lib/boost_python-vc142-mt-gd-x32-0_3.lib
+test cases/frameworks/35 boost symlinks/boost/Cellar/boost-python/0.3.0/lib/boost_python-vc142-mt-gd-x64-0_3.lib
+test cases/frameworks/35 boost symlinks/boost/Cellar/boost-python/0.3.0/lib/libboost_python.so.0.3.0
+test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/include/boost/version.hpp
+test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/lib/boost_regex-vc142-mt-gd-x32-0_3.lib
+test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/lib/boost_regex-vc142-mt-gd-x64-0_3.lib
+test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/lib/libboost_regex.so.0.3.0
+test cases/frameworks/35 boost symlinks/boost/include/boost/version.hpp
+test cases/frameworks/35 boost symlinks/boost/lib/boost_python-vc142-mt-gd-x32-0_3.lib
+test cases/frameworks/35 boost symlinks/boost/lib/boost_python-vc142-mt-gd-x64-0_3.lib
+test cases/frameworks/35 boost symlinks/boost/lib/boost_regex-vc142-mt-gd-x32-0_3.lib
+test cases/frameworks/35 boost symlinks/boost/lib/boost_regex-vc142-mt-gd-x64-0_3.lib
+test cases/frameworks/35 boost symlinks/boost/lib/libboost_python.so.0.3.0
+test cases/frameworks/35 boost symlinks/boost/lib/libboost_regex.so.0.3.0
 test cases/frameworks/4 qt/main.cpp
 test cases/frameworks/4 qt/mainWindow.cpp
 test cases/frameworks/4 qt/mainWindow.h
@@ -1977,11 +2551,16 @@
 test cases/frameworks/4 qt/meson.build
 test cases/frameworks/4 qt/meson_options.txt
 test cases/frameworks/4 qt/q5core.cpp
+test cases/frameworks/4 qt/qt4_lang.qrc
 test cases/frameworks/4 qt/qt4core_fr.ts
+test cases/frameworks/4 qt/qt4embedded_fr.ts
+test cases/frameworks/4 qt/qt5_lang.qrc
 test cases/frameworks/4 qt/qt5core_fr.ts
+test cases/frameworks/4 qt/qt5embedded_fr.ts
 test cases/frameworks/4 qt/qtinterface.cpp
 test cases/frameworks/4 qt/stuff.qrc
 test cases/frameworks/4 qt/stuff2.qrc
+test cases/frameworks/4 qt/test.json
 test cases/frameworks/4 qt/thing.png
 test cases/frameworks/4 qt/thing2.png
 test cases/frameworks/4 qt/plugin/plugin.cpp
@@ -1997,6 +2576,7 @@
 test cases/frameworks/5 protocol buffers/defs.proto
 test cases/frameworks/5 protocol buffers/main.cpp
 test cases/frameworks/5 protocol buffers/meson.build
+test cases/frameworks/5 protocol buffers/test.json
 test cases/frameworks/5 protocol buffers/asubdir/defs.proto
 test cases/frameworks/5 protocol buffers/asubdir/main.cpp
 test cases/frameworks/5 protocol buffers/asubdir/meson.build
@@ -2006,11 +2586,14 @@
 test cases/frameworks/5 protocol buffers/withpath/pathprog.cpp
 test cases/frameworks/5 protocol buffers/withpath/com/mesonbuild/simple.proto
 test cases/frameworks/5 protocol buffers/withpath/com/mesonbuild/subsite/complex.proto
-test cases/frameworks/6 gettext/installed_files.txt
 test cases/frameworks/6 gettext/meson.build
+test cases/frameworks/6 gettext/meson_options.txt
+test cases/frameworks/6 gettext/test.json
 test cases/frameworks/6 gettext/data/meson.build
 test cases/frameworks/6 gettext/data/test.desktop.in
 test cases/frameworks/6 gettext/data/test2.desktop.in
+test cases/frameworks/6 gettext/data/test5.desktop.in.in
+test cases/frameworks/6 gettext/data/test6.desktop.in.in
 test cases/frameworks/6 gettext/data/data3/meson.build
 test cases/frameworks/6 gettext/data/data3/test.desktop.in
 test cases/frameworks/6 gettext/data2/meson.build
@@ -2027,14 +2610,15 @@
 test cases/frameworks/6 gettext/po/ru.po
 test cases/frameworks/6 gettext/src/intlmain.c
 test cases/frameworks/6 gettext/src/meson.build
-test cases/frameworks/7 gnome/installed_files.txt
 test cases/frameworks/7 gnome/meson.build
+test cases/frameworks/7 gnome/test.json
 test cases/frameworks/7 gnome/gdbus/gdbusprog.c
 test cases/frameworks/7 gnome/gdbus/meson.build
 test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml
-test cases/frameworks/7 gnome/genmarshal/main.c
+test cases/frameworks/7 gnome/genmarshal/main.c.in
 test cases/frameworks/7 gnome/genmarshal/marshaller.list
 test cases/frameworks/7 gnome/genmarshal/meson.build
+test cases/frameworks/7 gnome/gir/copy.py
 test cases/frameworks/7 gnome/gir/meson-sample.c
 test cases/frameworks/7 gnome/gir/meson-sample.h
 test cases/frameworks/7 gnome/gir/meson-sample2.c
@@ -2048,6 +2632,9 @@
 test cases/frameworks/7 gnome/gir/dep1/dep2/dep2.c
 test cases/frameworks/7 gnome/gir/dep1/dep2/dep2.h
 test cases/frameworks/7 gnome/gir/dep1/dep2/meson.build
+test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c
+test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h
+test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build
 test cases/frameworks/7 gnome/mkenums/enums.c.in
 test cases/frameworks/7 gnome/mkenums/enums.h.in
 test cases/frameworks/7 gnome/mkenums/enums2.c.in
@@ -2080,13 +2667,15 @@
 test cases/frameworks/8 flex/meson.build
 test cases/frameworks/8 flex/parser.y
 test cases/frameworks/8 flex/prog.c
+test cases/frameworks/8 flex/test.json
 test cases/frameworks/8 flex/test.txt
+test cases/frameworks/8 flex/testfile
 test cases/frameworks/9 wxwidgets/mainwin.h
 test cases/frameworks/9 wxwidgets/meson.build
 test cases/frameworks/9 wxwidgets/wxprog.cpp
 test cases/frameworks/9 wxwidgets/wxstc.cpp
-test cases/java/1 basic/installed_files.txt
 test cases/java/1 basic/meson.build
+test cases/java/1 basic/test.json
 test cases/java/1 basic/com/mesonbuild/Simple.java
 test cases/java/2 subdir/meson.build
 test cases/java/2 subdir/sub/meson.build
@@ -2113,16 +2702,24 @@
 test cases/java/8 codegen custom target/com/mesonbuild/Simple.java
 test cases/java/8 codegen custom target/com/mesonbuild/TextPrinter.java
 test cases/java/8 codegen custom target/com/mesonbuild/meson.build
-test cases/kconfig/1 basic/.config
-test cases/kconfig/1 basic/meson.build
-test cases/kconfig/2 subdir/.config
-test cases/kconfig/2 subdir/meson.build
-test cases/kconfig/2 subdir/dir/meson.build
-test cases/kconfig/3 load_config files/meson.build
-test cases/kconfig/3 load_config files/dir/config
-test cases/kconfig/3 load_config files/dir/meson.build
-test cases/kconfig/4 load_config builddir/config
-test cases/kconfig/4 load_config builddir/meson.build
+test cases/java/9 jdk/meson.build
+test cases/java/9 jdk/lib/com_mesonbuild_JdkTest.c
+test cases/java/9 jdk/lib/meson.build
+test cases/java/9 jdk/lib/native.c
+test cases/java/9 jdk/src/meson.build
+test cases/java/9 jdk/src/com/mesonbuild/JdkTest.java
+test cases/java/9 jdk/src/com/mesonbuild/meson.build
+test cases/keyval/1 basic/.config
+test cases/keyval/1 basic/meson.build
+test cases/keyval/1 basic/test.json
+test cases/keyval/2 subdir/.config
+test cases/keyval/2 subdir/meson.build
+test cases/keyval/2 subdir/dir/meson.build
+test cases/keyval/3 load_config files/meson.build
+test cases/keyval/3 load_config files/dir/config
+test cases/keyval/3 load_config files/dir/meson.build
+test cases/keyval/4 load_config builddir/config
+test cases/keyval/4 load_config builddir/meson.build
 test cases/linuxlike/1 pkg-config/meson.build
 test cases/linuxlike/1 pkg-config/prog-checkver.c
 test cases/linuxlike/1 pkg-config/prog.c
@@ -2143,14 +2740,22 @@
 test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build
 test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h
 test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build
+test cases/linuxlike/13 cmake dependency/cmVers.sh
 test cases/linuxlike/13 cmake dependency/meson.build
 test cases/linuxlike/13 cmake dependency/prog-checkver.c
 test cases/linuxlike/13 cmake dependency/prog.c
-test cases/linuxlike/13 cmake dependency/setup_env.json
+test cases/linuxlike/13 cmake dependency/test.json
 test cases/linuxlike/13 cmake dependency/testFlagSet.c
+test cases/linuxlike/13 cmake dependency/cmake/FindImportedOldStyle.cmake
 test cases/linuxlike/13 cmake dependency/cmake/FindImportedTarget.cmake
 test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake
+test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake
+test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake
+test cases/linuxlike/13 cmake dependency/cmake_fake3/bin/.gitkeep
+test cases/linuxlike/13 cmake dependency/cmake_fake3/lib/cmake/cmMesonTestF3/cmMesonTestF3Config.cmake
 test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonTestDep/cmMesonTestDepConfig.cmake
+test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfig.cmake
+test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfigVersion.cmake
 test cases/linuxlike/13 cmake dependency/incdir/myinc.h
 test cases/linuxlike/14 static dynamic linkage/main.c
 test cases/linuxlike/14 static dynamic linkage/meson.build
@@ -2171,6 +2776,7 @@
 test cases/linuxlike/4 extdep static lib/meson.build
 test cases/linuxlike/4 extdep static lib/prog.c
 test cases/linuxlike/5 dependency versions/meson.build
+test cases/linuxlike/5 dependency versions/subprojects/fakezlib/meson.build
 test cases/linuxlike/5 dependency versions/subprojects/somelib/lib.c
 test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build
 test cases/linuxlike/5 dependency versions/subprojects/somelibnover/lib.c
@@ -2181,17 +2787,60 @@
 test cases/linuxlike/6 subdir include order/prog.c
 test cases/linuxlike/6 subdir include order/subdir/glib.h
 test cases/linuxlike/7 library versions/exe.orig.c
-test cases/linuxlike/7 library versions/installed_files.txt
 test cases/linuxlike/7 library versions/lib.c
 test cases/linuxlike/7 library versions/meson.build
-test cases/linuxlike/8 subproject library install/installed_files.txt
+test cases/linuxlike/7 library versions/test.json
 test cases/linuxlike/8 subproject library install/meson.build
+test cases/linuxlike/8 subproject library install/test.json
 test cases/linuxlike/8 subproject library install/subprojects/sublib/meson.build
 test cases/linuxlike/8 subproject library install/subprojects/sublib/sublib.c
 test cases/linuxlike/8 subproject library install/subprojects/sublib/include/subdefs.h
 test cases/linuxlike/9 compiler checks with dependencies/meson.build
 test cases/nasm/1 configure file/hello.asm
 test cases/nasm/1 configure file/meson.build
+test cases/native/1 trivial/meson.build
+test cases/native/1 trivial/trivial.c
+test cases/native/2 global arg/meson.build
+test cases/native/2 global arg/prog.c
+test cases/native/2 global arg/prog.cc
+test cases/native/3 pipeline/input_src.dat
+test cases/native/3 pipeline/meson.build
+test cases/native/3 pipeline/prog.c
+test cases/native/3 pipeline/srcgen.c
+test cases/native/3 pipeline/depends/copyrunner.py
+test cases/native/3 pipeline/depends/filecopier.c
+test cases/native/3 pipeline/depends/libsrc.c.in
+test cases/native/3 pipeline/depends/meson.build
+test cases/native/3 pipeline/depends/prog.c
+test cases/native/3 pipeline/src/input_src.dat
+test cases/native/3 pipeline/src/meson.build
+test cases/native/3 pipeline/src/prog.c
+test cases/native/3 pipeline/src/srcgen.c
+test cases/native/4 tryrun/error.c
+test cases/native/4 tryrun/meson.build
+test cases/native/4 tryrun/no_compile.c
+test cases/native/4 tryrun/ok.c
+test cases/native/5 install script/file.txt
+test cases/native/5 install script/meson.build
+test cases/native/5 install script/test.json
+test cases/native/5 install script/wrap.py
+test cases/native/5 install script/src/exe.c
+test cases/native/5 install script/src/meson.build
+test cases/native/6 add language/meson.build
+test cases/native/6 add language/prog.cc
+test cases/native/7 selfbuilt custom/checkarg.cpp
+test cases/native/7 selfbuilt custom/data.dat
+test cases/native/7 selfbuilt custom/mainprog.cpp
+test cases/native/7 selfbuilt custom/meson.build
+test cases/native/7 selfbuilt custom/tool.cpp
+test cases/native/8 external program shebang parsing/input.txt
+test cases/native/8 external program shebang parsing/main.c
+test cases/native/8 external program shebang parsing/meson.build
+test cases/native/8 external program shebang parsing/script.int.in
+test cases/native/9 override with exe/main2.input
+test cases/native/9 override with exe/meson.build
+test cases/native/9 override with exe/subprojects/sub/foobar.c
+test cases/native/9 override with exe/subprojects/sub/meson.build
 test cases/objc/1 simple/meson.build
 test cases/objc/1 simple/prog.m
 test cases/objc/2 nsstring/meson.build
@@ -2210,20 +2859,20 @@
 test cases/osx/1 basic/meson.build
 test cases/osx/2 library versions/CMakeLists.txt
 test cases/osx/2 library versions/exe.orig.c
-test cases/osx/2 library versions/installed_files.txt
 test cases/osx/2 library versions/lib.c
 test cases/osx/2 library versions/meson.build
 test cases/osx/2 library versions/require_pkgconfig.py
+test cases/osx/2 library versions/test.json
 test cases/osx/3 has function xcode8/meson.build
-test cases/osx/4 framework/installed_files.txt
 test cases/osx/4 framework/meson.build
 test cases/osx/4 framework/prog.c
 test cases/osx/4 framework/stat.c
+test cases/osx/4 framework/test.json
 test cases/osx/4 framework/xcode-frameworks.png
-test cases/osx/5 extra frameworks/installed_files.txt
 test cases/osx/5 extra frameworks/meson.build
 test cases/osx/5 extra frameworks/prog.c
 test cases/osx/5 extra frameworks/stat.c
+test cases/osx/5 extra frameworks/test.json
 test cases/osx/6 multiframework/main.m
 test cases/osx/6 multiframework/meson.build
 test cases/osx/7 bitcode/libbar.mm
@@ -2239,10 +2888,13 @@
 test cases/python/1 basic/gluon/gluonator.py
 test cases/python/1 basic/subdir/meson.build
 test cases/python/1 basic/subdir/subprog.py
-test cases/python/2 extmodule/blaster.py
+test cases/python/2 extmodule/blaster.py.in
 test cases/python/2 extmodule/meson.build
+test cases/python/2 extmodule/test.json
 test cases/python/2 extmodule/ext/meson.build
 test cases/python/2 extmodule/ext/tachyon_module.c
+test cases/python/2 extmodule/ext/nested/meson.build
+test cases/python/2 extmodule/ext/wrongdir/meson.build
 test cases/python/3 cython/cytest.py
 test cases/python/3 cython/meson.build
 test cases/python/3 cython/libdir/cstorer.pxd
@@ -2258,6 +2910,11 @@
 test cases/python/4 custom target depends extmodule/ext/lib/meson-tachyonlib.h
 test cases/python/4 custom target depends extmodule/ext/lib/meson.build
 test cases/python/5 modules kwarg/meson.build
+test cases/python/6 failing subproject/meson.build
+test cases/python/6 failing subproject/subprojects/bar/meson.build
+test cases/python/7 install path/meson.build
+test cases/python/7 install path/test.json
+test cases/python/7 install path/test.py
 test cases/python3/1 basic/meson.build
 test cases/python3/1 basic/prog.py
 test cases/python3/1 basic/gluon/__init__.py
@@ -2309,40 +2966,88 @@
 test cases/rewrite/4 same name targets/meson.build
 test cases/rewrite/4 same name targets/sub1/meson.build
 test cases/rewrite/5 sorting/meson.build
-test cases/rust/1 basic/installed_files.txt
+test cases/rewrite/6 extra_files/addExtraFiles.json
+test cases/rewrite/6 extra_files/info.json
+test cases/rewrite/6 extra_files/meson.build
+test cases/rewrite/6 extra_files/rmExtraFiles.json
+test cases/rust/1 basic/clippy.toml
 test cases/rust/1 basic/meson.build
 test cases/rust/1 basic/prog.rs
+test cases/rust/1 basic/test.json
 test cases/rust/1 basic/subdir/meson.build
 test cases/rust/1 basic/subdir/prog.rs
-test cases/rust/2 sharedlib/installed_files.txt
+test cases/rust/10 language stds/2015.rs
+test cases/rust/10 language stds/2018.rs
+test cases/rust/10 language stds/meson.build
+test cases/rust/11 generated main/gen.py
+test cases/rust/11 generated main/generated_lib_main.rs
+test cases/rust/11 generated main/meson.build
+test cases/rust/11 generated main/sub/meson.build
+test cases/rust/12 bindgen/meson.build
+test cases/rust/12 bindgen/include/other.h
+test cases/rust/12 bindgen/src/gen_header.py
+test cases/rust/12 bindgen/src/header.h
+test cases/rust/12 bindgen/src/main.rs
+test cases/rust/12 bindgen/src/main2.rs
+test cases/rust/12 bindgen/src/source.c
+test cases/rust/12 bindgen/sub/meson.build
+test cases/rust/13 external c dependencies/c_accessing_zlib.c
+test cases/rust/13 external c dependencies/meson.build
+test cases/rust/13 external c dependencies/meson_options.txt
+test cases/rust/13 external c dependencies/prog.rs
+test cases/rust/13 external c dependencies/test.json
+test cases/rust/14 external libm/meson.build
+test cases/rust/14 external libm/meson_options.txt
+test cases/rust/14 external libm/prog.rs
+test cases/rust/14 external libm/rs_math.rs
+test cases/rust/14 external libm/test.json
+test cases/rust/15 polyglot sharedlib/adder.c
+test cases/rust/15 polyglot sharedlib/adder.h
+test cases/rust/15 polyglot sharedlib/adder.rs
+test cases/rust/15 polyglot sharedlib/addertest.c
+test cases/rust/15 polyglot sharedlib/meson.build
+test cases/rust/16 internal c dependencies/lib.c
+test cases/rust/16 internal c dependencies/lib.h
+test cases/rust/16 internal c dependencies/main.rs
+test cases/rust/16 internal c dependencies/meson.build
+test cases/rust/16 internal c dependencies/test.py
+test cases/rust/17 staticlib link staticlib/branch.rs
+test cases/rust/17 staticlib link staticlib/leaf.rs
+test cases/rust/17 staticlib link staticlib/meson.build
+test cases/rust/17 staticlib link staticlib/prog.c
+test cases/rust/17 staticlib link staticlib/test.json
 test cases/rust/2 sharedlib/meson.build
 test cases/rust/2 sharedlib/prog.rs
 test cases/rust/2 sharedlib/stuff.rs
-test cases/rust/3 staticlib/installed_files.txt
+test cases/rust/2 sharedlib/test.json
 test cases/rust/3 staticlib/meson.build
 test cases/rust/3 staticlib/prog.rs
 test cases/rust/3 staticlib/stuff.rs
-test cases/rust/4 polyglot/installed_files.txt
+test cases/rust/3 staticlib/test.json
 test cases/rust/4 polyglot/meson.build
 test cases/rust/4 polyglot/prog.c
 test cases/rust/4 polyglot/stuff.rs
-test cases/rust/5 polyglot static/installed_files.txt
+test cases/rust/4 polyglot/test.json
 test cases/rust/5 polyglot static/meson.build
 test cases/rust/5 polyglot static/prog.c
 test cases/rust/5 polyglot static/stuff.rs
-test cases/rust/6 named staticlib/installed_files.txt
+test cases/rust/5 polyglot static/test.json
 test cases/rust/6 named staticlib/meson.build
 test cases/rust/6 named staticlib/prog.rs
 test cases/rust/6 named staticlib/stuff.rs
-test cases/rust/7 private crate collision/installed_files.txt
+test cases/rust/6 named staticlib/test.json
 test cases/rust/7 private crate collision/meson.build
 test cases/rust/7 private crate collision/prog.rs
 test cases/rust/7 private crate collision/rand.rs
+test cases/rust/7 private crate collision/test.json
 test cases/rust/8 many files/foo.rs
 test cases/rust/8 many files/main.rs
 test cases/rust/8 many files/meson.build
+test cases/rust/9 unit tests/meson.build
+test cases/rust/9 unit tests/test.rs
+test cases/rust/9 unit tests/test2.rs
+test cases/swift/1 exe/main.swift
 test cases/swift/1 exe/meson.build
-test cases/swift/1 exe/prog.swift
 test cases/swift/2 multifile/libfile.swift
 test cases/swift/2 multifile/main.swift
 test cases/swift/2 multifile/meson.build
@@ -2373,6 +3078,7 @@
 test cases/swift/7 modulemap subdir/mylib/mylib.c
 test cases/swift/7 modulemap subdir/mylib/mylib.h
 test cases/unit/1 soname/CMakeLists.txt
+test cases/unit/1 soname/main.c
 test cases/unit/1 soname/meson.build
 test cases/unit/1 soname/versioned.c
 test cases/unit/10 build_rpath/meson.build
@@ -2380,6 +3086,16 @@
 test cases/unit/10 build_rpath/prog.cc
 test cases/unit/10 build_rpath/sub/meson.build
 test cases/unit/10 build_rpath/sub/stuff.c
+test cases/unit/100 custom target name/file.txt.in
+test cases/unit/100 custom target name/meson.build
+test cases/unit/100 custom target name/subdir/meson.build
+test cases/unit/101 relative find program/foo.py
+test cases/unit/101 relative find program/meson.build
+test cases/unit/101 relative find program/subdir/meson.build
+test cases/unit/102 rlib linkage/lib2.rs
+test cases/unit/102 rlib linkage/main.rs
+test cases/unit/102 rlib linkage/meson.build
+test cases/unit/103 python without pkgconfig/meson.build
 test cases/unit/11 cross prog/meson.build
 test cases/unit/11 cross prog/some_cross_tool.py
 test cases/unit/11 cross prog/sometool.py
@@ -2414,7 +3130,11 @@
 test cases/unit/17 prebuilt shared/alexandria.h
 test cases/unit/17 prebuilt shared/another_visitor.c
 test cases/unit/17 prebuilt shared/meson.build
+test cases/unit/17 prebuilt shared/meson_options.txt
 test cases/unit/17 prebuilt shared/patron.c
+test cases/unit/17 prebuilt shared/rejected.c
+test cases/unit/17 prebuilt shared/rejected.h
+test cases/unit/17 prebuilt shared/rejected_main.c
 test cases/unit/18 pkgconfig static/foo.c
 test cases/unit/18 pkgconfig static/foo.pc.in
 test cases/unit/18 pkgconfig static/main.c
@@ -2494,6 +3214,10 @@
 test cases/unit/35 dist script/meson.build
 test cases/unit/35 dist script/prog.c
 test cases/unit/35 dist script/replacer.py
+test cases/unit/35 dist script/subprojects/sub/dist-script.py
+test cases/unit/35 dist script/subprojects/sub/meson.build
+test cases/unit/35 dist script/subprojects/sub/meson_options.txt
+test cases/unit/35 dist script/subprojects/sub/prog.c
 test cases/unit/36 exe_wrapper behaviour/broken-cross.txt
 test cases/unit/36 exe_wrapper behaviour/meson.build
 test cases/unit/36 exe_wrapper behaviour/meson_options.txt
@@ -2557,6 +3281,7 @@
 test cases/unit/48 reconfigure/main.c
 test cases/unit/48 reconfigure/meson.build
 test cases/unit/48 reconfigure/meson_options.txt
+test cases/unit/48 reconfigure/subprojects/sub1/meson.build
 test cases/unit/49 testsetup default/envcheck.py
 test cases/unit/49 testsetup default/meson.build
 test cases/unit/5 compiler detection/compiler wrapper.py
@@ -2580,6 +3305,7 @@
 test cases/unit/54 clang-format/meson.build
 test cases/unit/54 clang-format/prog_expected_c
 test cases/unit/54 clang-format/prog_orig_c
+test cases/unit/54 clang-format/dummydir.h/dummy.dat
 test cases/unit/55 introspect buildoptions/subprojects/projectBad/meson.build
 test cases/unit/55 introspect buildoptions/subprojects/projectBad/meson_options.txt
 test cases/unit/56 dedup compiler libs/meson.build
@@ -2591,6 +3317,7 @@
 test cases/unit/56 dedup compiler libs/libb/libb.c
 test cases/unit/56 dedup compiler libs/libb/libb.h
 test cases/unit/56 dedup compiler libs/libb/meson.build
+test cases/unit/57 introspection/cp.py
 test cases/unit/57 introspection/meson.build
 test cases/unit/57 introspection/meson_options.txt
 test cases/unit/57 introspection/t1.cpp
@@ -2628,71 +3355,211 @@
 test cases/unit/61 identity cross/meson.build
 test cases/unit/61 identity cross/stuff.h
 test cases/unit/62 pkgconfig relative paths/pkgconfig/librelativepath.pc
-test cases/unit/63 test env does not stack/meson.build
-test cases/unit/63 test env does not stack/script.py
-test cases/unit/64 cmake_prefix_path/meson.build
-test cases/unit/64 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake
-test cases/unit/65 cmake parser/meson.build
-test cases/unit/65 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake
-test cases/unit/66 alias target/main.c
-test cases/unit/66 alias target/meson.build
-test cases/unit/68 static archive stripping/app/appA.c
-test cases/unit/68 static archive stripping/app/appB.c
-test cases/unit/68 static archive stripping/app/meson.build
-test cases/unit/68 static archive stripping/lib/libA.c
-test cases/unit/68 static archive stripping/lib/libA.h
-test cases/unit/68 static archive stripping/lib/libB.c
-test cases/unit/68 static archive stripping/lib/libB.h
-test cases/unit/68 static archive stripping/lib/meson.build
-test cases/unit/69 static link/meson.build
-test cases/unit/69 static link/test1.c
-test cases/unit/69 static link/test2.c
-test cases/unit/69 static link/test3.c
-test cases/unit/69 static link/test4.c
-test cases/unit/69 static link/test5.c
-test cases/unit/69 static link/lib/func1.c
-test cases/unit/69 static link/lib/func10.c
-test cases/unit/69 static link/lib/func11.c
-test cases/unit/69 static link/lib/func12.c
-test cases/unit/69 static link/lib/func14.c
-test cases/unit/69 static link/lib/func15.c
-test cases/unit/69 static link/lib/func16.c
-test cases/unit/69 static link/lib/func17.c
-test cases/unit/69 static link/lib/func18.c
-test cases/unit/69 static link/lib/func19.c
-test cases/unit/69 static link/lib/func2.c
-test cases/unit/69 static link/lib/func3.c
-test cases/unit/69 static link/lib/func4.c
-test cases/unit/69 static link/lib/func5.c
-test cases/unit/69 static link/lib/func6.c
-test cases/unit/69 static link/lib/func7.c
-test cases/unit/69 static link/lib/func8.c
-test cases/unit/69 static link/lib/func9.c
-test cases/unit/69 static link/lib/meson.build
-test cases/unit/69 test env value/meson.build
-test cases/unit/69 test env value/test.py
+test cases/unit/63 cmake_prefix_path/meson.build
+test cases/unit/63 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake
+test cases/unit/64 cmake parser/meson.build
+test cases/unit/64 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake
+test cases/unit/65 alias target/main.c
+test cases/unit/65 alias target/meson.build
+test cases/unit/65 alias target/subdir/meson.build
+test cases/unit/66 static archive stripping/app/appA.c
+test cases/unit/66 static archive stripping/app/appB.c
+test cases/unit/66 static archive stripping/app/meson.build
+test cases/unit/66 static archive stripping/lib/libA.c
+test cases/unit/66 static archive stripping/lib/libA.h
+test cases/unit/66 static archive stripping/lib/libB.c
+test cases/unit/66 static archive stripping/lib/libB.h
+test cases/unit/66 static archive stripping/lib/meson.build
+test cases/unit/67 static link/meson.build
+test cases/unit/67 static link/test1.c
+test cases/unit/67 static link/test2.c
+test cases/unit/67 static link/test3.c
+test cases/unit/67 static link/test4.c
+test cases/unit/67 static link/test5.c
+test cases/unit/67 static link/lib/func1.c
+test cases/unit/67 static link/lib/func10.c
+test cases/unit/67 static link/lib/func11.c
+test cases/unit/67 static link/lib/func12.c
+test cases/unit/67 static link/lib/func14.c
+test cases/unit/67 static link/lib/func15.c
+test cases/unit/67 static link/lib/func16.c
+test cases/unit/67 static link/lib/func17.c
+test cases/unit/67 static link/lib/func18.c
+test cases/unit/67 static link/lib/func19.c
+test cases/unit/67 static link/lib/func2.c
+test cases/unit/67 static link/lib/func3.c
+test cases/unit/67 static link/lib/func4.c
+test cases/unit/67 static link/lib/func5.c
+test cases/unit/67 static link/lib/func6.c
+test cases/unit/67 static link/lib/func7.c
+test cases/unit/67 static link/lib/func8.c
+test cases/unit/67 static link/lib/func9.c
+test cases/unit/67 static link/lib/meson.build
+test cases/unit/68 test env value/meson.build
+test cases/unit/68 test env value/test.py
+test cases/unit/69 clang-tidy/.clang-tidy
+test cases/unit/69 clang-tidy/cttest.cpp
+test cases/unit/69 clang-tidy/meson.build
+test cases/unit/69 clang-tidy/dummydir.h/dummy.dat
 test cases/unit/7 run installed/meson.build
 test cases/unit/7 run installed/prog.c
 test cases/unit/7 run installed/foo/foo.c
 test cases/unit/7 run installed/foo/meson.build
-test cases/unit/70 clang-tidy/.clang-tidy
-test cases/unit/70 clang-tidy/cttest.cpp
-test cases/unit/70 clang-tidy/meson.build
-test cases/unit/71 cross/crossfile.in
-test cases/unit/71 cross/meson.build
-test cases/unit/71 cross/meson_options.txt
+test cases/unit/70 cross/crossfile.in
+test cases/unit/70 cross/meson.build
+test cases/unit/70 cross/meson_options.txt
+test cases/unit/71 cross test passed/exewrapper.py
+test cases/unit/71 cross test passed/meson.build
+test cases/unit/71 cross test passed/meson_options.txt
+test cases/unit/71 cross test passed/script.py
+test cases/unit/71 cross test passed/src/main.c
+test cases/unit/72 summary/meson.build
+test cases/unit/72 summary/meson_options.txt
+test cases/unit/72 summary/subprojects/sub/meson.build
+test cases/unit/72 summary/subprojects/sub2/meson.build
+test cases/unit/72 summary/subprojects/sub2/subprojects/subsub/meson.build
 test cases/unit/73 wrap file url/meson.build
 test cases/unit/73 wrap file url/subprojects/foo-patch.tar.xz
 test cases/unit/73 wrap file url/subprojects/foo.tar.xz
-test cases/unit/74 summary/meson.build
-test cases/unit/74 summary/subprojects/sub/meson.build
-test cases/unit/74 summary/subprojects/sub2/meson.build
+test cases/unit/74 dep files/foo.c
+test cases/unit/74 dep files/meson.build
+test cases/unit/75 pkgconfig prefixes/client/client.c
+test cases/unit/75 pkgconfig prefixes/client/meson.build
+test cases/unit/75 pkgconfig prefixes/val1/meson.build
+test cases/unit/75 pkgconfig prefixes/val1/val1.c
+test cases/unit/75 pkgconfig prefixes/val1/val1.h
+test cases/unit/75 pkgconfig prefixes/val2/meson.build
+test cases/unit/75 pkgconfig prefixes/val2/val2.c
+test cases/unit/75 pkgconfig prefixes/val2/val2.h
+test cases/unit/76 subdir libdir/meson.build
+test cases/unit/76 subdir libdir/subprojects/flub/meson.build
+test cases/unit/77 as link whole/bar.c
+test cases/unit/77 as link whole/foo.c
+test cases/unit/77 as link whole/meson.build
+test cases/unit/78 nostdlib/meson.build
+test cases/unit/78 nostdlib/prog.c
+test cases/unit/78 nostdlib/subprojects/mylibc/libc.c
+test cases/unit/78 nostdlib/subprojects/mylibc/meson.build
+test cases/unit/78 nostdlib/subprojects/mylibc/stdio.h
+test cases/unit/78 nostdlib/subprojects/mylibc/stubstart.s
+test cases/unit/79 user options for subproject/.gitignore
+test cases/unit/79 user options for subproject/75 user options for subproject/.gitignore
+test cases/unit/79 user options for subproject/75 user options for subproject/meson.build
+test cases/unit/79 user options for subproject/subprojects/sub/meson.build
+test cases/unit/79 user options for subproject/subprojects/sub/meson_options.txt
 test cases/unit/8 -L -l order/first.pc
 test cases/unit/8 -L -l order/meson.build
 test cases/unit/8 -L -l order/prog.c
 test cases/unit/8 -L -l order/second.pc
+test cases/unit/80 global-rpath/meson.build
+test cases/unit/80 global-rpath/rpathified.cpp
+test cases/unit/80 global-rpath/yonder/meson.build
+test cases/unit/80 global-rpath/yonder/yonder.cpp
+test cases/unit/80 global-rpath/yonder/yonder.h
+test cases/unit/81 wrap-git/meson.build
+test cases/unit/81 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build
+test cases/unit/81 wrap-git/subprojects/wrap_git_upstream/main.c
+test cases/unit/82 meson version compare/meson.build
+test cases/unit/82 meson version compare/subprojects/foo/meson.build
+test cases/unit/83 cross only introspect/meson.build
+test cases/unit/84 change option choices/meson.build
+test cases/unit/84 change option choices/meson_options.1.txt
+test cases/unit/84 change option choices/meson_options.2.txt
+test cases/unit/85 nested subproject regenerate depends/main.c
+test cases/unit/85 nested subproject regenerate depends/meson.build
+test cases/unit/85 nested subproject regenerate depends/subprojects/sub1/meson.build
+test cases/unit/85 nested subproject regenerate depends/subprojects/sub2/CMakeLists.txt
+test cases/unit/86 cpp modules/main.cpp
+test cases/unit/86 cpp modules/meson.build
+test cases/unit/86 cpp modules/src0.ixx
+test cases/unit/86 cpp modules/src1.ixx
+test cases/unit/86 cpp modules/src2.ixx
+test cases/unit/86 cpp modules/src3.ixx
+test cases/unit/86 cpp modules/src4.ixx
+test cases/unit/86 cpp modules/src5.ixx
+test cases/unit/86 cpp modules/src6.ixx
+test cases/unit/86 cpp modules/src7.ixx
+test cases/unit/86 cpp modules/src8.ixx
+test cases/unit/86 cpp modules/src9.ixx
+test cases/unit/87 prelinking/file1.c
+test cases/unit/87 prelinking/file2.c
+test cases/unit/87 prelinking/file3.c
+test cases/unit/87 prelinking/file4.c
+test cases/unit/87 prelinking/main.c
+test cases/unit/87 prelinking/meson.build
+test cases/unit/87 prelinking/private_header.h
+test cases/unit/87 prelinking/public_header.h
+test cases/unit/88 run native test/main.c
+test cases/unit/88 run native test/meson.build
+test cases/unit/89 multiple envvars/meson.build
+test cases/unit/89 multiple envvars/prog.c
+test cases/unit/89 multiple envvars/prog.cpp
 test cases/unit/9 d dedup/meson.build
 test cases/unit/9 d dedup/prog.c
+test cases/unit/90 pkgconfig build rpath order/dummy.pc
+test cases/unit/90 pkgconfig build rpath order/meson.build
+test cases/unit/90 pkgconfig build rpath order/prog.c
+test cases/unit/90 pkgconfig build rpath order/prog.cc
+test cases/unit/90 pkgconfig build rpath order/sub/meson.build
+test cases/unit/90 pkgconfig build rpath order/sub/stuff.c
+test cases/unit/91 devenv/main.c
+test cases/unit/91 devenv/meson.build
+test cases/unit/91 devenv/test-devenv.py
+test cases/unit/91 devenv/subprojects/sub/foo.c
+test cases/unit/91 devenv/subprojects/sub/meson.build
+test cases/unit/92 install skip subprojects/foo.c
+test cases/unit/92 install skip subprojects/foo.dat
+test cases/unit/92 install skip subprojects/foo.h
+test cases/unit/92 install skip subprojects/meson.build
+test cases/unit/92 install skip subprojects/foo/foofile
+test cases/unit/92 install skip subprojects/subprojects/bar/bar.c
+test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat
+test cases/unit/92 install skip subprojects/subprojects/bar/bar.h
+test cases/unit/92 install skip subprojects/subprojects/bar/meson.build
+test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile
+test cases/unit/93 new subproject in configured project/meson.build
+test cases/unit/93 new subproject in configured project/meson_options.txt
+test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c
+test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build
+test cases/unit/94 clangformat/.clang-format
+test cases/unit/94 clangformat/.clang-format-ignore
+test cases/unit/94 clangformat/.clang-format-include
+test cases/unit/94 clangformat/meson.build
+test cases/unit/94 clangformat/not-included/badformat.cpp
+test cases/unit/94 clangformat/src/badformat.c
+test cases/unit/94 clangformat/src/badformat.cpp
+test cases/unit/95 custominc/helper.c
+test cases/unit/95 custominc/meson.build
+test cases/unit/95 custominc/prog.c
+test cases/unit/95 custominc/prog2.c
+test cases/unit/95 custominc/easytogrepfor/genh.py
+test cases/unit/95 custominc/easytogrepfor/meson.build
+test cases/unit/96 implicit force fallback/meson.build
+test cases/unit/96 implicit force fallback/subprojects/something/meson.build
+test cases/unit/97 compiler.links file arg/meson.build
+test cases/unit/97 compiler.links file arg/test.c
+test cases/unit/98 link full name/.gitignore
+test cases/unit/98 link full name/libtestprovider/meson.build
+test cases/unit/98 link full name/libtestprovider/provider.c
+test cases/unit/98 link full name/proguser/meson.build
+test cases/unit/98 link full name/proguser/receiver.c
+test cases/unit/99 install all targets/bar-custom.txt
+test cases/unit/99 install all targets/bar-devel.h
+test cases/unit/99 install all targets/bar-notag.txt
+test cases/unit/99 install all targets/foo.in
+test cases/unit/99 install all targets/foo1-devel.h
+test cases/unit/99 install all targets/lib.c
+test cases/unit/99 install all targets/main.c
+test cases/unit/99 install all targets/meson.build
+test cases/unit/99 install all targets/script.py
+test cases/unit/99 install all targets/custom_files/data.txt
+test cases/unit/99 install all targets/subdir/bar2-devel.h
+test cases/unit/99 install all targets/subdir/foo2.in
+test cases/unit/99 install all targets/subdir/foo3-devel.h
+test cases/unit/99 install all targets/subdir/lib.c
+test cases/unit/99 install all targets/subdir/main.c
+test cases/unit/99 install all targets/subdir/meson.build
+test cases/unit/99 install all targets/subdir/script.py
 test cases/vala/1 basic/meson.build
 test cases/vala/1 basic/prog.vala
 test cases/vala/10 mixed sources/meson.build
@@ -2700,14 +3567,15 @@
 test cases/vala/10 mixed sources/c/meson.build
 test cases/vala/10 mixed sources/c/writec.py
 test cases/vala/10 mixed sources/vala/bar.vala
-test cases/vala/11 generated vapi/installed_files.txt
 test cases/vala/11 generated vapi/main.vala
 test cases/vala/11 generated vapi/meson.build
+test cases/vala/11 generated vapi/test.json
 test cases/vala/11 generated vapi/libbar/bar.c
 test cases/vala/11 generated vapi/libbar/bar.h
 test cases/vala/11 generated vapi/libbar/meson.build
 test cases/vala/11 generated vapi/libfoo/foo.c
 test cases/vala/11 generated vapi/libfoo/foo.h
+test cases/vala/11 generated vapi/libfoo/foo.metadata
 test cases/vala/11 generated vapi/libfoo/meson.build
 test cases/vala/12 custom output/bar.vala
 test cases/vala/12 custom output/foo.vala
@@ -2780,18 +3648,18 @@
 test cases/vala/5 target glib/GLib.Thread.vala
 test cases/vala/5 target glib/meson.build
 test cases/vala/5 target glib/retcode.c
-test cases/vala/6 static library/installed_files.txt
 test cases/vala/6 static library/meson.build
 test cases/vala/6 static library/mylib.vala
 test cases/vala/6 static library/prog.vala
-test cases/vala/7 shared library/installed_files.txt
+test cases/vala/6 static library/test.json
 test cases/vala/7 shared library/meson.build
+test cases/vala/7 shared library/test.json
 test cases/vala/7 shared library/lib/meson.build
 test cases/vala/7 shared library/lib/mylib.vala
 test cases/vala/7 shared library/prog/meson.build
 test cases/vala/7 shared library/prog/prog.vala
-test cases/vala/8 generated sources/installed_files.txt
 test cases/vala/8 generated sources/meson.build
+test cases/vala/8 generated sources/test.json
 test cases/vala/8 generated sources/dependency-generated/enum-types.c.template
 test cases/vala/8 generated sources/dependency-generated/enum-types.h.template
 test cases/vala/8 generated sources/dependency-generated/enums.h
@@ -2809,24 +3677,46 @@
 test cases/vala/8 generated sources/src/write_wrapper.py
 test cases/vala/8 generated sources/tools/meson.build
 test cases/vala/9 gir/foo.vala
-test cases/vala/9 gir/installed_files.txt
 test cases/vala/9 gir/meson.build
+test cases/vala/9 gir/test.json
 test cases/warning/1 version for string div/meson.build
+test cases/warning/1 version for string div/test.json
 test cases/warning/1 version for string div/a/b.c
+test cases/warning/2 languages missing native/meson.build
+test cases/warning/2 languages missing native/test.json
+test cases/warning/3 fallback consistency/meson.build
+test cases/warning/3 fallback consistency/test.json
+test cases/warning/3 fallback consistency/subprojects/sub/meson.build
+test cases/warning/4 fallback consistency/meson.build
+test cases/warning/4 fallback consistency/test.json
+test cases/warning/4 fallback consistency/subprojects/sub/meson.build
+test cases/warning/5 fallback consistency/meson.build
+test cases/warning/5 fallback consistency/test.json
+test cases/warning/5 fallback consistency/subprojects/foo.wrap
+test cases/warning/5 fallback consistency/subprojects/foo/meson.build
+test cases/warning/6 list add/meson.build
+test cases/warning/6 list add/test.json
+test cases/wasm/1 basic/hello.c
 test cases/wasm/1 basic/hello.cpp
 test cases/wasm/1 basic/hello.html
 test cases/wasm/1 basic/meson.build
-test cases/windows/1 basic/installed_files.txt
+test cases/wasm/2 threads/meson.build
+test cases/wasm/2 threads/threads.c
+test cases/wasm/2 threads/threads.cpp
+test cases/wasm/3 jslib/meson.build
+test cases/wasm/3 jslib/prog.c
+test cases/wasm/3 jslib/somefuncs.js
 test cases/windows/1 basic/meson.build
 test cases/windows/1 basic/prog.c
+test cases/windows/1 basic/test.json
 test cases/windows/10 vs module defs generated custom target/meson.build
 test cases/windows/10 vs module defs generated custom target/prog.c
 test cases/windows/10 vs module defs generated custom target/subdir/make_def.py
 test cases/windows/10 vs module defs generated custom target/subdir/meson.build
 test cases/windows/10 vs module defs generated custom target/subdir/somedll.c
-test cases/windows/11 exe implib/installed_files.txt
 test cases/windows/11 exe implib/meson.build
 test cases/windows/11 exe implib/prog.c
+test cases/windows/11 exe implib/test.json
 test cases/windows/12 resources with custom targets/meson.build
 test cases/windows/12 resources with custom targets/prog.c
 test cases/windows/12 resources with custom targets/res/gen-res.py
@@ -2874,6 +3764,18 @@
 test cases/windows/16 gui app/gui_app_tester.py
 test cases/windows/16 gui app/gui_prog.c
 test cases/windows/16 gui app/meson.build
+test cases/windows/17 msvc ndebug/main.cpp
+test cases/windows/17 msvc ndebug/meson.build
+test cases/windows/18 msvc charset/iso-8859-1.c
+test cases/windows/18 msvc charset/meson.build
+test cases/windows/18 msvc charset/meson_options.txt
+test cases/windows/18 msvc charset/utf8.c
+test cases/windows/19 vs install static lib with generated obj deps/both_lib_source.c
+test cases/windows/19 vs install static lib with generated obj deps/copyfile.py
+test cases/windows/19 vs install static lib with generated obj deps/generated_source.c
+test cases/windows/19 vs install static lib with generated obj deps/meson.build
+test cases/windows/19 vs install static lib with generated obj deps/static_lib_source.c
+test cases/windows/19 vs install static lib with generated obj deps/test.json
 test cases/windows/2 winmain/meson.build
 test cases/windows/2 winmain/prog.c
 test cases/windows/3 cpp/meson.build
@@ -2895,9 +3797,9 @@
 test cases/windows/6 vs module defs/subdir/somedll.def
 test cases/windows/7 dll versioning/copyfile.py
 test cases/windows/7 dll versioning/exe.orig.c
-test cases/windows/7 dll versioning/installed_files.txt
 test cases/windows/7 dll versioning/lib.c
 test cases/windows/7 dll versioning/meson.build
+test cases/windows/7 dll versioning/test.json
 test cases/windows/8 find program/meson.build
 test cases/windows/8 find program/test-script
 test cases/windows/8 find program/test-script-ext.py
@@ -2908,5 +3810,26 @@
 test cases/windows/9 vs module defs generated/subdir/somedll.def.in
 tools/ac_converter.py
 tools/boost_names.py
+tools/build_website.py
 tools/cmake2meson.py
-tools/dircondenser.py
\ No newline at end of file
+tools/copy_files.py
+tools/dircondenser.py
+tools/gen_data.py
+tools/regenerate_docs.py
+tools/run_with_cov.py
+unittests/allplatformstests.py
+unittests/baseplatformtests.py
+unittests/darwintests.py
+unittests/datatests.py
+unittests/failuretests.py
+unittests/helpers.py
+unittests/internaltests.py
+unittests/linuxcrosstests.py
+unittests/linuxliketests.py
+unittests/machinefiletests.py
+unittests/platformagnostictests.py
+unittests/pythontests.py
+unittests/rewritetests.py
+unittests/subprojectscommandtests.py
+unittests/taptests.py
+unittests/windowstests.py
\ No newline at end of file
diff -Nru meson-0.53.2/packaging/createmsi.py meson-0.61.2/packaging/createmsi.py
--- meson-0.53.2/packaging/createmsi.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/packaging/createmsi.py	2022-02-14 19:03:13.000000000 +0000
@@ -0,0 +1,381 @@
+#!/usr/bin/env python3
+
+# Copyright 2017-2021 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 script is for generating MSI packages
+for Windows users.
+'''
+
+import subprocess
+import shutil
+import uuid
+import sys
+import os
+from glob import glob
+import xml.etree.ElementTree as ET
+
+sys.path.append(os.getcwd())
+from mesonbuild import coredata
+
+# Elementtree does not support CDATA. So hack it.
+WINVER_CHECK = ' 602)]]>'
+
+def gen_guid():
+    '''
+       Generate guid
+    '''
+    return str(uuid.uuid4()).upper()
+
+def get_all_modules_from_dir(dirname):
+    '''
+    Get all modules required for Meson build MSI package
+    from directories.
+    '''
+    modname = os.path.basename(dirname)
+    modules = [os.path.splitext(os.path.split(x)[1])[0] for x in glob(os.path.join(dirname, '*'))]
+    modules = ['mesonbuild.' + modname + '.' + x for x in modules if not x.startswith('_')]
+    return modules
+
+def get_more_modules():
+    '''
+        Getter for missing Modules.
+        Python packagers want to be minimal and only copy the things
+        that they can see that being used. They are blind to many things.
+    '''
+    return ['distutils.archive_util',
+            'distutils.cmd',
+            'distutils.config',
+            'distutils.core',
+            'distutils.debug',
+            'distutils.dep_util',
+            'distutils.dir_util',
+            'distutils.dist',
+            'distutils.errors',
+            'distutils.extension',
+            'distutils.fancy_getopt',
+            'distutils.file_util',
+            'distutils.spawn',
+            'distutils.util',
+            'distutils.version',
+            'distutils.command.build_ext',
+            'distutils.command.build',
+            'distutils.command.install',
+            'filecmp',
+            ]
+
+def get_modules():
+    modules = get_all_modules_from_dir('mesonbuild/modules')
+    modules += get_all_modules_from_dir('mesonbuild/scripts')
+    modules += get_more_modules()
+    return modules
+
+class Node:
+    '''
+       Node to hold path and directory values
+    '''
+
+    def __init__(self, dirs, files):
+        self.check_dirs(dirs)
+        self.check_files(files)
+        self.dirs = dirs
+        self.files = files
+
+    @staticmethod
+    def check_dirs(dirs):
+        '''
+           Check to see if directory is instance of list
+        '''
+        assert isinstance(dirs, list)
+
+    @staticmethod
+    def check_files(files):
+        '''
+           Check to see if files is instance of list
+        '''
+        assert isinstance(files, list)
+
+
+class PackageGenerator:
+    '''
+       Package generator for MSI packages
+    '''
+
+    def __init__(self):
+        self.product_name = 'Meson Build System'
+        self.manufacturer = 'The Meson Development Team'
+        self.version = coredata.version.replace('dev', '')
+        self.root = None
+        self.guid = '*'
+        self.update_guid = '141527EE-E28A-4D14-97A4-92E6075D28B2'
+        self.main_xml = 'meson.wxs'
+        self.main_o = 'meson.wixobj'
+        self.final_output = f'meson-{self.version}-64.msi'
+        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\\Community\\VC\\Redist\\MSVC\\v*\\MergeModules\\Microsoft_VC143_CRT_x64.msm']
+        redist_path = None
+        for g in redist_globs:
+            trials = glob(g)
+            if len(trials) > 1:
+                sys.exit('MSM glob matched multiple entries:' + '\n'.join(trials))
+            if len(trials) == 1:
+                redist_path = trials[0]
+                break
+        if redist_path is None:
+            sys.exit('No MSMs found.')
+        self.redist_path = redist_path
+        self.component_num = 0
+        self.feature_properties = {
+            self.staging_dirs[0]: {
+                'Id': 'MainProgram',
+                'Title': 'Meson',
+                'Description': 'Meson executables',
+                'Level': '1',
+                'Absent': 'disallow',
+            },
+            self.staging_dirs[1]: {
+                'Id': 'NinjaProgram',
+                'Title': 'Ninja',
+                'Description': 'Ninja build tool',
+                'Level': '1',
+            }
+        }
+        self.feature_components = {}
+        for s_d in self.staging_dirs:
+            self.feature_components[s_d] = []
+
+    def build_dist(self):
+        '''
+           Build dist file from PyInstaller info
+        '''
+        for sdir in self.staging_dirs:
+            if os.path.exists(sdir):
+                shutil.rmtree(sdir)
+        main_stage, ninja_stage = self.staging_dirs
+        modules = get_modules()
+
+        pyinstaller = shutil.which('pyinstaller')
+        if not pyinstaller:
+            print("ERROR: This script requires pyinstaller.")
+            sys.exit(1)
+
+        pyinstaller_tmpdir = 'pyinst-tmp'
+        if os.path.exists(pyinstaller_tmpdir):
+            shutil.rmtree(pyinstaller_tmpdir)
+        pyinst_cmd = [pyinstaller,
+                      '--clean',
+                      '--distpath',
+                      pyinstaller_tmpdir]
+        for m in modules:
+            pyinst_cmd += ['--hidden-import', m]
+        pyinst_cmd += ['meson.py']
+        subprocess.check_call(pyinst_cmd)
+        shutil.move(pyinstaller_tmpdir + '/meson', main_stage)
+        self.del_infodirs(main_stage)
+        if not os.path.exists(os.path.join(main_stage, 'meson.exe')):
+            sys.exit('Meson exe missing from staging dir.')
+        os.mkdir(ninja_stage)
+        shutil.copy(shutil.which('ninja'), ninja_stage)
+        if not os.path.exists(os.path.join(ninja_stage, 'ninja.exe')):
+            sys.exit('Ninja exe missing from staging dir.')
+
+    def del_infodirs(self, dirname):
+        # Starting with 3.9.something there are some
+        # extra metadatadirs that have a hyphen in their
+        # file names. This is a forbidden character in WiX
+        # filenames so delete them.
+        for d in glob(os.path.join(dirname, '*-info')):
+            shutil.rmtree(d)
+
+    def generate_files(self):
+        '''
+           Generate package files for MSI installer package
+        '''
+        self.root = ET.Element('Wix', {'xmlns': 'http://schemas.microsoft.com/wix/2006/wi'})
+        product = ET.SubElement(self.root, 'Product', {
+            'Name': self.product_name,
+            'Manufacturer': 'The Meson Development Team',
+            'Id': self.guid,
+            'UpgradeCode': self.update_guid,
+            'Language': '1033',
+            'Codepage':  '1252',
+            'Version': self.version,
+        })
+
+        package = ET.SubElement(product, 'Package', {
+            'Id': '*',
+            'Keywords': 'Installer',
+            'Description': f'Meson {self.version} installer',
+            'Comments': 'Meson is a high performance build system',
+            'Manufacturer': 'The Meson Development Team',
+            'InstallerVersion': '500',
+            'Languages': '1033',
+            'Compressed': 'yes',
+            'SummaryCodepage': '1252',
+        })
+
+        condition = ET.SubElement(product, 'Condition', {'Message': 'This application is only supported on Windows 10 or higher.'})
+
+        condition.text = 'X'*len(WINVER_CHECK)
+        ET.SubElement(product, 'MajorUpgrade',
+                      {'DowngradeErrorMessage': 'A newer version of Meson is already installed.'})
+
+        package.set('Platform', 'x64')
+        ET.SubElement(product, 'Media', {
+            'Id': '1',
+            'Cabinet': 'meson.cab',
+            'EmbedCab': 'yes',
+        })
+        targetdir = ET.SubElement(product, 'Directory', {
+            'Id': 'TARGETDIR',
+            'Name': 'SourceDir',
+        })
+        progfiledir = ET.SubElement(targetdir, 'Directory', {
+            'Id': self.progfile_dir,
+        })
+        installdir = ET.SubElement(progfiledir, 'Directory', {
+            'Id': 'INSTALLDIR',
+            'Name': 'Meson',
+        })
+        ET.SubElement(installdir, 'Merge', {
+            'Id': 'VCRedist',
+            'SourceFile': self.redist_path,
+            'DiskId': '1',
+            'Language': '0',
+        })
+
+        ET.SubElement(product, 'Property', {
+            'Id': 'WIXUI_INSTALLDIR',
+            'Value': 'INSTALLDIR',
+        })
+        ET.SubElement(product, 'UIRef', {
+            'Id': 'WixUI_FeatureTree',
+        })
+        for s_d in self.staging_dirs:
+            assert os.path.isdir(s_d)
+        top_feature = ET.SubElement(product, 'Feature', {
+            'Id': 'Complete',
+            'Title': 'Meson ' + self.version,
+            'Description': 'The complete package',
+            'Display': 'expand',
+            'Level': '1',
+            'ConfigurableDirectory': 'INSTALLDIR',
+        })
+        for s_d in self.staging_dirs:
+            nodes = {}
+            for root, dirs, files in os.walk(s_d):
+                cur_node = Node(dirs, files)
+                nodes[root] = cur_node
+            self.create_xml(nodes, s_d, installdir, s_d)
+            self.build_features(top_feature, s_d)
+        vcredist_feature = ET.SubElement(top_feature, 'Feature', {
+            'Id': 'VCRedist',
+            'Title': 'Visual C++ runtime',
+            'AllowAdvertise': 'no',
+            'Display': 'hidden',
+            'Level': '1',
+        })
+        ET.SubElement(vcredist_feature, 'MergeRef', {'Id': 'VCRedist'})
+        ET.ElementTree(self.root).write(self.main_xml, encoding='utf-8', xml_declaration=True)
+        # ElementTree can not do prettyprinting so do it manually
+        import xml.dom.minidom
+        doc = xml.dom.minidom.parse(self.main_xml)
+        with open(self.main_xml, 'w') as open_file:
+            open_file.write(doc.toprettyxml())
+        # One last fix, add CDATA.
+        with open(self.main_xml) as open_file:
+            data = open_file.read()
+        data = data.replace('X'*len(WINVER_CHECK), WINVER_CHECK)
+        with open(self.main_xml, 'w') as open_file:
+            open_file.write(data)
+
+    def build_features(self, top_feature, staging_dir):
+        '''
+           Generate build features
+        '''
+        feature = ET.SubElement(top_feature, 'Feature', self.feature_properties[staging_dir])
+        for component_id in self.feature_components[staging_dir]:
+            ET.SubElement(feature, 'ComponentRef', {
+                'Id': component_id,
+            })
+
+    def create_xml(self, nodes, current_dir, parent_xml_node, staging_dir):
+        '''
+           Create XML file
+        '''
+        cur_node = nodes[current_dir]
+        if cur_node.files:
+            component_id = f'ApplicationFiles{self.component_num}'
+            comp_xml_node = ET.SubElement(parent_xml_node, 'Component', {
+                'Id': component_id,
+                'Guid': gen_guid(),
+            })
+            self.feature_components[staging_dir].append(component_id)
+            comp_xml_node.set('Win64', 'yes')
+            if self.component_num == 0:
+                ET.SubElement(comp_xml_node, 'Environment', {
+                    'Id': 'Environment',
+                    'Name': 'PATH',
+                    'Part': 'last',
+                    'System': 'yes',
+                    'Action': 'set',
+                    'Value': '[INSTALLDIR]',
+                })
+            self.component_num += 1
+            for f_node in cur_node.files:
+                file_id = os.path.join(current_dir, f_node).replace('\\', '_').replace('#', '_').replace('-', '_')
+                ET.SubElement(comp_xml_node, 'File', {
+                    'Id': file_id,
+                    'Name': f_node,
+                    'Source': os.path.join(current_dir, f_node),
+                })
+
+        for dirname in cur_node.dirs:
+            dir_id = os.path.join(current_dir, dirname).replace('\\', '_').replace('/', '_')
+            dir_node = ET.SubElement(parent_xml_node, 'Directory', {
+                'Id': dir_id,
+                'Name': dirname,
+            })
+            self.create_xml(nodes, os.path.join(current_dir, dirname), dir_node, staging_dir)
+
+    def build_package(self):
+        '''
+           Generate the Meson build MSI package.
+        '''
+        wixdir = 'c:\\Program Files\\Wix Toolset v3.11\\bin'
+        if not os.path.isdir(wixdir):
+            wixdir = 'c:\\Program Files (x86)\\Wix Toolset v3.11\\bin'
+        if not os.path.isdir(wixdir):
+            print("ERROR: This script requires WIX")
+            sys.exit(1)
+        subprocess.check_call([os.path.join(wixdir, 'candle'), self.main_xml])
+        subprocess.check_call([os.path.join(wixdir, 'light'),
+                               '-ext', 'WixUIExtension',
+                               '-cultures:en-us',
+                               '-dWixUILicenseRtf=packaging\\License.rtf',
+                               '-out', self.final_output,
+                               self.main_o])
+
+if __name__ == '__main__':
+    if not os.path.exists('meson.py'):
+        sys.exit(print('Run me in the top level source dir.'))
+    subprocess.check_call(['pip', 'install', '--upgrade', 'pyinstaller'])
+
+    p = PackageGenerator()
+    p.build_dist()
+    p.generate_files()
+    p.build_package()
diff -Nru meson-0.53.2/packaging/createpkg.py meson-0.61.2/packaging/createpkg.py
--- meson-0.53.2/packaging/createpkg.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/packaging/createpkg.py	2021-11-02 19:58:07.000000000 +0000
@@ -0,0 +1,122 @@
+#!/usr/bin/env python3
+
+# Copyright 2017-2021 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 subprocess
+import shutil, sys, os
+
+import xml.etree.ElementTree as ET
+
+sys.path.append(os.getcwd())
+from mesonbuild import coredata
+
+from createmsi import get_modules
+
+class PkgGenerator:
+
+    def __init__(self):
+        self.pkg_dir = 'macpkg'
+        self.sharedir = os.path.join(self.pkg_dir, 'usr/local/share')
+        self.bindir = os.path.join(self.pkg_dir, 'usr/local/bin')
+        self.product_name = 'Meson Build System'
+        self.identifier = 'com.mesonbuild.meson'
+        self.version = coredata.version.replace('dev', '')
+        self.mesonstashdir = os.path.join(self.sharedir, f'meson-{self.version}')
+        self.pkgname = 'meson.pkg'
+        self.productname = f'meson-{self.version}.pkg'
+        self.distribution_file = 'meson-distribution.xml'
+        self.resourcedir = 'packaging/macpages'
+
+    def build_dist(self):
+        if os.path.exists(self.pkg_dir):
+            shutil.rmtree(self.pkg_dir)
+        os.mkdir(self.pkg_dir)
+        pyinstaller_bin = '/Users/jpakkane/Library/Python/3.8/bin/pyinstaller'
+        pyinst_cmd = [pyinstaller_bin,
+                      '--clean',
+                      '--distpath',
+                      self.pkg_dir]
+        for m in get_modules():
+            pyinst_cmd += ['--hidden-import', m]
+        pyinst_cmd += ['meson.py']
+        subprocess.check_call(pyinst_cmd)
+        tmpdir = os.path.join(self.pkg_dir, 'meson')
+        shutil.move(tmpdir, self.mesonstashdir)
+        os.makedirs(self.bindir)
+        ln_base = os.path.relpath(self.mesonstashdir, self.bindir)
+        ninja_bin = shutil.which('ninja')
+        assert ninja_bin
+        shutil.copy(ninja_bin, self.bindir)
+        subprocess.check_call(['strip', os.path.join(self.bindir, 'ninja')])
+        os.symlink(os.path.join(ln_base, 'meson'), os.path.join(self.bindir, 'meson'))
+
+    def build_package(self):
+        subprocess.check_call(['pkgbuild',
+                               '--root',
+                               self.pkg_dir,
+                               '--identifier',
+                               self.identifier,
+                               self.pkgname])
+        self.generate_distribution()
+        subprocess.check_call(['productbuild',
+                               '--distribution',
+                               self.distribution_file,
+                               '--resources',
+                               self.resourcedir,
+                               self.productname])
+
+    def generate_distribution(self):
+        root = ET.Element('installer-gui-script', {'minSpecVersion': '1'})
+        ET.SubElement(root, 'welcome', {'file': 'welcome.html',
+                                        'mime-type': 'text/html'})
+        ET.SubElement(root, 'license', {'file': 'license.html',
+                                        'mime-type': 'text/html'})
+        ET.SubElement(root, 'conclusion', {'file': 'conclusion.html',
+                                        'mime-type': 'text/html'})
+        ET.SubElement(root, 'pkg-ref', {'id': self.identifier})
+        ET.SubElement(root, 'options', {'customize': 'never',
+                                        'require-scripts': 'false',
+                                        'hostArhcitectures': 'x86_64,arm64'})
+        choices_outline = ET.SubElement(root, 'choices-outline')
+        line = ET.SubElement(choices_outline, 'line', {'choice': 'default'})
+        ET.SubElement(line, 'line', {'choice': self.identifier})
+        ET.SubElement(root, 'choice', {'id': 'default'})
+        choice = ET.SubElement(root, 'choice', {'id': self.identifier, 'visible': 'false'})
+        ET.SubElement(choice, 'pkg-ref', {'id': self.identifier})
+        ET.SubElement(root, 'pkg-ref', {'id': self.identifier,
+                                        'version': '0', # self.version,
+                                        'onConclusion': 'none'}).text = self.pkgname
+        ET.ElementTree(root).write(self.distribution_file, encoding='utf-8', xml_declaration=True)
+        # ElementTree can not do prettyprinting so do it manually
+        import xml.dom.minidom
+        doc = xml.dom.minidom.parse(self.distribution_file)
+        with open(self.distribution_file, 'w') as open_file:
+            open_file.write(doc.toprettyxml())
+
+    def remove_tempfiles(self):
+        shutil.rmtree('macpkg')
+        os.unlink('meson-distribution.xml')
+        os.unlink('meson.pkg')
+        os.unlink('meson.spec')
+
+if __name__ == '__main__':
+    if not os.path.exists('meson.py'):
+        sys.exit(print('Run me in the top level source dir.'))
+    subprocess.check_call(['pip3', 'install', '--user', '--upgrade', 'pyinstaller'])
+
+    pg = PkgGenerator()
+    pg.build_dist()
+    pg.build_package()
+    pg.remove_tempfiles()
diff -Nru meson-0.53.2/packaging/create_zipapp.py meson-0.61.2/packaging/create_zipapp.py
--- meson-0.53.2/packaging/create_zipapp.py	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/packaging/create_zipapp.py	2021-04-01 21:13:00.000000000 +0000
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+
+import argparse
+from pathlib import Path
+import shutil
+import sys
+import tempfile
+import zipapp
+
+parser = argparse.ArgumentParser()
+parser.add_argument('source', nargs='?', default='.', help='Source directory')
+parser.add_argument('--outfile', default='meson.pyz', help='Output file for the zipapp')
+parser.add_argument('--interpreter', default='/usr/bin/env python3', help='The name of the Python interpreter to use')
+
+options = parser.parse_args(sys.argv[1:])
+
+source = Path(options.source).resolve()
+
+with tempfile.TemporaryDirectory() as d:
+    shutil.copy2(source / 'meson.py', Path(d, '__main__.py'))
+    shutil.copytree(source / 'mesonbuild', Path(d, 'mesonbuild'))
+    zipapp.create_archive(d, interpreter=options.interpreter, target=options.outfile)
diff -Nru meson-0.53.2/packaging/License.rtf meson-0.61.2/packaging/License.rtf
--- meson-0.53.2/packaging/License.rtf	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/packaging/License.rtf	2021-04-01 21:13:00.000000000 +0000
@@ -0,0 +1,73 @@
+{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
+{\colortbl ;\red0\green0\blue255;}
+{\*\generator Msftedit 5.41.21.2510;}\viewkind4\uc1\pard\qc\lang1033\b\f0\fs18 Apache License\par
+Version 2.0, January 2004\par
+{\field{\*\fldinst{HYPERLINK "http://www.apache.org/licenses/"}}{\fldrslt{\ul\cf1 http://www.apache.org/licenses/}}}\f0\fs18\par
+\b0\par
+\pard TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\par
+\par
+\pard\fi-180\li180 1. Definitions.\par
+\par
+\pard\li180 "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.\par
+\par
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.\par
+\par
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.\par
+\par
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.\par
+\par
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.\par
+\par
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.\par
+\par
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).\par
+\par
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.\par
+\par
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."\par
+\par
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.\par
+\pard\par
+\pard\fi-180\li180 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.\par
+\par
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.\par
+\par
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:\par
+\pard\par
+\pard\fi-270\li450 (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and\par
+\par
+(b) You must cause any modified files to carry prominent notices stating that You changed the files; and\par
+\par
+(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and\par
+\par
+(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.\par
+\pard\par
+\pard\li180 You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or  for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.\par
+\pard\par
+\pard\fi-180\li180 5. Submission of Contributions. Unless You explicitly state otherwise,  any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.\par
+\par
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.\par
+\par
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.\par
+\par
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.\par
+\par
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.\par
+\pard\par
+END OF TERMS AND CONDITIONS\par
+\par
+APPENDIX: How to apply the Apache License to your work.\par
+\par
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!)  The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.\par
+\par
+\pard\li180 Copyright [yyyy] [name of copyright owner]\par
+\par
+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\par
+\par
+\pard\li360{\field{\*\fldinst{HYPERLINK "http://www.apache.org/licenses/LICENSE-2.0"}}{\fldrslt{\ul\cf1 http://www.apache.org/licenses/LICENSE-2.0}}}\f0\fs18\par
+\pard\li180\par
+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.\par
+\pard\par
+\par
+}
+
\ No newline at end of file
diff -Nru meson-0.53.2/packaging/macpages/English.lproj/conclusion.html meson-0.61.2/packaging/macpages/English.lproj/conclusion.html
--- meson-0.53.2/packaging/macpages/English.lproj/conclusion.html	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/packaging/macpages/English.lproj/conclusion.html	2021-06-07 17:35:22.000000000 +0000
@@ -0,0 +1,24 @@
+
+  
+  
+  
+
+    

Install finished

+ +

The Meson build system is now installed. Note that Meson does not + provide any GUI applications, it is only usable from the command + line. You can verify if your installation of Meson is working by + running the following command in a terminal +

+ +
+      $ meson --version
+    
+ +

If the system reports that the program could not be found + you might need to edit your configuration files so + that /usr/local/bin is in your path. +

+ + + diff -Nru meson-0.53.2/packaging/macpages/English.lproj/license.html meson-0.61.2/packaging/macpages/English.lproj/license.html --- meson-0.53.2/packaging/macpages/English.lproj/license.html 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/packaging/macpages/English.lproj/license.html 2021-06-07 17:35:22.000000000 +0000 @@ -0,0 +1,209 @@ + + + + +
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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.
+  
+  
+
diff -Nru meson-0.53.2/packaging/macpages/English.lproj/welcome.html meson-0.61.2/packaging/macpages/English.lproj/welcome.html
--- meson-0.53.2/packaging/macpages/English.lproj/welcome.html	1970-01-01 00:00:00.000000000 +0000
+++ meson-0.61.2/packaging/macpages/English.lproj/welcome.html	2021-06-07 17:35:22.000000000 +0000
@@ -0,0 +1,12 @@
+
+  
+  
+  
+
+  

Meson build system installer

+ +

This package will install the command line tools of Meson to + this computer. +

+ + diff -Nru meson-0.53.2/PKG-INFO meson-0.61.2/PKG-INFO --- meson-0.53.2/PKG-INFO 2020-02-25 16:02:10.000000000 +0000 +++ meson-0.61.2/PKG-INFO 2022-02-14 19:24:02.893610000 +0000 @@ -1,12 +1,11 @@ Metadata-Version: 2.1 Name: meson -Version: 0.53.2 +Version: 0.61.2 Summary: A high performance build system Home-page: https://mesonbuild.com Author: Jussi Pakkanen Author-email: jpakkane@gmail.com License: Apache License, Version 2.0 -Description: Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL. Keywords: meson,mesonbuild,build system,cmake Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable @@ -19,10 +18,16 @@ Classifier: Operating System :: POSIX :: BSD Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Software Development :: Build Tools -Requires-Python: >=3.5.2 +Requires-Python: >=3.6 +Provides-Extra: ninja Provides-Extra: progress +Provides-Extra: typing +License-File: COPYING + +Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL. + diff -Nru meson-0.53.2/README.md meson-0.61.2/README.md --- meson-0.53.2/README.md 2019-12-04 18:45:50.000000000 +0000 +++ meson-0.61.2/README.md 2022-01-17 10:50:45.000000000 +0000 @@ -7,7 +7,6 @@ #### Status [![PyPI](https://img.shields.io/pypi/v/meson.svg)](https://pypi.python.org/pypi/meson) -[![Travis](https://travis-ci.org/mesonbuild/meson.svg?branch=master)](https://travis-ci.org/mesonbuild/meson) [![Build Status](https://dev.azure.com/jussi0947/jussi/_apis/build/status/mesonbuild.meson)](https://dev.azure.com/jussi0947/jussi/_build/latest?definitionId=1) [![Codecov](https://codecov.io/gh/mesonbuild/meson/coverage.svg?branch=master)](https://codecov.io/gh/mesonbuild/meson/branch/master) [![Code Quality: Python](https://img.shields.io/lgtm/grade/python/g/mesonbuild/meson.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/mesonbuild/meson/context:python) @@ -15,32 +14,41 @@ #### Dependencies - - [Python](https://python.org) (version 3.5 or newer) - - [Ninja](https://ninja-build.org) (version 1.5 or newer) + - [Python](https://python.org) (version 3.6 or newer) + - [Ninja](https://ninja-build.org) (version 1.8.2 or newer) #### Installing from source -You can run Meson directly from a revision control checkout or an -extracted tarball. If you wish you can install it locally with the -standard Python command +Meson is available on [PyPi](https://pypi.python.org/pypi/meson), so +it can be installed with `pip3 install meson`. The exact command to +type to install with `pip` can vary between systems, be sure to use +the Python 3 version of `pip`. -```sh -python3 -m pip install meson -``` +If you wish you can install it locally with the standard Python command: -Meson is also available from -[PyPi](https://pypi.python.org/pypi/meson), so it can be installed -with `pip3 install meson` (this does not require a source checkout, -pip will download the package automatically). The exact command to -type to install with Pip can vary between systems, be sure to use the -Python 3 version of Pip. +```console +python3 -m pip install meson +``` -For builds using Ninja, Ninja can be [downloaded directly](https://github.com/ninja-build/ninja/releases) or via +For builds using Ninja, Ninja can be downloaded directly from Ninja +[GitHub release page](https://github.com/ninja-build/ninja/releases) +or via [PyPi](https://pypi.python.org/pypi/ninja) -```sh +```console python3 -m pip install ninja ``` +More on Installing Meson build can be found at the +[getting meson page](https://mesonbuild.com/Getting-meson.html). + +#### Creating a standalone script + +Meson can be run as a [Python zip +app](https://docs.python.org/3/library/zipapp.html). To generate the +executable run the following command: + + ./packaging/create_zipapp.py --outfile meson.pyz --interpreter '/usr/bin/env python3' + #### Running Meson requires that you have a source directory and a build directory @@ -48,7 +56,7 @@ file called `meson.build`. To generate the build system run this command: -`meson ` +`meson setup ` Depending on how you obtained Meson the command might also be called `meson.py` instead of plain `meson`. In the rest of this document we @@ -58,42 +66,36 @@ the current directory and autodetect what you mean. This allows you to do things like this: -`cd source_root; mkdir builddir; cd builddir; meson ..` - -or - -`cd source_root; mkdir builddir; meson builddir` +```console +cd +meson setup builddir +``` To compile, cd into your build directory and type `ninja`. To run unit tests, type `ninja test`. -Install is the same but it can take an extra argument: - -`DESTDIR=/destdir/path ninja install` - -`DESTDIR` can be omitted. If you are installing to system directories, -you may need to run this command with sudo. - +More on running Meson build system commands can be found at the +[running meson page](https://mesonbuild.com/Running-Meson.html) +or by typing `meson --help`. #### Contributing We love code contributions. See the [contribution -page](https://mesonbuild.com/Contributing.html) on the web site for +page](https://mesonbuild.com/Contributing.html) on the website for details. #### IRC -The irc channel for Meson is `#mesonbuild` over at Freenode. - -You can use [FreeNode's official webchat][meson_irc] -to connect to this channel. +The channel to use is `#mesonbuild` either via Matrix ([web +interface][matrix_web]) or [OFTC IRC][oftc_irc]. -[meson_irc]: https://webchat.freenode.net/?channels=%23mesonbuild +[matrix_web]: https://app.element.io/#/room/#mesonbuild:matrix.org +[oftc_irc]: https://www.oftc.net/ #### Further info More information about the Meson build system can be found at the [project's home page](https://mesonbuild.com). -Meson is a registered trademark of Jussi Pakkanen. +Meson is a registered trademark of ***Jussi Pakkanen***. diff -Nru meson-0.53.2/run_cross_test.py meson-0.61.2/run_cross_test.py --- meson-0.53.2/run_cross_test.py 2019-04-17 08:08:43.000000000 +0000 +++ meson-0.61.2/run_cross_test.py 2021-07-20 08:56:20.000000000 +0000 @@ -15,44 +15,49 @@ # limitations under the License. '''Runs the basic test suite through a cross compiler. -Not part of the main test suite because of two reasons: -1) setup of the cross build is platform specific -2) it can be slow (e.g. when invoking test apps via wine) +This is now just a wrapper around run_project_tests.py with specific arguments +''' -Eventually migrate to something fancier.''' - -import sys -import os -from pathlib import Path import argparse +import subprocess +from mesonbuild import mesonlib +from mesonbuild.coredata import version as meson_version +from pathlib import Path +import json +import os -from run_project_tests import gather_tests, run_tests, StopException, setup_commands -from run_project_tests import failing_logs -def runtests(cross_file, failfast): - commontests = [('common', gather_tests(Path('test cases', 'common')), False)] - try: - (passing_tests, failing_tests, skipped_tests) = \ - run_tests(commontests, 'meson-cross-test-run', failfast, ['--cross-file', cross_file]) - except StopException: - pass - print('\nTotal passed cross tests:', passing_tests) - print('Total failed cross tests:', failing_tests) - print('Total skipped cross tests:', skipped_tests) - if failing_tests > 0 and ('CI' in os.environ): - print('\nMesonlogs of failing tests\n') - for log in failing_logs: - print(log, '\n') - return failing_tests +def runtests(cross_file, failfast, cross_only, test_list, env=None): + tests = ['--only'] + test_list + if not cross_only: + tests.append('native') + cmd = mesonlib.python_command + ['run_project_tests.py', '--backend', 'ninja'] + if failfast: + cmd += ['--failfast'] + cmd += tests + cmd += ['--cross-file', cross_file] + if cross_only: + cmd += ['--native-file', 'cross/none.txt'] + return subprocess.call(cmd, env=env) def main(): parser = argparse.ArgumentParser() parser.add_argument('--failfast', action='store_true') + parser.add_argument('--cross-only', action='store_true') parser.add_argument('cross_file') options = parser.parse_args() - setup_commands('ninja') - return runtests(options.cross_file, options.failfast) + cf_path = Path(options.cross_file) + try: + data = json.loads(cf_path.read_text(encoding='utf-8')) + real_cf = cf_path.resolve().parent / data['file'] + assert real_cf.exists() + env = os.environ.copy() + env.update(data['env']) + return runtests(real_cf.as_posix(), options.failfast, options.cross_only, data['tests'], env=env) + except Exception: + return runtests(options.cross_file, options.failfast, options.cross_only, ['common']) if __name__ == '__main__': - sys.exit(main()) + print('Meson build system', meson_version, 'Cross Tests') + raise SystemExit(main()) diff -Nru meson-0.53.2/run_meson_command_tests.py meson-0.61.2/run_meson_command_tests.py --- meson-0.53.2/run_meson_command_tests.py 2019-08-28 17:15:39.000000000 +0000 +++ meson-0.61.2/run_meson_command_tests.py 2022-01-17 10:50:45.000000000 +0000 @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys import os import tempfile import unittest @@ -23,6 +22,8 @@ from pathlib import Path from mesonbuild.mesonlib import windows_proof_rmtree, python_command, is_windows +from mesonbuild.coredata import version as meson_version + def get_pypath(): import sysconfig @@ -78,7 +79,7 @@ def assertMesonCommandIs(self, line, cmd): self.assertTrue(line.startswith('meson_command '), msg=line) - self.assertEqual(line, 'meson_command is {!r}'.format(cmd)) + self.assertEqual(line, f'meson_command is {cmd!r}') def test_meson_uninstalled(self): # This is what the meson command must be for all these cases @@ -128,24 +129,13 @@ os.environ['PYTHONPATH'] = os.path.join(str(pylibdir), '') os.environ['PATH'] = str(bindir) + os.pathsep + os.environ['PATH'] self._run(python_command + ['setup.py', 'install', '--prefix', str(prefix)]) + # Fix importlib-metadata by appending all dirs in pylibdir + PYTHONPATHS = [pylibdir] + [x for x in pylibdir.iterdir()] + PYTHONPATHS = [os.path.join(str(x), '') for x in PYTHONPATHS] + os.environ['PYTHONPATH'] = os.pathsep.join(PYTHONPATHS) # Check that all the files were installed correctly self.assertTrue(bindir.is_dir()) self.assertTrue(pylibdir.is_dir()) - from setup import packages - # Extract list of expected python module files - expect = set() - for pkg in packages: - expect.update([p.as_posix() for p in Path(pkg.replace('.', '/')).glob('*.py')]) - # Check what was installed, only count files that are inside 'mesonbuild' - have = set() - for p in Path(pylibdir).glob('**/*.py'): - s = p.as_posix() - if 'mesonbuild' not in s: - continue - if '/data/' in s: - continue - have.add(s[s.rfind('mesonbuild'):]) - self.assertEqual(have, expect) # Run `meson` os.chdir('/') resolved_meson_command = [str(bindir / 'meson')] @@ -175,7 +165,7 @@ builddir = str(self.tmpdir / 'build4') (bindir / 'meson').rename(bindir / 'meson.real') wrapper = (bindir / 'meson') - wrapper.open('w').write('#!/bin/sh\n\nmeson.real "$@"') + wrapper.write_text('#!/bin/sh\n\nmeson.real "$@"', encoding='utf-8') wrapper.chmod(0o755) meson_setup = [str(wrapper), 'setup'] meson_command = meson_setup + self.meson_args @@ -188,11 +178,13 @@ def test_meson_zipapp(self): if is_windows(): raise unittest.SkipTest('NOT IMPLEMENTED') - source = Path(__file__).resolve().parent.as_posix() + source = Path(__file__).resolve().parent target = self.tmpdir / 'meson.pyz' - zipapp.create_archive(source=source, target=target, interpreter=python_command[0], main=None) + script = source / 'packaging' / 'create_zipapp.py' + self._run([script.as_posix(), source, '--outfile', target, '--interpreter', python_command[0]]) self._run([target.as_posix(), '--help']) if __name__ == '__main__': - sys.exit(unittest.main(buffer=True)) + print('Meson build system', meson_version, 'Command Tests') + raise SystemExit(unittest.main(buffer=True)) diff -Nru meson-0.53.2/run_project_tests.py meson-0.61.2/run_project_tests.py --- meson-0.53.2/run_project_tests.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/run_project_tests.py 2022-01-17 10:50:45.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2012-2019 The Meson development team +# Copyright 2012-2021 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. @@ -14,43 +14,77 @@ # See the License for the specific language governing permissions and # limitations under the License. -import typing as T +# Work around some pathlib bugs... +from mesonbuild import _pathlib +import sys +sys.modules['pathlib'] = _pathlib + +from concurrent.futures import ProcessPoolExecutor, CancelledError +from enum import Enum +from io import StringIO +from pathlib import Path, PurePath +import argparse +import functools import itertools +import json +import multiprocessing import os -import subprocess +import re +import shlex import shutil -import sys import signal -import shlex -from io import StringIO -from ast import literal_eval -from enum import Enum +import subprocess import tempfile -from pathlib import Path, PurePath +import time +import typing as T +import xml.etree.ElementTree as ET +import collections + from mesonbuild import build from mesonbuild import environment from mesonbuild import compilers from mesonbuild import mesonlib from mesonbuild import mlog from mesonbuild import mtest -from mesonbuild.mesonlib import MachineChoice, stringlistify, Popen_safe -from mesonbuild.coredata import backendlist -import argparse -import json -import xml.etree.ElementTree as ET -import time -import multiprocessing -from concurrent.futures import ProcessPoolExecutor, CancelledError -import re +from mesonbuild.compilers import compiler_from_language, detect_objc_compiler, detect_objcpp_compiler +from mesonbuild.build import ConfigurationData +from mesonbuild.mesonlib import MachineChoice, Popen_safe, TemporaryDirectoryWinProof, setup_vsenv +from mesonbuild.mlog import blue, bold, cyan, green, red, yellow, normal_green +from mesonbuild.coredata import backendlist, version as meson_version +from mesonbuild.modules.python import PythonExternalProgram from run_tests import get_fake_options, run_configure, get_meson_script from run_tests import get_backend_commands, get_backend_args_for_dir, Backend from run_tests import ensure_backend_detects_changes from run_tests import guess_backend -ALL_TESTS = ['cmake', 'common', 'warning-meson', 'failing-meson', 'failing-build', 'failing-test', - 'kconfig', 'platform-osx', 'platform-windows', 'platform-linux', - 'java', 'C#', 'vala', 'rust', 'd', 'objective c', 'objective c++', - 'fortran', 'swift', 'cuda', 'python3', 'python', 'fpga', 'frameworks', 'nasm', 'wasm' +if T.TYPE_CHECKING: + from types import FrameType + from mesonbuild.environment import Environment + from mesonbuild._typing import Protocol + from concurrent.futures import Future + from mesonbuild.modules.python import PythonIntrospectionDict + + class CompilerArgumentType(Protocol): + cross_file: str + native_file: str + use_tmpdir: bool + + + class ArgumentType(CompilerArgumentType): + + """Typing information for command line arguments.""" + + extra_args: T.List[str] + backend: str + num_workers: int + failfast: bool + no_unittests: bool + only: T.List[str] + +ALL_TESTS = ['cmake', 'common', 'native', 'warning-meson', 'failing-meson', 'failing-build', 'failing-test', + 'keyval', 'platform-osx', 'platform-windows', 'platform-linux', + 'java', 'C#', 'vala', 'cython', 'rust', 'd', 'objective c', 'objective c++', + 'fortran', 'swift', 'cuda', 'python3', 'python', 'fpga', 'frameworks', 'nasm', 'wasm', ] @@ -63,87 +97,237 @@ validate = 6 -class TestResult: - def __init__(self, msg, step, stdo, stde, mlog, cicmds, conftime=0, buildtime=0, testtime=0): - self.msg = msg - self.step = step - self.stdo = stdo - self.stde = stde - self.mlog = mlog +class TestResult(BaseException): + def __init__(self, cicmds: T.List[str]) -> None: + self.msg = '' # empty msg indicates test success + self.stdo = '' + self.stde = '' + self.mlog = '' self.cicmds = cicmds - self.conftime = conftime - self.buildtime = buildtime - self.testtime = testtime + self.conftime: float = 0 + self.buildtime: float = 0 + self.testtime: float = 0 + + def add_step(self, step: BuildStep, stdo: str, stde: str, mlog: str = '', time: float = 0) -> None: + self.step = step + self.stdo += stdo + self.stde += stde + self.mlog += mlog + if step == BuildStep.configure: + self.conftime = time + elif step == BuildStep.build: + self.buildtime = time + elif step == BuildStep.test: + self.testtime = time + + def fail(self, msg: str) -> None: + self.msg = msg + +python = PythonExternalProgram(sys.executable) +python.sanity() + +class InstalledFile: + def __init__(self, raw: T.Dict[str, str]): + self.path = raw['file'] + self.typ = raw['type'] + self.platform = raw.get('platform', None) + self.language = raw.get('language', 'c') # type: str + + version = raw.get('version', '') # type: str + if version: + self.version = version.split('.') # type: T.List[str] + else: + # split on '' will return [''], we want an empty list though + self.version = [] + + def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Path]: + p = Path(self.path) + canonical_compiler = compiler + if ((compiler in ['clang-cl', 'intel-cl']) or + (env.machines.host.is_windows() and compiler in {'pgi', 'dmd', 'ldc'})): + canonical_compiler = 'msvc' + + python_suffix = python.info['suffix'] + + has_pdb = False + if self.language in {'c', 'cpp'}: + has_pdb = canonical_compiler == 'msvc' + elif self.language == 'd': + # dmd's optlink does not genearte pdb iles + has_pdb = env.coredata.compilers.host['d'].linker.id in {'link', 'lld-link'} + + # Abort if the platform does not match + matches = { + 'msvc': canonical_compiler == 'msvc', + 'gcc': canonical_compiler != 'msvc', + 'cygwin': env.machines.host.is_cygwin(), + '!cygwin': not env.machines.host.is_cygwin(), + }.get(self.platform or '', True) + if not matches: + return None + # Handle the different types + if self.typ in {'py_implib', 'python_lib', 'python_file'}: + val = p.as_posix() + val = val.replace('@PYTHON_PLATLIB@', python.platlib) + val = val.replace('@PYTHON_PURELIB@', python.purelib) + p = Path(val) + if self.typ == 'python_file': + return p + if self.typ == 'python_lib': + return p.with_suffix(python_suffix) + if self.typ in ['file', 'dir']: + return p + elif self.typ == 'shared_lib': + if env.machines.host.is_windows() or env.machines.host.is_cygwin(): + # Windows only has foo.dll and foo-X.dll + if len(self.version) > 1: + return None + if self.version: + p = p.with_name('{}-{}'.format(p.name, self.version[0])) + return p.with_suffix('.dll') + + p = p.with_name(f'lib{p.name}') + if env.machines.host.is_darwin(): + # MacOS only has libfoo.dylib and libfoo.X.dylib + if len(self.version) > 1: + return None + + # pathlib.Path.with_suffix replaces, not appends + suffix = '.dylib' + if self.version: + suffix = '.{}{}'.format(self.version[0], suffix) + else: + # pathlib.Path.with_suffix replaces, not appends + suffix = '.so' + if self.version: + suffix = '{}.{}'.format(suffix, '.'.join(self.version)) + return p.with_suffix(suffix) + elif self.typ == 'exe': + if env.machines.host.is_windows() or env.machines.host.is_cygwin(): + return p.with_suffix('.exe') + elif self.typ == 'pdb': + if self.version: + p = p.with_name('{}-{}'.format(p.name, self.version[0])) + return p.with_suffix('.pdb') if has_pdb else None + elif self.typ in {'implib', 'implibempty', 'py_implib'}: + if env.machines.host.is_windows() and canonical_compiler == 'msvc': + # only MSVC doesn't generate empty implibs + if self.typ == 'implibempty' and compiler == 'msvc': + return None + return p.parent / (re.sub(r'^lib', '', p.name) + '.lib') + elif env.machines.host.is_windows() or env.machines.host.is_cygwin(): + if self.typ == 'py_implib': + p = p.with_suffix(python_suffix) + return p.with_suffix('.dll.a') + else: + return None + elif self.typ == 'expr': + return Path(platform_fix_name(p.as_posix(), canonical_compiler, env)) + else: + raise RuntimeError(f'Invalid installed file type {self.typ}') + + return p + + def get_paths(self, compiler: str, env: environment.Environment, installdir: Path) -> T.List[Path]: + p = self.get_path(compiler, env) + if not p: + return [] + if self.typ == 'dir': + abs_p = installdir / p + if not abs_p.exists(): + raise RuntimeError(f'{p} does not exist') + if not abs_p.is_dir(): + raise RuntimeError(f'{p} is not a directory') + return [x.relative_to(installdir) for x in abs_p.rglob('*') if x.is_file() or x.is_symlink()] + else: + return [p] +@functools.total_ordering class TestDef: def __init__(self, path: Path, name: T.Optional[str], args: T.List[str], skip: bool = False): + self.category = path.parts[1] self.path = path self.name = name self.args = args self.skip = skip + self.env = os.environ.copy() + self.installed_files = [] # type: T.List[InstalledFile] + self.do_not_set_opts = [] # type: T.List[str] + self.stdout = [] # type: T.List[T.Dict[str, str]] + self.skip_expected = False + + # Always print a stack trace for Meson exceptions + self.env['MESON_FORCE_BACKTRACE'] = '1' def __repr__(self) -> str: return '<{}: {:<48} [{}: {}] -- {}>'.format(type(self).__name__, str(self.path), self.name, self.args, self.skip) - def display_name(self) -> str: + def display_name(self) -> mlog.TV_LoggableList: + # Remove the redundant 'test cases' part + section, id = self.path.parts[1:3] + res: mlog.TV_LoggableList = [f'{section}:', bold(id)] if self.name: - return '{} ({})'.format(self.path.as_posix(), self.name) - return self.path.as_posix() + res += [f' ({self.name})'] + return res -class AutoDeletedDir: - def __init__(self, d): - self.dir = d - - def __enter__(self): - os.makedirs(self.dir, exist_ok=True) - return self.dir - - def __exit__(self, _type, value, traceback): - # We don't use tempfile.TemporaryDirectory, but wrap the - # deletion in the AutoDeletedDir class because - # it fails on Windows due antivirus programs - # holding files open. - mesonlib.windows_proof_rmtree(self.dir) + def __lt__(self, other: object) -> bool: + if isinstance(other, TestDef): + # None is not sortable, so replace it with an empty string + s_id = int(self.path.name.split(' ')[0]) + o_id = int(other.path.name.split(' ')[0]) + return (s_id, self.path, self.name or '') < (o_id, other.path, other.name or '') + return NotImplemented -failing_logs = [] +failing_logs: T.List[str] = [] print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ under_ci = 'CI' in os.environ -under_old_os_ci = 'OLD_OS_CI' in os.environ +ci_jobname = os.environ.get('MESON_CI_JOBNAME', None) do_debug = under_ci or print_debug no_meson_log_msg = 'No meson-log.txt found.' -system_compiler = None +host_c_compiler: T.Optional[str] = None +compiler_id_map: T.Dict[str, str] = {} +tool_vers_map: T.Dict[str, str] = {} + +compile_commands: T.List[str] +clean_commands: T.List[str] +test_commands: T.List[str] +install_commands: T.List[str] +uninstall_commands: T.List[str] + +backend: 'Backend' +backend_flags: T.List[str] + +stop: bool = False +is_worker_process: bool = False + +# Let's have colors in our CI output +if under_ci: + def _ci_colorize_console() -> bool: + return not is_worker_process + + mlog.colorize_console = _ci_colorize_console class StopException(Exception): - def __init__(self): + def __init__(self) -> None: super().__init__('Stopped by user') -stop = False -def stop_handler(signal, frame): +def stop_handler(signal: int, frame: T.Optional['FrameType']) -> None: global stop stop = True signal.signal(signal.SIGINT, stop_handler) signal.signal(signal.SIGTERM, stop_handler) -def setup_commands(optbackend): +def setup_commands(optbackend: str) -> None: global do_debug, backend, backend_flags global compile_commands, clean_commands, test_commands, install_commands, uninstall_commands backend, backend_flags = guess_backend(optbackend, shutil.which('msbuild')) compile_commands, clean_commands, test_commands, install_commands, \ uninstall_commands = get_backend_commands(backend, do_debug) -def get_relative_files_list_from_dir(fromdir: Path) -> T.List[Path]: - return [file.relative_to(fromdir) for file in fromdir.rglob('*') if file.is_file()] - -def platform_fix_name(fname: str, compiler, env) -> str: - # canonicalize compiler - if (compiler in {'clang-cl', 'intel-cl'} or - (env.machines.host.is_windows() and compiler == 'pgi')): - canonical_compiler = 'msvc' - else: - canonical_compiler = compiler - +# TODO try to eliminate or at least reduce this function +def platform_fix_name(fname: str, canonical_compiler: str, env: environment.Environment) -> str: if '?lib' in fname: if env.machines.host.is_windows() and canonical_compiler == 'msvc': fname = re.sub(r'lib/\?lib(.*)\.', r'bin/\1.', fname) @@ -160,31 +344,6 @@ else: fname = re.sub(r'\?lib', 'lib', fname) - if fname.endswith('?exe'): - fname = fname[:-4] - if env.machines.host.is_windows() or env.machines.host.is_cygwin(): - return fname + '.exe' - - if fname.startswith('?msvc:'): - fname = fname[6:] - if canonical_compiler != 'msvc': - return None - - if fname.startswith('?gcc:'): - fname = fname[5:] - if canonical_compiler == 'msvc': - return None - - if fname.startswith('?cygwin:'): - fname = fname[8:] - if not env.machines.host.is_cygwin(): - return None - - if fname.startswith('?!cygwin:'): - fname = fname[9:] - if env.machines.host.is_cygwin(): - return None - if fname.endswith('?so'): if env.machines.host.is_windows() and canonical_compiler == 'msvc': fname = re.sub(r'lib/([^/]*)\?so$', r'bin/\1.dll', fname) @@ -204,106 +363,62 @@ else: return fname[:-3] + '.so' - if fname.endswith('?implib') or fname.endswith('?implibempty'): - if env.machines.host.is_windows() and canonical_compiler == 'msvc': - # only MSVC doesn't generate empty implibs - if fname.endswith('?implibempty') and compiler == 'msvc': - return None - return re.sub(r'/(?:lib|)([^/]*?)\?implib(?:empty|)$', r'/\1.lib', fname) - elif env.machines.host.is_windows() or env.machines.host.is_cygwin(): - return re.sub(r'\?implib(?:empty|)$', r'.dll.a', fname) - else: - return None - return fname -def validate_install(srcdir: str, installdir: Path, compiler, env) -> str: - # List of installed files - info_file = Path(srcdir) / 'installed_files.txt' - installdir = Path(installdir) - # If this exists, the test does not install any other files - noinst_file = Path('usr/no-installed-files') - expected = {} # type: T.Dict[Path, bool] +def validate_install(test: TestDef, installdir: Path, env: environment.Environment) -> str: ret_msg = '' - # Generate list of expected files - if (installdir / noinst_file).is_file(): - expected[noinst_file] = False - elif info_file.is_file(): - with info_file.open() as f: - for line in f: - line = platform_fix_name(line.strip(), compiler, env) - if line: - expected[Path(line)] = False - # Check if expected files were found - for fname in expected: - file_path = installdir / fname - if file_path.is_file() or file_path.is_symlink(): - expected[fname] = True - for (fname, found) in expected.items(): - if not found: - ret_msg += 'Expected file {} missing.\n'.format(fname) - # Check if there are any unexpected files - found = get_relative_files_list_from_dir(installdir) + expected_raw = [] # type: T.List[Path] + for i in test.installed_files: + try: + expected_raw += i.get_paths(host_c_compiler, env, installdir) + except RuntimeError as err: + ret_msg += f'Expected path error: {err}\n' + expected = {x: False for x in expected_raw} + found = [x.relative_to(installdir) for x in installdir.rglob('*') if x.is_file() or x.is_symlink()] + # Mark all found files as found and detect unexpected files for fname in found: if fname not in expected: - ret_msg += 'Extra file {} found.\n'.format(fname) + ret_msg += f'Extra file {fname} found.\n' + continue + expected[fname] = True + # Check if expected files were found + for p, f in expected.items(): + if not f: + ret_msg += f'Expected file {p} missing.\n' + # List dir content on error if ret_msg != '': ret_msg += '\nInstall dir contents:\n' - for i in found: - ret_msg += ' - {}'.format(i) + for p in found: + ret_msg += f' - {p}\n' return ret_msg -def log_text_file(logfile, testdir, stdo, stde): - global stop, executor, futures +def log_text_file(logfile: T.TextIO, testdir: Path, result: TestResult) -> None: logfile.write('%s\nstdout\n\n---\n' % testdir.as_posix()) - logfile.write(stdo) + logfile.write(result.stdo) logfile.write('\n\n---\n\nstderr\n\n---\n') - logfile.write(stde) + logfile.write(result.stde) logfile.write('\n\n---\n\n') if print_debug: try: - print(stdo) + print(result.stdo) except UnicodeError: - sanitized_out = stdo.encode('ascii', errors='replace').decode() + sanitized_out = result.stdo.encode('ascii', errors='replace').decode() print(sanitized_out) try: - print(stde, file=sys.stderr) + print(result.stde, file=sys.stderr) except UnicodeError: - sanitized_err = stde.encode('ascii', errors='replace').decode() + sanitized_err = result.stde.encode('ascii', errors='replace').decode() print(sanitized_err, file=sys.stderr) - if stop: - print("Aborting..") - for f in futures: - f[2].cancel() - executor.shutdown() - raise StopException() - - -def bold(text): - return mlog.bold(text).get_text(mlog.colorize_console) - - -def green(text): - return mlog.green(text).get_text(mlog.colorize_console) - - -def red(text): - return mlog.red(text).get_text(mlog.colorize_console) - - -def yellow(text): - return mlog.yellow(text).get_text(mlog.colorize_console) def _run_ci_include(args: T.List[str]) -> str: if not args: return 'At least one parameter required' try: - file_path = Path(args[0]) - data = file_path.open(errors='ignore', encoding='utf-8').read() + data = Path(args[0]).read_text(errors='ignore', encoding='utf-8') return 'Included file {}:\n{}\n'.format(args[0], data) except Exception: - return 'Failed to open {} ({})'.format(args[0]) + return 'Failed to open {}'.format(args[0]) ci_commands = { 'ci_include': _run_ci_include @@ -320,8 +435,101 @@ res += ['CI COMMAND {}:\n{}\n'.format(cmd[0], ci_commands[cmd[0]](cmd[1:]))] return res +class OutputMatch: + def __init__(self, how: str, expected: str, count: int) -> None: + self.how = how + self.expected = expected + self.count = count + + def match(self, actual: str) -> bool: + if self.how == "re": + return bool(re.match(self.expected, actual)) + return self.expected == actual + +def _compare_output(expected: T.List[T.Dict[str, str]], output: str, desc: str) -> str: + if expected: + matches: T.List[OutputMatch] = [] + nomatches: T.List[OutputMatch] = [] + for item in expected: + how = item.get('match', 'literal') + expected_line = item.get('line') + count = int(item.get('count', -1)) + + # Simple heuristic to automatically convert path separators for + # Windows: + # + # Any '/' appearing before 'WARNING' or 'ERROR' (i.e. a path in a + # filename part of a location) is replaced with '\' (in a re: '\\' + # which matches a literal '\') + # + # (There should probably be a way to turn this off for more complex + # cases which don't fit this) + if mesonlib.is_windows(): + if how != "re": + sub = r'\\' + else: + sub = r'\\\\' + expected_line = re.sub(r'/(?=.*(WARNING|ERROR))', sub, expected_line) -def run_test_inprocess(testdir): + m = OutputMatch(how, expected_line, count) + if count == 0: + nomatches.append(m) + else: + matches.append(m) + + + i = 0 + for actual in output.splitlines(): + # Verify this line does not match any unexpected lines (item.count == 0) + for match in nomatches: + if match.match(actual): + return f'unexpected "{match.expected}" found in {desc}' + # If we matched all expected lines, continue to verify there are + # no unexpected line. If nomatches is empty then we are done already. + if i >= len(matches): + if not nomatches: + break + continue + # Check if this line match current expected line + match = matches[i] + if match.match(actual): + if match.count < 0: + # count was not specified, continue with next expected line, + # it does not matter if this line will be matched again or + # not. + i += 1 + else: + # count was specified (must be >0), continue expecting this + # same line. If count reached 0 we continue with next + # expected line but remember that this one must not match + # anymore. + match.count -= 1 + if match.count == 0: + nomatches.append(match) + i += 1 + + if i < len(matches): + # reached the end of output without finding expected + return f'expected "{matches[i].expected}" not found in {desc}' + + return '' + +def validate_output(test: TestDef, stdo: str, stde: str) -> str: + return _compare_output(test.stdout, stdo, 'stdout') + +# There are some class variables and such that cache +# information. Clear all of these. The better solution +# would be to change the code so that no state is persisted +# but that would be a lot of work given that Meson was originally +# coded to run as a batch process. +def clear_internal_caches() -> None: + import mesonbuild.interpreterbase + from mesonbuild.dependencies import CMakeDependency + from mesonbuild.mesonlib import PerMachine + mesonbuild.interpreterbase.FeatureNew.feature_registry = {} + CMakeDependency.class_cmakeinfo = PerMachine(None, None) + +def run_test_inprocess(testdir: str) -> T.Tuple[int, str, str, str]: old_stdout = sys.stdout sys.stdout = mystdout = StringIO() old_stderr = sys.stderr @@ -332,7 +540,7 @@ try: returncode_test = mtest.run_with_args(['--no-rebuild']) if test_log_fname.exists(): - test_log = test_log_fname.open(errors='ignore').read() + test_log = test_log_fname.open(encoding='utf-8', errors='ignore').read() else: test_log = '' returncode_benchmark = mtest.run_with_args(['--no-rebuild', '--benchmark', '--logbase', 'benchmarklog']) @@ -342,208 +550,371 @@ os.chdir(old_cwd) return max(returncode_test, returncode_benchmark), mystdout.getvalue(), mystderr.getvalue(), test_log -def parse_test_args(testdir): - args = [] - try: - with open(os.path.join(testdir, 'test_args.txt'), 'r') as f: - content = f.read() - try: - args = literal_eval(content) - except Exception: - raise Exception('Malformed test_args file.') - args = stringlistify(args) - except FileNotFoundError: - pass - return args - # Build directory name must be the same so Ccache works over # consecutive invocations. -def create_deterministic_builddir(src_dir, name): +def create_deterministic_builddir(test: TestDef, use_tmpdir: bool) -> str: import hashlib - if name: - src_dir += name + src_dir = test.path.as_posix() + if test.name: + src_dir += test.name rel_dirname = 'b ' + hashlib.sha256(src_dir.encode(errors='ignore')).hexdigest()[0:10] - os.mkdir(rel_dirname) - abs_pathname = os.path.join(os.getcwd(), rel_dirname) + abs_pathname = os.path.join(tempfile.gettempdir() if use_tmpdir else os.getcwd(), rel_dirname) + if os.path.exists(abs_pathname): + mesonlib.windows_proof_rmtree(abs_pathname) + os.mkdir(abs_pathname) return abs_pathname -def run_test(skipped, testdir, name, extra_args, compiler, backend, flags, commands, should_fail): - if skipped: - return None - with AutoDeletedDir(create_deterministic_builddir(testdir, name)) as build_dir: - with AutoDeletedDir(tempfile.mkdtemp(prefix='i ', dir=os.getcwd())) as install_dir: +def format_parameter_file(file_basename: str, test: TestDef, test_build_dir: str) -> Path: + confdata = ConfigurationData() + confdata.values = {'MESON_TEST_ROOT': (str(test.path.absolute()), 'base directory of current test')} + + template = test.path / (file_basename + '.in') + destination = Path(test_build_dir) / file_basename + mesonlib.do_conf_file(str(template), str(destination), confdata, 'meson') + + return destination + +def detect_parameter_files(test: TestDef, test_build_dir: str) -> T.Tuple[Path, Path]: + nativefile = test.path / 'nativefile.ini' + crossfile = test.path / 'crossfile.ini' + + if os.path.exists(str(test.path / 'nativefile.ini.in')): + nativefile = format_parameter_file('nativefile.ini', test, test_build_dir) + + if os.path.exists(str(test.path / 'crossfile.ini.in')): + crossfile = format_parameter_file('crossfile.ini', test, test_build_dir) + + return nativefile, crossfile + +# In previous python versions the global variables are lost in ProcessPoolExecutor. +# So, we use this tuple to restore some of them +class GlobalState(T.NamedTuple): + compile_commands: T.List[str] + clean_commands: T.List[str] + test_commands: T.List[str] + install_commands: T.List[str] + uninstall_commands: T.List[str] + + backend: 'Backend' + backend_flags: T.List[str] + + host_c_compiler: T.Optional[str] + +def run_test(test: TestDef, + extra_args: T.List[str], + should_fail: str, + use_tmp: bool, + state: T.Optional[GlobalState] = None) -> T.Optional[TestResult]: + # Unpack the global state + global compile_commands, clean_commands, test_commands, install_commands, uninstall_commands, backend, backend_flags, host_c_compiler + if state is not None: + compile_commands, clean_commands, test_commands, install_commands, uninstall_commands, backend, backend_flags, host_c_compiler = state + # Store that this is a worker process + global is_worker_process + is_worker_process = True + # Setup the test environment + assert not test.skip, 'Skipped test should not be run' + build_dir = create_deterministic_builddir(test, use_tmp) + try: + with TemporaryDirectoryWinProof(prefix='i ', dir=None if use_tmp else os.getcwd()) as install_dir: try: - return _run_test(testdir, build_dir, install_dir, extra_args, compiler, backend, flags, commands, should_fail) + return _run_test(test, build_dir, install_dir, extra_args, should_fail) + except TestResult as r: + return r finally: mlog.shutdown() # Close the log file because otherwise Windows wets itself. + finally: + mesonlib.windows_proof_rmtree(build_dir) -def pass_prefix_to_test(dirname): - if '39 prefix absolute' in dirname: - return False - return True - -def pass_libdir_to_test(dirname): - if '8 install' in dirname: - return False - if '38 libdir must be inside prefix' in dirname: - return False - if '195 install_mode' in dirname: - return False - return True - -def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backend, flags, commands, should_fail): - compile_commands, clean_commands, install_commands, uninstall_commands = commands - test_args = parse_test_args(testdir) +def _run_test(test: TestDef, + test_build_dir: str, + install_dir: str, + extra_args: T.List[str], + should_fail: str) -> TestResult: gen_start = time.time() - setup_env = None # Configure in-process - if pass_prefix_to_test(testdir): - gen_args = ['--prefix', '/usr'] - else: - gen_args = [] - if pass_libdir_to_test(testdir): + gen_args = [] # type: T.List[str] + if 'prefix' not in test.do_not_set_opts: + gen_args += ['--prefix', 'x:/usr'] if mesonlib.is_windows() else ['--prefix', '/usr'] + if 'libdir' not in test.do_not_set_opts: gen_args += ['--libdir', 'lib'] - gen_args += [testdir, test_build_dir] + flags + test_args + extra_args - nativefile = os.path.join(testdir, 'nativefile.ini') - if os.path.exists(nativefile): - gen_args.extend(['--native-file', nativefile]) - crossfile = os.path.join(testdir, 'crossfile.ini') - if os.path.exists(crossfile): - gen_args.extend(['--cross-file', crossfile]) - setup_env_file = os.path.join(testdir, 'setup_env.json') - if os.path.exists(setup_env_file): - setup_env = os.environ.copy() - with open(setup_env_file, 'r') as fp: - data = json.load(fp) - for key, val in data.items(): - val = val.replace('@ROOT@', os.path.abspath(testdir)) - setup_env[key] = val - (returncode, stdo, stde) = run_configure(gen_args, env=setup_env) + gen_args += [test.path.as_posix(), test_build_dir] + backend_flags + extra_args + + nativefile, crossfile = detect_parameter_files(test, test_build_dir) + + if nativefile.exists(): + gen_args.extend(['--native-file', nativefile.as_posix()]) + if crossfile.exists(): + gen_args.extend(['--cross-file', crossfile.as_posix()]) + (returncode, stdo, stde) = run_configure(gen_args, env=test.env, catch_exception=True) try: logfile = Path(test_build_dir, 'meson-logs', 'meson-log.txt') mesonlog = logfile.open(errors='ignore', encoding='utf-8').read() except Exception: mesonlog = no_meson_log_msg cicmds = run_ci_commands(mesonlog) - gen_time = time.time() - gen_start + testresult = TestResult(cicmds) + testresult.add_step(BuildStep.configure, stdo, stde, mesonlog, time.time() - gen_start) + output_msg = validate_output(test, stdo, stde) + testresult.mlog += output_msg + if output_msg: + testresult.fail('Unexpected output while configuring.') + return testresult if should_fail == 'meson': if returncode == 1: - return TestResult('', BuildStep.configure, stdo, stde, mesonlog, cicmds, gen_time) + return testresult elif returncode != 0: - return TestResult('Test exited with unexpected status {}'.format(returncode), BuildStep.configure, stdo, stde, mesonlog, cicmds, gen_time) + testresult.fail(f'Test exited with unexpected status {returncode}.') + return testresult else: - return TestResult('Test that should have failed succeeded', BuildStep.configure, stdo, stde, mesonlog, cicmds, gen_time) + testresult.fail('Test that should have failed succeeded.') + return testresult if returncode != 0: - return TestResult('Generating the build system failed.', BuildStep.configure, stdo, stde, mesonlog, cicmds, gen_time) + testresult.fail('Generating the build system failed.') + return testresult builddata = build.load(test_build_dir) - # Touch the meson.build file to force a regenerate so we can test that - # regeneration works before a build is run. - ensure_backend_detects_changes(backend) - os.utime(os.path.join(testdir, 'meson.build')) - # Build with subprocess dir_args = get_backend_args_for_dir(backend, test_build_dir) - build_start = time.time() - pc, o, e = Popen_safe(compile_commands + dir_args, cwd=test_build_dir) - build_time = time.time() - build_start - stdo += o - stde += e - if should_fail == 'build': + + # Build with subprocess + def build_step() -> None: + build_start = time.time() + pc, o, e = Popen_safe(compile_commands + dir_args, cwd=test_build_dir) + testresult.add_step(BuildStep.build, o, e, '', time.time() - build_start) + if should_fail == 'build': + if pc.returncode != 0: + raise testresult + testresult.fail('Test that should have failed to build succeeded.') + raise testresult if pc.returncode != 0: - return TestResult('', BuildStep.build, stdo, stde, mesonlog, cicmds, gen_time) - return TestResult('Test that should have failed to build succeeded', BuildStep.build, stdo, stde, mesonlog, cicmds, gen_time) - if pc.returncode != 0: - return TestResult('Compiling source code failed.', BuildStep.build, stdo, stde, mesonlog, cicmds, gen_time, build_time) - # Touch the meson.build file to force a regenerate so we can test that - # regeneration works after a build is complete. - ensure_backend_detects_changes(backend) - os.utime(os.path.join(testdir, 'meson.build')) - test_start = time.time() + testresult.fail('Compiling source code failed.') + raise testresult + + # Touch the meson.build file to force a regenerate + def force_regenerate() -> None: + ensure_backend_detects_changes(backend) + os.utime(str(test.path / 'meson.build')) + + # just test building + build_step() + + # test that regeneration works for build step + force_regenerate() + build_step() # TBD: assert nothing gets built after the regenerate? + + # test that regeneration works for test step + force_regenerate() + # Test in-process + clear_internal_caches() + test_start = time.time() (returncode, tstdo, tstde, test_log) = run_test_inprocess(test_build_dir) - test_time = time.time() - test_start - stdo += tstdo - stde += tstde - mesonlog += test_log + testresult.add_step(BuildStep.test, tstdo, tstde, test_log, time.time() - test_start) if should_fail == 'test': if returncode != 0: - return TestResult('', BuildStep.test, stdo, stde, mesonlog, cicmds, gen_time) - return TestResult('Test that should have failed to run unit tests succeeded', BuildStep.test, stdo, stde, mesonlog, cicmds, gen_time) + return testresult + testresult.fail('Test that should have failed to run unit tests succeeded.') + return testresult if returncode != 0: - return TestResult('Running unit tests failed.', BuildStep.test, stdo, stde, mesonlog, cicmds, gen_time, build_time, test_time) + testresult.fail('Running unit tests failed.') + return testresult + # Do installation, if the backend supports it if install_commands: - env = os.environ.copy() + env = test.env.copy() env['DESTDIR'] = install_dir # Install with subprocess pi, o, e = Popen_safe(install_commands, cwd=test_build_dir, env=env) - stdo += o - stde += e + testresult.add_step(BuildStep.install, o, e) if pi.returncode != 0: - return TestResult('Running install failed.', BuildStep.install, stdo, stde, mesonlog, cicmds, gen_time, build_time, test_time) + testresult.fail('Running install failed.') + return testresult + # Clean with subprocess - env = os.environ.copy() + env = test.env.copy() pi, o, e = Popen_safe(clean_commands + dir_args, cwd=test_build_dir, env=env) - stdo += o - stde += e + testresult.add_step(BuildStep.clean, o, e) if pi.returncode != 0: - return TestResult('Running clean failed.', BuildStep.clean, stdo, stde, mesonlog, cicmds, gen_time, build_time, test_time) - if not install_commands: - return TestResult('', BuildStep.install, '', '', mesonlog, cicmds, gen_time, build_time, test_time) - return TestResult(validate_install(testdir, install_dir, compiler, builddata.environment), - BuildStep.validate, stdo, stde, mesonlog, cicmds, gen_time, build_time, test_time) - -def gather_tests(testdir: Path) -> T.List[TestDef]: - tests = [t.name for t in testdir.glob('*') if t.is_dir()] - tests = [t for t in tests if not t.startswith('.')] # Filter non-tests files (dot files, etc) - tests = [TestDef(testdir / t, None, []) for t in tests] - all_tests = [] - for t in tests: - matrix_file = t.path / 'test_matrix.json' - if not matrix_file.is_file(): - all_tests += [t] - continue + testresult.fail('Running clean failed.') + return testresult - # Build multiple tests from matrix definition - opt_list = [] # type: T.List[T.List[T.Tuple[str, bool]]] - matrix = json.loads(matrix_file.read_text()) - assert "options" in matrix - for key, val in matrix["options"].items(): - assert isinstance(val, list) - tmp_opts = [] # type: T.List[T.Tuple[str, bool]] - for i in val: - assert isinstance(i, dict) - assert "val" in i - skip = False - - # Skip the matrix entry if environment variable is present - if 'skip_on_env' in i: - for env in i['skip_on_env']: - if env in os.environ: - skip = True - - tmp_opts += [('{}={}'.format(key, i['val']), skip)] - - if opt_list: - new_opt_list = [] # type: T.List[T.List[T.Tuple[str, bool]]] - for i in opt_list: - for j in tmp_opts: - new_opt_list += [[*i, j]] - opt_list = new_opt_list + # Validate installed files + testresult.add_step(BuildStep.install, '', '') + if not install_commands: + return testresult + install_msg = validate_install(test, Path(install_dir), builddata.environment) + if install_msg: + testresult.fail('\n' + install_msg) + return testresult + + return testresult + + +# processing of test.json 'skip_*' keys, which can appear at top level, or in +# matrix: +def _skip_keys(test_def: T.Dict) -> T.Tuple[bool, bool]: + skip_expected = False + + # Test is expected to skip if MESON_CI_JOBNAME contains any of the list of + # substrings + if ('skip_on_jobname' in test_def) and (ci_jobname is not None): + skip_expected = any(s in ci_jobname for s in test_def['skip_on_jobname']) + + # Test is expected to skip if os matches + if 'skip_on_os' in test_def: + mesonenv = environment.Environment(None, None, get_fake_options('/')) + for skip_os in test_def['skip_on_os']: + if skip_os.startswith('!'): + if mesonenv.machines.host.system != skip_os[1:]: + skip_expected = True else: - opt_list = [[x] for x in tmp_opts] + if mesonenv.machines.host.system == skip_os: + skip_expected = True + + # Skip if environment variable is present + skip = False + if 'skip_on_env' in test_def: + for skip_env_var in test_def['skip_on_env']: + if skip_env_var in os.environ: + skip = True + + return (skip, skip_expected) + + +def load_test_json(t: TestDef, stdout_mandatory: bool) -> T.List[TestDef]: + all_tests: T.List[TestDef] = [] + test_def = {} + test_def_file = t.path / 'test.json' + if test_def_file.is_file(): + test_def = json.loads(test_def_file.read_text(encoding='utf-8')) + + # Handle additional environment variables + env = {} # type: T.Dict[str, str] + if 'env' in test_def: + assert isinstance(test_def['env'], dict) + env = test_def['env'] + for key, val in env.items(): + val = val.replace('@ROOT@', t.path.resolve().as_posix()) + val = val.replace('@PATH@', t.env.get('PATH', '')) + env[key] = val + + # Handle installed files + installed = [] # type: T.List[InstalledFile] + if 'installed' in test_def: + installed = [InstalledFile(x) for x in test_def['installed']] + + # Handle expected output + stdout = test_def.get('stdout', []) + if stdout_mandatory and not stdout: + raise RuntimeError(f"{test_def_file} must contain a non-empty stdout key") + + # Handle the do_not_set_opts list + do_not_set_opts = test_def.get('do_not_set_opts', []) # type: T.List[str] + + (t.skip, t.skip_expected) = _skip_keys(test_def) + + # Skip tests if the tool requirements are not met + if 'tools' in test_def: + assert isinstance(test_def['tools'], dict) + for tool, vers_req in test_def['tools'].items(): + if tool not in tool_vers_map: + t.skip = True + elif not mesonlib.version_compare(tool_vers_map[tool], vers_req): + t.skip = True + + # Skip the matrix code and just update the existing test + if 'matrix' not in test_def: + t.env.update(env) + t.installed_files = installed + t.do_not_set_opts = do_not_set_opts + t.stdout = stdout + return [t] + + new_opt_list: T.List[T.List[T.Tuple[str, bool, bool]]] + + # 'matrix; entry is present, so build multiple tests from matrix definition + opt_list = [] # type: T.List[T.List[T.Tuple[str, bool, bool]]] + matrix = test_def['matrix'] + assert "options" in matrix + for key, val in matrix["options"].items(): + assert isinstance(val, list) + tmp_opts = [] # type: T.List[T.Tuple[str, bool, bool]] + for i in val: + assert isinstance(i, dict) + assert "val" in i + + (skip, skip_expected) = _skip_keys(i) + + # Only run the test if all compiler ID's match + if 'compilers' in i: + for lang, id_list in i['compilers'].items(): + if lang not in compiler_id_map or compiler_id_map[lang] not in id_list: + skip = True + break + + # Add an empty matrix entry + if i['val'] is None: + tmp_opts += [(None, skip, skip_expected)] + continue + tmp_opts += [('{}={}'.format(key, i['val']), skip, skip_expected)] + + if opt_list: + new_opt_list = [] + for i in opt_list: + for j in tmp_opts: + new_opt_list += [[*i, j]] + opt_list = new_opt_list + else: + opt_list = [[x] for x in tmp_opts] + + # Exclude specific configurations + if 'exclude' in matrix: + assert isinstance(matrix['exclude'], list) + new_opt_list = [] for i in opt_list: - name = ' '.join([x[0] for x in i]) - opts = ['-D' + x[0] for x in i] - skip = any([x[1] for x in i]) - all_tests += [TestDef(t.path, name, opts, skip)] - - all_tests = [(int(t.path.name.split()[0]), t.name or '', t) for t in all_tests] - all_tests.sort() - all_tests = [t[2] for t in all_tests] + exclude = False + opt_names = [x[0] for x in i] + for j in matrix['exclude']: + ex_list = [f'{k}={v}' for k, v in j.items()] + if all([x in opt_names for x in ex_list]): + exclude = True + break + + if not exclude: + new_opt_list += [i] + + opt_list = new_opt_list + + for i in opt_list: + name = ' '.join([x[0] for x in i if x[0] is not None]) + opts = ['-D' + x[0] for x in i if x[0] is not None] + skip = any([x[1] for x in i]) + skip_expected = any([x[2] for x in i]) + test = TestDef(t.path, name, opts, skip or t.skip) + test.env.update(env) + test.installed_files = installed + test.do_not_set_opts = do_not_set_opts + test.stdout = stdout + test.skip_expected = skip_expected or t.skip_expected + all_tests.append(test) + return all_tests -def have_d_compiler(): + +def gather_tests(testdir: Path, stdout_mandatory: bool, only: T.List[str]) -> T.List[TestDef]: + all_tests: T.List[TestDef] = [] + for t in testdir.iterdir(): + # Filter non-tests files (dot files, etc) + if not t.is_dir() or t.name.startswith('.'): + continue + if only and not any(t.name.startswith(prefix) for prefix in only): + continue + test_def = TestDef(t, None, []) + all_tests.extend(load_test_json(test_def, stdout_mandatory)) + return sorted(all_tests) + + +def have_d_compiler() -> bool: if shutil.which("ldc2"): return True elif shutil.which("ldc"): @@ -562,11 +933,11 @@ return True return False -def have_objc_compiler(): - with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: +def have_objc_compiler(use_tmp: bool) -> bool: + with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir: env = environment.Environment(None, build_dir, get_fake_options('/')) try: - objc_comp = env.detect_objc_compiler(MachineChoice.HOST) + objc_comp = detect_objc_compiler(env, MachineChoice.HOST) except mesonlib.MesonException: return False if not objc_comp: @@ -578,11 +949,11 @@ return False return True -def have_objcpp_compiler(): - with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: +def have_objcpp_compiler(use_tmp: bool) -> bool: + with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir: env = environment.Environment(None, build_dir, get_fake_options('/')) try: - objcpp_comp = env.detect_objcpp_compiler(MachineChoice.HOST) + objcpp_comp = detect_objcpp_compiler(env, MachineChoice.HOST) except mesonlib.MesonException: return False if not objcpp_comp: @@ -594,56 +965,26 @@ return False return True -def have_java(): +def have_java() -> bool: if shutil.which('javac') and shutil.which('java'): return True return False -def skippable(suite, test): - # Everything is optional when not running on CI, or on Ubuntu 16.04 CI - if not under_ci or under_old_os_ci: - return True - - if not suite.endswith('frameworks'): - return True - - # gtk-doc test may be skipped, pending upstream fixes for spaces in - # filenames landing in the distro used for CI - if test.endswith('10 gtk-doc'): - return True - - # NetCDF is not in the CI Docker image - if test.endswith('netcdf'): +def skip_dont_care(t: TestDef) -> bool: + # Everything is optional when not running on CI + if not under_ci: return True - # MSVC doesn't link with GFortran - if test.endswith('14 fortran links c'): + # Non-frameworks test are allowed to determine their own skipping under CI (currently) + if not t.category.endswith('frameworks'): return True - # Blocks are not supported on all compilers - if test.endswith('29 blocks'): + if mesonlib.is_osx() and '6 gettext' in str(t.path): return True - # No frameworks test should be skipped on linux CI, as we expect all - # prerequisites to be installed - if mesonlib.is_linux(): - return False - - # Boost test should only be skipped for windows CI build matrix entries - # which don't define BOOST_ROOT - if test.endswith('1 boost'): - if mesonlib.is_windows(): - return 'BOOST_ROOT' not in os.environ - return False - - # Qt is provided on macOS by Homebrew - if test.endswith('4 qt') and mesonlib.is_osx(): - return False - - # Other framework tests are allowed to be skipped on other platforms - return True + return False -def skip_csharp(backend) -> bool: +def skip_csharp(backend: Backend) -> bool: if backend is not Backend.ninja: return True if not shutil.which('resgen'): @@ -669,18 +1010,17 @@ # on all compilation attempts. def has_broken_rustc() -> bool: - dirname = 'brokenrusttest' - if os.path.exists(dirname): - mesonlib.windows_proof_rmtree(dirname) - os.mkdir(dirname) - open(dirname + '/sanity.rs', 'w').write('''fn main() { -} -''') + dirname = Path('brokenrusttest') + if dirname.exists(): + mesonlib.windows_proof_rmtree(dirname.as_posix()) + dirname.mkdir() + sanity_file = dirname / 'sanity.rs' + sanity_file.write_text('fn main() {\n}\n', encoding='utf-8') pc = subprocess.run(['rustc', '-o', 'sanity.exe', 'sanity.rs'], - cwd=dirname, + cwd=dirname.as_posix(), stdout = subprocess.DEVNULL, stderr = subprocess.DEVNULL) - mesonlib.windows_proof_rmtree(dirname) + mesonlib.windows_proof_rmtree(dirname.as_posix()) return pc.returncode != 0 def should_skip_rust(backend: Backend) -> bool: @@ -688,15 +1028,16 @@ return True if backend is not Backend.ninja: return True - if mesonlib.is_windows() and has_broken_rustc(): - return True + if mesonlib.is_windows(): + if has_broken_rustc(): + return True return False -def detect_tests_to_run(only: T.List[str]) -> T.List[T.Tuple[str, T.List[TestDef], bool]]: +def detect_tests_to_run(only: T.Dict[str, T.List[str]], use_tmp: bool) -> T.List[T.Tuple[str, T.List[TestDef], bool]]: """ Parameters ---------- - only: list of str, optional + only: dict of categories and list of test cases, optional specify names of tests to run Returns @@ -708,105 +1049,162 @@ skip_fortran = not(shutil.which('gfortran') or shutil.which('flang') or shutil.which('pgfortran') or + shutil.which('nagfor') or shutil.which('ifort')) - # Name, subdirectory, skip condition. + class TestCategory: + def __init__(self, category: str, subdir: str, skip: bool = False, stdout_mandatory: bool = False): + self.category = category # category name + self.subdir = subdir # subdirectory + self.skip = skip # skip condition + self.stdout_mandatory = stdout_mandatory # expected stdout is mandatory for tests in this category + all_tests = [ - ('cmake', 'cmake', not shutil.which('cmake') or (os.environ.get('compiler') == 'msvc2015' and under_ci)), - ('common', 'common', False), - ('warning-meson', 'warning', False), - ('failing-meson', 'failing', False), - ('failing-build', 'failing build', False), - ('failing-test', 'failing test', False), - ('kconfig', 'kconfig', False), - - ('platform-osx', 'osx', not mesonlib.is_osx()), - ('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()), - ('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()), - - ('java', 'java', backend is not Backend.ninja or mesonlib.is_osx() or not have_java()), - ('C#', 'csharp', skip_csharp(backend)), - ('vala', 'vala', backend is not Backend.ninja or not shutil.which(os.environ.get('VALAC', 'valac'))), - ('rust', 'rust', should_skip_rust(backend)), - ('d', 'd', backend is not Backend.ninja or not have_d_compiler()), - ('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler()), - ('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler()), - ('fortran', 'fortran', skip_fortran or backend != Backend.ninja), - ('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')), + TestCategory('cmake', 'cmake', not shutil.which('cmake') or (os.environ.get('compiler') == 'msvc2015' and under_ci)), + TestCategory('common', 'common'), + TestCategory('native', 'native'), + TestCategory('warning-meson', 'warning', stdout_mandatory=True), + TestCategory('failing-meson', 'failing', stdout_mandatory=True), + TestCategory('failing-build', 'failing build'), + TestCategory('failing-test', 'failing test'), + TestCategory('keyval', 'keyval'), + TestCategory('platform-osx', 'osx', not mesonlib.is_osx()), + TestCategory('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()), + TestCategory('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()), + TestCategory('java', 'java', backend is not Backend.ninja or mesonlib.is_osx() or not have_java()), + TestCategory('C#', 'csharp', skip_csharp(backend)), + TestCategory('vala', 'vala', backend is not Backend.ninja or not shutil.which(os.environ.get('VALAC', 'valac'))), + TestCategory('cython', 'cython', backend is not Backend.ninja or not shutil.which(os.environ.get('CYTHON', 'cython'))), + TestCategory('rust', 'rust', should_skip_rust(backend)), + TestCategory('d', 'd', backend is not Backend.ninja or not have_d_compiler()), + TestCategory('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler(options.use_tmpdir)), + TestCategory('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler(options.use_tmpdir)), + TestCategory('fortran', 'fortran', skip_fortran or backend != Backend.ninja), + TestCategory('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')), # CUDA tests on Windows: use Ninja backend: python run_project_tests.py --only cuda --backend ninja - ('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')), - ('python3', 'python3', backend is not Backend.ninja), - ('python', 'python', backend is not Backend.ninja), - ('fpga', 'fpga', shutil.which('yosys') is None), - ('frameworks', 'frameworks', False), - ('nasm', 'nasm', False), - ('wasm', 'wasm', shutil.which('emcc') is None or backend is not Backend.ninja), + TestCategory('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')), + TestCategory('python3', 'python3', backend is not Backend.ninja), + TestCategory('python', 'python'), + TestCategory('fpga', 'fpga', shutil.which('yosys') is None), + TestCategory('frameworks', 'frameworks'), + TestCategory('nasm', 'nasm'), + TestCategory('wasm', 'wasm', shutil.which('emcc') is None or backend is not Backend.ninja), ] - names = [t[0] for t in all_tests] - assert names == ALL_TESTS, 'argparse("--only", choices=ALL_TESTS) need to be updated to match all_tests names' + categories = [t.category for t in all_tests] + assert categories == ALL_TESTS, 'argparse("--only", choices=ALL_TESTS) need to be updated to match all_tests categories' + if only: - ind = [names.index(o) for o in only] - all_tests = [all_tests[i] for i in ind] - gathered_tests = [(name, gather_tests(Path('test cases', subdir)), skip) for name, subdir, skip in all_tests] + for key in only.keys(): + assert key in categories, f'key `{key}` is not a recognized category' + all_tests = [t for t in all_tests if t.category in only.keys()] + + gathered_tests = [(t.category, gather_tests(Path('test cases', t.subdir), t.stdout_mandatory, only[t.category]), t.skip) for t in all_tests] return gathered_tests def run_tests(all_tests: T.List[T.Tuple[str, T.List[TestDef], bool]], - log_name_base: str, failfast: bool, - extra_args: T.List[str]) -> T.Tuple[int, int, int]: - global logfile + log_name_base: str, + failfast: bool, + extra_args: T.List[str], + use_tmp: bool, + num_workers: int) -> T.Tuple[int, int, int]: txtname = log_name_base + '.txt' with open(txtname, 'w', encoding='utf-8', errors='ignore') as lf: - logfile = lf - return _run_tests(all_tests, log_name_base, failfast, extra_args) + return _run_tests(all_tests, log_name_base, failfast, extra_args, use_tmp, num_workers, lf) + +class TestStatus(Enum): + OK = normal_green(' [SUCCESS] ') + SKIP = yellow(' [SKIPPED] ') + ERROR = red(' [ERROR] ') + UNEXSKIP = red('[UNEXSKIP] ') + UNEXRUN = red(' [UNEXRUN] ') + CANCELED = cyan('[CANCELED] ') + RUNNING = blue(' [RUNNING] ') # Should never be actually printed + LOG = bold(' [LOG] ') # Should never be actually printed + +def default_print(*args: mlog.TV_Loggable, sep: str = ' ') -> None: + print(*args, sep=sep) + +safe_print = default_print + +class TestRunFuture: + def __init__(self, name: str, testdef: TestDef, future: T.Optional['Future[T.Optional[TestResult]]']) -> None: + super().__init__() + self.name = name + self.testdef = testdef + self.future = future + self.status = TestStatus.RUNNING if self.future is not None else TestStatus.SKIP + + @property + def result(self) -> T.Optional[TestResult]: + return self.future.result() if self.future else None + + def log(self) -> None: + without_install = '' if install_commands else '(without install)' + safe_print(self.status.value, without_install, *self.testdef.display_name()) + + def update_log(self, new_status: TestStatus) -> None: + self.status = new_status + self.log() + + def cancel(self) -> None: + if self.future is not None and self.future.cancel(): + self.status = TestStatus.CANCELED + +class LogRunFuture: + def __init__(self, msgs: mlog.TV_LoggableList) -> None: + self.msgs = msgs + self.status = TestStatus.LOG + + def log(self) -> None: + safe_print(*self.msgs, sep='') + + def cancel(self) -> None: + pass + +RunFutureUnion = T.Union[TestRunFuture, LogRunFuture] def _run_tests(all_tests: T.List[T.Tuple[str, T.List[TestDef], bool]], - log_name_base: str, failfast: bool, - extra_args: T.List[str]) -> T.Tuple[int, int, int]: - global stop, executor, futures, system_compiler + log_name_base: str, + failfast: bool, + extra_args: T.List[str], + use_tmp: bool, + num_workers: int, + logfile: T.TextIO) -> T.Tuple[int, int, int]: + global stop, host_c_compiler xmlname = log_name_base + '.xml' junit_root = ET.Element('testsuites') - conf_time = 0 - build_time = 0 - test_time = 0 + conf_time: float = 0 + build_time: float = 0 + test_time: float = 0 passing_tests = 0 failing_tests = 0 skipped_tests = 0 - commands = (compile_commands, clean_commands, install_commands, uninstall_commands) - try: - # This fails in some CI environments for unknown reasons. - num_workers = multiprocessing.cpu_count() - except Exception as e: - print('Could not determine number of CPUs due to the following reason:' + str(e)) - print('Defaulting to using only one process') - num_workers = 1 - # Due to Ninja deficiency, almost 50% of build time - # is spent waiting. Do something useful instead. - # - # Remove this once the following issue has been resolved: - # https://github.com/mesonbuild/meson/pull/2082 - if not mesonlib.is_windows(): # twice as fast on Windows by *not* multiplying by 2. - num_workers *= 2 + print(f'\nRunning tests with {num_workers} workers') + + # Pack the global state + state = (compile_commands, clean_commands, test_commands, install_commands, uninstall_commands, backend, backend_flags, host_c_compiler) executor = ProcessPoolExecutor(max_workers=num_workers) + futures: T.List[RunFutureUnion] = [] + + # First, collect and start all tests and also queue log messages for name, test_cases, skipped in all_tests: current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))}) - print() if skipped: - print(bold('Not running %s tests.' % name)) + futures += [LogRunFuture(['\n', bold(f'Not running {name} tests.'), '\n'])] else: - print(bold('Running %s tests.' % name)) - print() - futures = [] + futures += [LogRunFuture(['\n', bold(f'Running {name} tests.'), '\n'])] + for t in test_cases: # Jenkins screws us over by automatically sorting test cases by name # and getting it wrong by not doing logical number sorting. (testnum, testbase) = t.path.name.split(' ', 1) testname = '%.3d %s' % (int(testnum), testbase) if t.name: - testname += ' ({})'.format(t.name) - should_fail = False + testname += f' ({t.name})' + should_fail = '' suite_args = [] if name.startswith('failing'): should_fail = name.split('failing-')[1] @@ -814,227 +1212,364 @@ suite_args = ['--fatal-meson-warnings'] should_fail = name.split('warning-')[1] - result = executor.submit(run_test, skipped or t.skip, t.path.as_posix(), t.name, extra_args + suite_args + t.args, - system_compiler, backend, backend_flags, commands, should_fail) - futures.append((testname, t, result)) - for (testname, t, result) in futures: - sys.stdout.flush() - try: - result = result.result() - except CancelledError: + if skipped or t.skip: + futures += [TestRunFuture(testname, t, None)] continue - if (result is None) or (('MESON_SKIP_TEST' in result.stdo) and (skippable(name, t.path.as_posix()))): - print(yellow('Skipping:'), t.display_name()) - current_test = ET.SubElement(current_suite, 'testcase', {'name': testname, - 'classname': name}) - ET.SubElement(current_test, 'skipped', {}) - skipped_tests += 1 - else: - without_install = "" if len(install_commands) > 0 else " (without install)" - if result.msg != '': - print(red('Failed test{} during {}: {!r}'.format(without_install, result.step.name, t.display_name()))) - print('Reason:', result.msg) - failing_tests += 1 - if result.step == BuildStep.configure and result.mlog != no_meson_log_msg: - # For configure failures, instead of printing stdout, - # print the meson log if available since it's a superset - # of stdout and often has very useful information. - failing_logs.append(result.mlog) - elif under_ci: - # Always print the complete meson log when running in - # a CI. This helps debugging issues that only occur in - # a hard to reproduce environment - failing_logs.append(result.mlog) - failing_logs.append(result.stdo) - else: - failing_logs.append(result.stdo) - for cmd_res in result.cicmds: - failing_logs.append(cmd_res) - failing_logs.append(result.stde) - if failfast: - print("Cancelling the rest of the tests") - for (_, _, res) in futures: - res.cancel() - else: - print('Succeeded test%s: %s' % (without_install, t.display_name())) - passing_tests += 1 - conf_time += result.conftime - build_time += result.buildtime - test_time += result.testtime - total_time = conf_time + build_time + test_time - log_text_file(logfile, t.path, result.stdo, result.stde) - current_test = ET.SubElement(current_suite, 'testcase', {'name': testname, - 'classname': name, - 'time': '%.3f' % total_time}) - if result.msg != '': - ET.SubElement(current_test, 'failure', {'message': result.msg}) - stdoel = ET.SubElement(current_test, 'system-out') - stdoel.text = result.stdo - stdeel = ET.SubElement(current_test, 'system-err') - stdeel.text = result.stde - - if failfast and failing_tests > 0: - break - - print("\nTotal configuration time: %.2fs" % conf_time) - print("Total build time: %.2fs" % build_time) - print("Total test time: %.2fs" % test_time) - ET.ElementTree(element=junit_root).write(xmlname, xml_declaration=True, encoding='UTF-8') - return passing_tests, failing_tests, skipped_tests + result_future = executor.submit(run_test, t, extra_args + suite_args + t.args, should_fail, use_tmp, state=state) + futures += [TestRunFuture(testname, t, result_future)] + + # Ensure we only cancel once + tests_canceled = False -def check_file(file: Path): - lines = file.read_bytes().split(b'\n') - tabdetector = re.compile(br' *\t') - for i, line in enumerate(lines): - if re.match(tabdetector, line): - raise SystemExit("File {} contains a tab indent on line {:d}. Only spaces are permitted.".format(file, i + 1)) - if line.endswith(b'\r'): - raise SystemExit("File {} contains DOS line ending on line {:d}. Only unix-style line endings are permitted.".format(file, i + 1)) - -def check_format(): - check_suffixes = {'.c', - '.cpp', - '.cxx', - '.cc', - '.rs', - '.f90', - '.vala', - '.d', - '.s', - '.m', - '.mm', - '.asm', - '.java', - '.txt', - '.py', - '.swift', - '.build', - '.md', - } - for (root, _, filenames) in os.walk('.'): - if '.dub' in root: # external deps are here + # Optionally enable the tqdm progress bar + global safe_print + futures_iter: T.Iterable[RunFutureUnion] = futures + try: + from tqdm import tqdm + futures_iter = tqdm(futures, desc='Running tests', unit='test') + + def tqdm_print(*args: mlog.TV_Loggable, sep: str = ' ') -> None: + tqdm.write(sep.join([str(x) for x in args])) + + safe_print = tqdm_print + except ImportError: + pass + + # Wait and handle the test results and print the stored log output + for f in futures_iter: + # Just a log entry to print something to stdout + sys.stdout.flush() + if isinstance(f, LogRunFuture): + f.log() continue - if '.pytest_cache' in root: + + # Actual Test run + testname = f.name + t = f.testdef + try: + result = f.result + except (CancelledError, KeyboardInterrupt): + f.status = TestStatus.CANCELED + + if stop and not tests_canceled: + num_running = sum(1 if f2.status is TestStatus.RUNNING else 0 for f2 in futures) + for f2 in futures: + f2.cancel() + executor.shutdown() + num_canceled = sum(1 if f2.status is TestStatus.CANCELED else 0 for f2 in futures) + safe_print(f'\nCanceled {num_canceled} out of {num_running} running tests.') + safe_print(f'Finishing the remaining {num_running - num_canceled} tests.\n') + tests_canceled = True + + # Handle canceled tests + if f.status is TestStatus.CANCELED: + f.log() continue - if 'meson-logs' in root or 'meson-private' in root: + + # Handle skipped tests + if result is None: + # skipped due to skipped category skip or 'tools:' or 'skip_on_env:' + is_skipped = True + skip_as_expected = True + else: + # skipped due to test outputting 'MESON_SKIP_TEST' + is_skipped = 'MESON_SKIP_TEST' in result.stdo + if not skip_dont_care(t): + skip_as_expected = (is_skipped == t.skip_expected) + else: + skip_as_expected = True + + if is_skipped: + skipped_tests += 1 + + if is_skipped and skip_as_expected: + f.update_log(TestStatus.SKIP) + current_test = ET.SubElement(current_suite, 'testcase', {'name': testname, 'classname': t.category}) + ET.SubElement(current_test, 'skipped', {}) continue - if '.eggs' in root or '_cache' in root: # e.g. .mypy_cache + + if not skip_as_expected: + failing_tests += 1 + if is_skipped: + skip_msg = 'Test asked to be skipped, but was not expected to' + status = TestStatus.UNEXSKIP + else: + skip_msg = 'Test ran, but was expected to be skipped' + status = TestStatus.UNEXRUN + result.msg = f"{skip_msg} for MESON_CI_JOBNAME '{ci_jobname}'" + + f.update_log(status) + current_test = ET.SubElement(current_suite, 'testcase', {'name': testname, 'classname': t.category}) + ET.SubElement(current_test, 'failure', {'message': result.msg}) continue - for fname in filenames: - file = Path(fname) - if file.suffix.lower() in check_suffixes: - if file.name in ('sitemap.txt', 'meson-test-run.txt'): - continue - check_file(root / file) -def check_meson_commands_work(): + # Handle Failed tests + if result.msg != '': + f.update_log(TestStatus.ERROR) + safe_print(bold('During:'), result.step.name) + safe_print(bold('Reason:'), result.msg) + failing_tests += 1 + # Append a visual separator for the different test cases + cols = shutil.get_terminal_size((100, 20)).columns + name_str = ' '.join([str(x) for x in f.testdef.display_name()]) + name_len = len(re.sub(r'\x1B[^m]+m', '', name_str)) # Do not count escape sequences + left_w = (cols // 2) - (name_len // 2) - 1 + left_w = max(3, left_w) + right_w = cols - left_w - name_len - 2 + right_w = max(3, right_w) + failing_logs.append(f'\n\x1b[31m{"="*left_w}\x1b[0m {name_str} \x1b[31m{"="*right_w}\x1b[0m\n') + if result.step == BuildStep.configure and result.mlog != no_meson_log_msg: + # For configure failures, instead of printing stdout, + # print the meson log if available since it's a superset + # of stdout and often has very useful information. + failing_logs.append(result.mlog) + elif under_ci: + # Always print the complete meson log when running in + # a CI. This helps debugging issues that only occur in + # a hard to reproduce environment + failing_logs.append(result.mlog) + failing_logs.append(result.stdo) + else: + failing_logs.append(result.stdo) + for cmd_res in result.cicmds: + failing_logs.append(cmd_res) + failing_logs.append(result.stde) + if failfast: + safe_print("Cancelling the rest of the tests") + for f2 in futures: + f2.cancel() + else: + f.update_log(TestStatus.OK) + passing_tests += 1 + conf_time += result.conftime + build_time += result.buildtime + test_time += result.testtime + total_time = conf_time + build_time + test_time + log_text_file(logfile, t.path, result) + current_test = ET.SubElement( + current_suite, + 'testcase', + {'name': testname, 'classname': t.category, 'time': '%.3f' % total_time} + ) + if result.msg != '': + ET.SubElement(current_test, 'failure', {'message': result.msg}) + stdoel = ET.SubElement(current_test, 'system-out') + stdoel.text = result.stdo + stdeel = ET.SubElement(current_test, 'system-err') + stdeel.text = result.stde + + # Reset, just in case + safe_print = default_print + + print() + print("Total configuration time: %.2fs" % conf_time) + print("Total build time: %.2fs" % build_time) + print("Total test time: %.2fs" % test_time) + ET.ElementTree(element=junit_root).write(xmlname, xml_declaration=True, encoding='UTF-8') + return passing_tests, failing_tests, skipped_tests + +def check_meson_commands_work(use_tmpdir: bool, extra_args: T.List[str]) -> None: global backend, compile_commands, test_commands, install_commands testdir = PurePath('test cases', 'common', '1 trivial').as_posix() meson_commands = mesonlib.python_command + [get_meson_script()] - with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: + with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmpdir else '.') as build_dir: print('Checking that configuring works...') - gen_cmd = meson_commands + [testdir, build_dir] + backend_flags + gen_cmd = meson_commands + [testdir, build_dir] + backend_flags + extra_args pc, o, e = Popen_safe(gen_cmd) if pc.returncode != 0: - raise RuntimeError('Failed to configure {!r}:\n{}\n{}'.format(testdir, e, o)) + raise RuntimeError(f'Failed to configure {testdir!r}:\n{e}\n{o}') + print('Checking that introspect works...') + pc, o, e = Popen_safe(meson_commands + ['introspect', '--targets'], cwd=build_dir) + json.loads(o) + if pc.returncode != 0: + raise RuntimeError(f'Failed to introspect --targets {testdir!r}:\n{e}\n{o}') print('Checking that building works...') dir_args = get_backend_args_for_dir(backend, build_dir) pc, o, e = Popen_safe(compile_commands + dir_args, cwd=build_dir) if pc.returncode != 0: - raise RuntimeError('Failed to build {!r}:\n{}\n{}'.format(testdir, e, o)) + raise RuntimeError(f'Failed to build {testdir!r}:\n{e}\n{o}') print('Checking that testing works...') pc, o, e = Popen_safe(test_commands, cwd=build_dir) if pc.returncode != 0: - raise RuntimeError('Failed to test {!r}:\n{}\n{}'.format(testdir, e, o)) + raise RuntimeError(f'Failed to test {testdir!r}:\n{e}\n{o}') if install_commands: print('Checking that installing works...') pc, o, e = Popen_safe(install_commands, cwd=build_dir) if pc.returncode != 0: - raise RuntimeError('Failed to install {!r}:\n{}\n{}'.format(testdir, e, o)) + raise RuntimeError(f'Failed to install {testdir!r}:\n{e}\n{o}') -def detect_system_compiler(): - global system_compiler +def detect_system_compiler(options: 'CompilerArgumentType') -> None: + global host_c_compiler, compiler_id_map - with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: - env = environment.Environment(None, build_dir, get_fake_options('/')) - print() - for lang in sorted(compilers.all_languages): - try: - comp = env.compiler_from_language(lang, MachineChoice.HOST) - details = '%s %s' % (' '.join(comp.get_exelist()), comp.get_version_string()) - except mesonlib.MesonException: - comp = None - details = 'not found' - print('%-7s: %s' % (lang, details)) - - # note C compiler for later use by platform_fix_name() - if lang == 'c': - if comp: - system_compiler = comp.get_id() - else: - raise RuntimeError("Could not find C compiler.") - print() + fake_opts = get_fake_options('/') + if options.cross_file: + fake_opts.cross_file = [options.cross_file] + if options.native_file: + fake_opts.native_file = [options.native_file] + + env = environment.Environment(None, None, fake_opts) + + print_compilers(env, MachineChoice.HOST) + if options.cross_file: + print_compilers(env, MachineChoice.BUILD) -def print_tool_versions(): - tools = [ - { - 'tool': 'cmake', - 'args': ['--version'], - 'regex': re.compile(r'^cmake version ([0-9]+(\.[0-9]+)*)$'), - 'match_group': 1, - }, + for lang in sorted(compilers.all_languages): + try: + comp = compiler_from_language(env, lang, MachineChoice.HOST) + # note compiler id for later use with test.json matrix + compiler_id_map[lang] = comp.get_id() + except mesonlib.MesonException: + comp = None + + # note C compiler for later use by platform_fix_name() + if lang == 'c': + if comp: + host_c_compiler = comp.get_id() + else: + raise RuntimeError("Could not find C compiler.") + + +def print_compilers(env: 'Environment', machine: MachineChoice) -> None: + print() + print(f'{machine.get_lower_case_name()} machine compilers') + print() + for lang in sorted(compilers.all_languages): + try: + comp = compiler_from_language(env, lang, machine) + details = '{:<10} {} {}'.format('[' + comp.get_id() + ']', ' '.join(comp.get_exelist()), comp.get_version_string()) + except mesonlib.MesonException: + details = '[not found]' + print(f'{lang:<7}: {details}') + +class ToolInfo(T.NamedTuple): + tool: str + args: T.List[str] + regex: T.Pattern + match_group: int + +def print_tool_versions() -> None: + tools: T.List[ToolInfo] = [ + ToolInfo( + 'ninja', + ['--version'], + re.compile(r'^([0-9]+(\.[0-9]+)*(-[a-z0-9]+)?)$'), + 1, + ), + ToolInfo( + 'cmake', + ['--version'], + re.compile(r'^cmake version ([0-9]+(\.[0-9]+)*(-[a-z0-9]+)?)$'), + 1, + ), + ToolInfo( + 'hotdoc', + ['--version'], + re.compile(r'^([0-9]+(\.[0-9]+)*(-[a-z0-9]+)?)$'), + 1, + ), ] - def get_version(t: dict) -> str: - exe = shutil.which(t['tool']) + def get_version(t: ToolInfo) -> str: + exe = shutil.which(t.tool) if not exe: return 'not found' - args = [t['tool']] + t['args'] + args = [t.tool] + t.args pc, o, e = Popen_safe(args) if pc.returncode != 0: - return '{} (invalid {} executable)'.format(exe, t['tool']) + return f'{exe} (invalid {t.tool} executable)' for i in o.split('\n'): i = i.strip('\n\r\t ') - m = t['regex'].match(i) + m = t.regex.match(i) if m is not None: - return '{} ({})'.format(exe, m.group(t['match_group'])) + tool_vers_map[t.tool] = m.group(t.match_group) + return '{} ({})'.format(exe, m.group(t.match_group)) - return '{} (unknown)'.format(exe) + return f'{exe} (unknown)' + + print() + print('tools') + print() - max_width = max([len(x['tool']) for x in tools] + [7]) + max_width = max([len(x.tool) for x in tools] + [7]) for tool in tools: - print('{0:<{2}}: {1}'.format(tool['tool'], get_version(tool), max_width)) + print('{0:<{2}}: {1}'.format(tool.tool, get_version(tool), max_width)) print() +def clear_transitive_files() -> None: + a = Path('test cases/common') + for d in a.glob('*subproject subdir/subprojects/subsubsub*'): + if d.is_dir(): + mesonlib.windows_proof_rmtree(str(d)) + else: + mesonlib.windows_proof_rm(str(d)) + if __name__ == '__main__': + if under_ci and not ci_jobname: + raise SystemExit('Running under CI but MESON_CI_JOBNAME is not set') + + setup_vsenv() + + try: + # This fails in some CI environments for unknown reasons. + num_workers = multiprocessing.cpu_count() + except Exception as e: + print('Could not determine number of CPUs due to the following reason:' + str(e)) + print('Defaulting to using only two processes') + num_workers = 2 + parser = argparse.ArgumentParser(description="Run the test suite of Meson.") parser.add_argument('extra_args', nargs='*', help='arguments that are passed directly to Meson (remember to have -- before these).') parser.add_argument('--backend', dest='backend', choices=backendlist) + parser.add_argument('-j', dest='num_workers', type=int, default=num_workers, + help=f'Maximum number of parallel tests (default {num_workers})') parser.add_argument('--failfast', action='store_true', help='Stop running if test case fails') parser.add_argument('--no-unittests', action='store_true', help='Not used, only here to simplify run_tests.py') - parser.add_argument('--only', help='name of test(s) to run', nargs='+', choices=ALL_TESTS) - options = parser.parse_args() + parser.add_argument('--only', default=[], + help='name of test(s) to run, in format "category[/name]" where category is one of: ' + ', '.join(ALL_TESTS), nargs='+') + parser.add_argument('--cross-file', action='store', help='File describing cross compilation environment.') + parser.add_argument('--native-file', action='store', help='File describing native compilation environment.') + parser.add_argument('--use-tmpdir', action='store_true', help='Use tmp directory for temporary files.') + options = T.cast('ArgumentType', parser.parse_args()) + + if options.cross_file: + options.extra_args += ['--cross-file', options.cross_file] + if options.native_file: + options.extra_args += ['--native-file', options.native_file] + + clear_transitive_files() + + print('Meson build system', meson_version, 'Project Tests') + print('Using python', sys.version.split('\n')[0]) + if 'VSCMD_VER' in os.environ: + print('VSCMD version', os.environ['VSCMD_VER']) setup_commands(options.backend) - - detect_system_compiler() + detect_system_compiler(options) print_tool_versions() script_dir = os.path.split(__file__)[0] if script_dir != '': os.chdir(script_dir) - check_format() - check_meson_commands_work() + check_meson_commands_work(options.use_tmpdir, options.extra_args) + only = collections.defaultdict(list) + for i in options.only: + try: + cat, case = i.split('/') + only[cat].append(case) + except ValueError: + only[i].append('') try: - all_tests = detect_tests_to_run(options.only) - (passing_tests, failing_tests, skipped_tests) = run_tests(all_tests, 'meson-test-run', options.failfast, options.extra_args) + all_tests = detect_tests_to_run(only, options.use_tmpdir) + res = run_tests(all_tests, 'meson-test-run', options.failfast, options.extra_args, options.use_tmpdir, options.num_workers) + (passing_tests, failing_tests, skipped_tests) = res except StopException: pass - print('\nTotal passed tests:', green(str(passing_tests))) - print('Total failed tests:', red(str(failing_tests))) + print() + print('Total passed tests: ', green(str(passing_tests))) + print('Total failed tests: ', red(str(failing_tests))) print('Total skipped tests:', yellow(str(skipped_tests))) if failing_tests > 0: print('\nMesonlogs of failing tests\n') @@ -1044,9 +1579,10 @@ except UnicodeError: print(l.encode('ascii', errors='replace').decode(), '\n') for name, dirs, _ in all_tests: - dir_names = list(set(x.path.name for x in dirs)) + dir_names = list({x.path.name for x in dirs}) for k, g in itertools.groupby(dir_names, key=lambda x: x.split()[0]): tests = list(g) if len(tests) != 1: - print('WARNING: The %s suite contains duplicate "%s" tests: "%s"' % (name, k, '", "'.join(tests))) + print('WARNING: The {} suite contains duplicate "{}" tests: "{}"'.format(name, k, '", "'.join(tests))) + clear_transitive_files() raise SystemExit(failing_tests) diff -Nru meson-0.53.2/run_tests.py meson-0.61.2/run_tests.py --- meson-0.53.2/run_tests.py 2020-02-25 18:00:46.000000000 +0000 +++ meson-0.61.2/run_tests.py 2022-01-17 10:50:38.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2012-2017 The Meson development team +# Copyright 2012-2021 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. @@ -14,18 +14,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os +# Work around some pathlib bugs... +from mesonbuild import _pathlib import sys +sys.modules['pathlib'] = _pathlib + +import collections +import os import time import shutil import subprocess -import tempfile import platform import argparse +import traceback from io import StringIO from enum import Enum from glob import glob from pathlib import Path +from unittest import mock +import typing as T + from mesonbuild import compilers from mesonbuild import dependencies from mesonbuild import mesonlib @@ -33,30 +41,50 @@ from mesonbuild import mtest from mesonbuild import mlog from mesonbuild.environment import Environment, detect_ninja -from mesonbuild.coredata import backendlist +from mesonbuild.coredata import backendlist, version as meson_version +from mesonbuild.mesonlib import OptionKey, setup_vsenv NINJA_1_9_OR_NEWER = False +NINJA_CMD = None +# If we're on CI, just assume we have ninja in PATH and it's new enough because +# we provide that. This avoids having to detect ninja for every subprocess unit +# test that we run. +if 'CI' in os.environ: + NINJA_1_9_OR_NEWER = True + NINJA_CMD = ['ninja'] +else: + # Look for 1.9 to see if https://github.com/ninja-build/ninja/issues/1219 + # is fixed + NINJA_CMD = detect_ninja('1.9') + if NINJA_CMD is not None: + NINJA_1_9_OR_NEWER = True + else: + mlog.warning('Found ninja <1.9, tests will run slower', once=True) + NINJA_CMD = detect_ninja() +if NINJA_CMD is None: + raise RuntimeError('Could not find Ninja v1.7 or newer') -def guess_backend(backend, msbuild_exe: str): +def guess_backend(backend_str: str, msbuild_exe: str) -> T.Tuple['Backend', T.List[str]]: # Auto-detect backend if unspecified backend_flags = [] - if backend is None: + if backend_str is None: if msbuild_exe is not None and (mesonlib.is_windows() and not _using_intelcl()): - backend = 'vs' # Meson will auto-detect VS version to use + backend_str = 'vs' # Meson will auto-detect VS version to use else: - backend = 'ninja' + backend_str = 'ninja' + # Set backend arguments for Meson - if backend.startswith('vs'): - backend_flags = ['--backend=' + backend] + if backend_str.startswith('vs'): + backend_flags = ['--backend=' + backend_str] backend = Backend.vs - elif backend == 'xcode': + elif backend_str == 'xcode': backend_flags = ['--backend=xcode'] backend = Backend.xcode - elif backend == 'ninja': + elif backend_str == 'ninja': backend_flags = ['--backend=ninja'] backend = Backend.ninja else: - raise RuntimeError('Unknown backend: {!r}'.format(backend)) + raise RuntimeError(f'Unknown backend: {backend_str!r}') return (backend, backend_flags) @@ -95,7 +123,8 @@ def __init__(self): self.value = [] -def get_fake_options(prefix=''): +# TODO: use a typing.Protocol here +def get_fake_options(prefix: str = '') -> argparse.Namespace: opts = argparse.Namespace() opts.native_file = [] opts.cross_file = None @@ -108,7 +137,7 @@ if opts is None: opts = get_fake_options(prefix) env = Environment(sdir, bdir, opts) - env.coredata.compiler_options.host['c_args'] = FakeCompilerOptions() + env.coredata.options[OptionKey('args', lang='c')] = FakeCompilerOptions() env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library return env @@ -125,7 +154,7 @@ else: exe_suffix = '' -def get_meson_script(): +def get_meson_script() -> str: ''' Guess the meson that corresponds to the `mesonbuild` that has been imported so we can run configure and other commands in-process, since mesonmain.run @@ -145,9 +174,9 @@ meson_cmd = shutil.which('meson') if meson_cmd: return meson_cmd - raise RuntimeError('Could not find {!r} or a meson in PATH'.format(meson_script)) + raise RuntimeError(f'Could not find {meson_script!r} or a meson in PATH') -def get_backend_args_for_dir(backend, builddir): +def get_backend_args_for_dir(backend: Backend, builddir: str) -> T.List[str]: ''' Visual Studio backend needs to be given the solution to build ''' @@ -160,18 +189,18 @@ import re, fnmatch t, ext = os.path.splitext(target) if ext: - p = r'{}\s*\{}'.format(t, ext) + p = fr'{t}\s*\{ext}' else: - p = r'{}'.format(t) + p = fr'{t}' for _, _, files in os.walk(builddir): for f in fnmatch.filter(files, '*.vcxproj'): f = os.path.join(builddir, f) - with open(f, 'r', encoding='utf-8') as o: + with open(f, encoding='utf-8') as o: if re.search(p, o.read(), flags=re.MULTILINE): return f - raise RuntimeError('No vcxproj matching {!r} in {!r}'.format(p, builddir)) + raise RuntimeError(f'No vcxproj matching {p!r} in {builddir!r}') -def get_builddir_target_args(backend, builddir, target): +def get_builddir_target_args(backend: Backend, builddir, target): dir_args = [] if not target: dir_args = get_backend_args_for_dir(backend, builddir) @@ -185,39 +214,27 @@ elif backend is Backend.ninja: target_args = [target] else: - raise AssertionError('Unknown backend: {!r}'.format(backend)) + raise AssertionError(f'Unknown backend: {backend!r}') return target_args + dir_args -def get_backend_commands(backend, debug=False): - install_cmd = [] - uninstall_cmd = [] +def get_backend_commands(backend: Backend, debug: bool = False) -> \ + T.Tuple[T.List[str], T.List[str], T.List[str], T.List[str], T.List[str]]: + install_cmd: T.List[str] = [] + uninstall_cmd: T.List[str] = [] + clean_cmd: T.List[str] + cmd: T.List[str] + test_cmd: T.List[str] if backend is Backend.vs: cmd = ['msbuild'] clean_cmd = cmd + ['/target:Clean'] test_cmd = cmd + ['RUN_TESTS.vcxproj'] elif backend is Backend.xcode: cmd = ['xcodebuild'] - # In Xcode9 new build system's clean command fails when using a custom build directory. - # Maybe use it when CI uses Xcode10 we can remove '-UseNewBuildSystem=FALSE' - clean_cmd = cmd + ['-alltargets', 'clean', '-UseNewBuildSystem=FALSE'] + clean_cmd = cmd + ['-alltargets', 'clean'] test_cmd = cmd + ['-target', 'RUN_TESTS'] elif backend is Backend.ninja: - global NINJA_1_9_OR_NEWER - # Look for 1.9 to see if https://github.com/ninja-build/ninja/issues/1219 - # is fixed, else require 1.6 for -w dupbuild=err - for v in ('1.9', '1.6'): - ninja_cmd = detect_ninja(v) - if ninja_cmd is not None: - if v == '1.9': - NINJA_1_9_OR_NEWER = True - else: - mlog.warning('Found ninja <1.9, tests will run slower', once=True) - if 'CI' in os.environ and 'OLD_OS_CI' not in os.environ: - raise RuntimeError('Require ninja >= 1.9 when running on Meson CI') - break - cmd = [ninja_cmd, '-w', 'dupbuild=err', '-d', 'explain'] - if cmd[0] is None: - raise RuntimeError('Could not find Ninja v1.6 or newer') + global NINJA_CMD + cmd = NINJA_CMD + ['-w', 'dupbuild=err', '-d', 'explain'] if debug: cmd += ['-v'] clean_cmd = cmd + ['clean'] @@ -225,21 +242,14 @@ install_cmd = cmd + ['install'] uninstall_cmd = cmd + ['uninstall'] else: - raise AssertionError('Unknown backend: {!r}'.format(backend)) + raise AssertionError(f'Unknown backend: {backend!r}') return cmd, clean_cmd, test_cmd, install_cmd, uninstall_cmd -def ensure_backend_detects_changes(backend): +def ensure_backend_detects_changes(backend: Backend) -> None: global NINJA_1_9_OR_NEWER if backend is not Backend.ninja: return need_workaround = False - # We're not running on HFS+ which only stores dates in seconds: - # https://developer.apple.com/legacy/library/technotes/tn/tn1150.html#HFSPlusDates - # XXX: Upgrade Travis image to Apple FS when that becomes available - # TODO: Detect HFS+ vs APFS - if mesonlib.is_osx(): - mlog.warning('Running on HFS+, enabling timestamp resolution workaround', once=True) - need_workaround = True # We're using ninja >= 1.9 which has QuLogic's patch for sub-1s resolution # timestamps if not NINJA_1_9_OR_NEWER: @@ -250,82 +260,67 @@ if need_workaround: time.sleep(1) -def run_mtest_inprocess(commandlist): - old_stdout = sys.stdout - sys.stdout = mystdout = StringIO() - old_stderr = sys.stderr - sys.stderr = mystderr = StringIO() - try: +def run_mtest_inprocess(commandlist: T.List[str]) -> T.Tuple[int, str, str]: + out = StringIO() + with mock.patch.object(sys, 'stdout', out), mock.patch.object(sys, 'stderr', out): returncode = mtest.run_with_args(commandlist) - finally: - sys.stdout = old_stdout - sys.stderr = old_stderr - return returncode, mystdout.getvalue(), mystderr.getvalue() - -def clear_meson_configure_class_caches(): - compilers.CCompiler.library_dirs_cache = {} - compilers.CCompiler.program_dirs_cache = {} + return returncode, stdout.getvalue() + +def clear_meson_configure_class_caches() -> None: compilers.CCompiler.find_library_cache = {} compilers.CCompiler.find_framework_cache = {} dependencies.PkgConfigDependency.pkgbin_cache = {} dependencies.PkgConfigDependency.class_pkgbin = mesonlib.PerMachine(None, None) + mesonlib.project_meson_versions = collections.defaultdict(str) -def run_configure_inprocess(commandlist, env=None): - old_stdout = sys.stdout - sys.stdout = mystdout = StringIO() - old_stderr = sys.stderr - sys.stderr = mystderr = StringIO() - old_environ = os.environ.copy() - if env is not None: - os.environ.update(env) - try: - returncode = mesonmain.run(commandlist, get_meson_script()) - finally: - sys.stdout = old_stdout - sys.stderr = old_stderr - clear_meson_configure_class_caches() - os.environ.clear() - os.environ.update(old_environ) - return returncode, mystdout.getvalue(), mystderr.getvalue() +def run_configure_inprocess(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[int, str, str]: + stderr = StringIO() + stdout = StringIO() + returncode = 0 + with mock.patch.dict(os.environ, env or {}), mock.patch.object(sys, 'stdout', stdout), mock.patch.object(sys, 'stderr', stderr): + try: + returncode = mesonmain.run(commandlist, get_meson_script()) + except Exception: + if catch_exception: + returncode = 1 + traceback.print_exc() + else: + raise + finally: + clear_meson_configure_class_caches() + return returncode, stdout.getvalue(), stderr.getvalue() -def run_configure_external(full_command, env=None): +def run_configure_external(full_command: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str, str]: pc, o, e = mesonlib.Popen_safe(full_command, env=env) return pc.returncode, o, e -def run_configure(commandlist, env=None): +def run_configure(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[int, str, str]: global meson_exe if meson_exe: return run_configure_external(meson_exe + commandlist, env=env) - return run_configure_inprocess(commandlist, env=env) + return run_configure_inprocess(commandlist, env=env, catch_exception=catch_exception) def print_system_info(): - print(mlog.bold('System information.').get_text(mlog.colorize_console)) + print(mlog.bold('System information.')) print('Architecture:', platform.architecture()) print('Machine:', platform.machine()) print('Platform:', platform.system()) print('Processor:', platform.processor()) print('System:', platform.system()) print('') + print(flush=True) def main(): print_system_info() parser = argparse.ArgumentParser() - parser.add_argument('--cov', action='store_true') parser.add_argument('--backend', default=None, dest='backend', choices=backendlist) - parser.add_argument('--cross', default=False, dest='cross', action='store_true') + parser.add_argument('--cross', default=[], dest='cross', action='append') + parser.add_argument('--cross-only', action='store_true') parser.add_argument('--failfast', action='store_true') parser.add_argument('--no-unittests', action='store_true', default=False) (options, _) = parser.parse_known_args() - # Enable coverage early... - enable_coverage = options.cov - if enable_coverage: - os.makedirs('.coverage', exist_ok=True) - sys.argv.remove('--cov') - import coverage - coverage.process_startup() returncode = 0 - cross = options.cross backend, _ = guess_backend(options.backend, shutil.which('msbuild')) no_unittests = options.no_unittests # Running on a developer machine? Be nice! @@ -346,59 +341,46 @@ if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86': os.environ.pop('platform') # Run tests - print(mlog.bold('Running unittests.').get_text(mlog.colorize_console)) - print(flush=True) # Can't pass arguments to unit tests, so set the backend to use in the environment env = os.environ.copy() - env['MESON_UNIT_TEST_BACKEND'] = backend.name - with tempfile.TemporaryDirectory() as temp_dir: - # Enable coverage on all subsequent processes. - if enable_coverage: - Path(temp_dir, 'usercustomize.py').open('w').write( - 'import coverage\n' - 'coverage.process_startup()\n') - env['COVERAGE_PROCESS_START'] = '.coveragerc' - if 'PYTHONPATH' in env: - env['PYTHONPATH'] = os.pathsep.join([temp_dir, env.get('PYTHONPATH')]) - else: - env['PYTHONPATH'] = temp_dir - if not cross: - cmd = mesonlib.python_command + ['run_meson_command_tests.py', '-v'] - if options.failfast: - cmd += ['--failfast'] - returncode += subprocess.call(cmd, env=env) - if options.failfast and returncode != 0: - return returncode - if no_unittests: - print('Skipping all unit tests.') - returncode = 0 - else: - cmd = mesonlib.python_command + ['run_unittests.py', '-v'] - if options.failfast: - cmd += ['--failfast'] - returncode += subprocess.call(cmd, env=env) - if options.failfast and returncode != 0: - return returncode - cmd = mesonlib.python_command + ['run_project_tests.py'] + sys.argv[1:] - returncode += subprocess.call(cmd, env=env) + if not options.cross: + cmd = mesonlib.python_command + ['run_meson_command_tests.py', '-v'] + if options.failfast: + cmd += ['--failfast'] + returncode += subprocess.call(cmd, env=env) + if options.failfast and returncode != 0: + return returncode + if no_unittests: + print('Skipping all unit tests.') + print(flush=True) + returncode = 0 else: - cross_test_args = mesonlib.python_command + ['run_cross_test.py'] - print(mlog.bold('Running armhf cross tests.').get_text(mlog.colorize_console)) + print(mlog.bold('Running unittests.')) print(flush=True) - cmd = cross_test_args + ['cross/ubuntu-armhf.txt'] + cmd = mesonlib.python_command + ['run_unittests.py', '--backend=' + backend.name, '-v'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode - print(mlog.bold('Running mingw-w64 64-bit cross tests.') - .get_text(mlog.colorize_console)) + cmd = mesonlib.python_command + ['run_project_tests.py'] + sys.argv[1:] + returncode += subprocess.call(cmd, env=env) + else: + cross_test_args = mesonlib.python_command + ['run_cross_test.py'] + for cf in options.cross: + print(mlog.bold(f'Running {cf} cross tests.')) print(flush=True) - cmd = cross_test_args + ['cross/linux-mingw-w64-64bit.txt'] + cmd = cross_test_args + ['cross/' + cf] if options.failfast: cmd += ['--failfast'] + if options.cross_only: + cmd += ['--cross-only'] returncode += subprocess.call(cmd, env=env) + if options.failfast and returncode != 0: + return returncode return returncode if __name__ == '__main__': - sys.exit(main()) + setup_vsenv() + print('Meson build system', meson_version, 'Project and Unit Tests') + raise SystemExit(main()) diff -Nru meson-0.53.2/run_unittests.py meson-0.61.2/run_unittests.py --- meson-0.53.2/run_unittests.py 2020-02-25 18:00:47.000000000 +0000 +++ meson-0.61.2/run_unittests.py 2022-02-14 19:03:13.000000000 +0000 @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright 2016-2017 The Meson development team +# Copyright 2016-2021 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. @@ -13,7220 +13,48 @@ # See the License for the specific language governing permissions and # limitations under the License. -import stat -import subprocess -import re -import json -import tempfile -import textwrap -import os -import shutil -import sys -import unittest -import platform -import pickle -import functools -import io -import operator -import threading -import urllib.error -import urllib.request -import zipfile -import hashlib -from itertools import chain -from unittest import mock -from configparser import ConfigParser -from contextlib import contextmanager -from glob import glob -from pathlib import (PurePath, Path) -from distutils.dir_util import copy_tree - -import mesonbuild.mlog -import mesonbuild.depfile -import mesonbuild.compilers -import mesonbuild.envconfig -import mesonbuild.environment -import mesonbuild.mesonlib -import mesonbuild.coredata -import mesonbuild.modules.gnome -from mesonbuild.interpreter import Interpreter, ObjectHolder -from mesonbuild.ast import AstInterpreter -from mesonbuild.mesonlib import ( - BuildDirLock, LibType, MachineChoice, PerMachine, Version, is_windows, - is_osx, is_cygwin, is_dragonflybsd, is_openbsd, is_haiku, is_sunos, - windows_proof_rmtree, python_command, version_compare, split_args, - quote_arg -) -from mesonbuild.environment import detect_ninja -from mesonbuild.mesonlib import MesonException, EnvironmentException -from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram -import mesonbuild.dependencies.base -from mesonbuild.build import Target -import mesonbuild.modules.pkgconfig - -from mesonbuild.mtest import TAPParser, TestResult - -from run_tests import ( - Backend, FakeBuild, FakeCompilerOptions, - ensure_backend_detects_changes, exe_suffix, get_backend_commands, - get_builddir_target_args, get_fake_env, get_fake_options, get_meson_script, - run_configure_inprocess, run_mtest_inprocess -) - - -URLOPEN_TIMEOUT = 5 - - -def get_dynamic_section_entry(fname, entry): - if is_cygwin() or is_osx(): - raise unittest.SkipTest('Test only applicable to ELF platforms') - - try: - raw_out = subprocess.check_output(['readelf', '-d', fname], - universal_newlines=True) - except FileNotFoundError: - # FIXME: Try using depfixer.py:Elf() as a fallback - raise unittest.SkipTest('readelf not found') - pattern = re.compile(entry + r': \[(.*?)\]') - for line in raw_out.split('\n'): - m = pattern.search(line) - if m is not None: - return m.group(1) - return None # The file did not contain the specified entry. - -def get_soname(fname): - return get_dynamic_section_entry(fname, 'soname') - -def get_rpath(fname): - return get_dynamic_section_entry(fname, r'(?:rpath|runpath)') - -def is_tarball(): - if not os.path.isdir('docs'): - return True - return False - -def is_ci(): - if 'CI' in os.environ: - return True - return False - -def is_pull(): - # Travis - if os.environ.get('TRAVIS_PULL_REQUEST', 'false') != 'false': - return True - # Azure - if 'SYSTEM_PULLREQUEST_ISFORK' in os.environ: - return True - return False - -def _git_init(project_dir): - subprocess.check_call(['git', 'init'], cwd=project_dir, stdout=subprocess.DEVNULL) - subprocess.check_call(['git', 'config', - 'user.name', 'Author Person'], cwd=project_dir) - subprocess.check_call(['git', 'config', - 'user.email', 'teh_coderz@example.com'], cwd=project_dir) - subprocess.check_call('git add *', cwd=project_dir, shell=True, - stdout=subprocess.DEVNULL) - subprocess.check_call(['git', 'commit', '-a', '-m', 'I am a project'], cwd=project_dir, - stdout=subprocess.DEVNULL) - -@functools.lru_cache() -def is_real_gnu_compiler(path): - ''' - Check if the gcc we have is a real gcc and not a macOS wrapper around clang - ''' - if not path: - return False - out = subprocess.check_output([path, '--version'], universal_newlines=True, stderr=subprocess.STDOUT) - return 'Free Software Foundation' in out - -def skipIfNoExecutable(exename): - ''' - Skip this test if the given executable is not found. - ''' - def wrapper(func): - @functools.wraps(func) - def wrapped(*args, **kwargs): - if shutil.which(exename) is None: - raise unittest.SkipTest(exename + ' not found') - return func(*args, **kwargs) - return wrapped - return wrapper - -def skipIfNoPkgconfig(f): - ''' - Skip this test if no pkg-config is found, unless we're on CI. - This allows users to run our test suite without having - pkg-config installed on, f.ex., macOS, while ensuring that our CI does not - silently skip the test because of misconfiguration. - - Note: Yes, we provide pkg-config even while running Windows CI - ''' - @functools.wraps(f) - def wrapped(*args, **kwargs): - if not is_ci() and shutil.which('pkg-config') is None: - raise unittest.SkipTest('pkg-config not found') - return f(*args, **kwargs) - return wrapped - -def skipIfNoPkgconfigDep(depname): - ''' - Skip this test if the given pkg-config dep is not found, unless we're on CI. - ''' - def wrapper(func): - @functools.wraps(func) - def wrapped(*args, **kwargs): - if not is_ci() and shutil.which('pkg-config') is None: - raise unittest.SkipTest('pkg-config not found') - if not is_ci() and subprocess.call(['pkg-config', '--exists', depname]) != 0: - raise unittest.SkipTest('pkg-config dependency {} not found.'.format(depname)) - return func(*args, **kwargs) - return wrapped - return wrapper - -def skip_if_no_cmake(f): - ''' - Skip this test if no cmake is found, unless we're on CI. - This allows users to run our test suite without having - cmake installed on, f.ex., macOS, while ensuring that our CI does not - silently skip the test because of misconfiguration. - ''' - @functools.wraps(f) - def wrapped(*args, **kwargs): - if not is_ci() and shutil.which('cmake') is None: - raise unittest.SkipTest('cmake not found') - return f(*args, **kwargs) - return wrapped - -def skip_if_not_language(lang): - def wrapper(func): - @functools.wraps(func) - def wrapped(*args, **kwargs): - try: - env = get_fake_env() - f = getattr(env, 'detect_{}_compiler'.format(lang)) - f(MachineChoice.HOST) - except EnvironmentException: - raise unittest.SkipTest('No {} compiler found.'.format(lang)) - return func(*args, **kwargs) - return wrapped - return wrapper - -def skip_if_env_set(key): - ''' - Skip a test if a particular env is set, except when running under CI - ''' - def wrapper(func): - @functools.wraps(func) - def wrapped(*args, **kwargs): - old = None - if key in os.environ: - if not is_ci(): - raise unittest.SkipTest('Env var {!r} set, skipping'.format(key)) - old = os.environ.pop(key) - try: - return func(*args, **kwargs) - finally: - if old is not None: - os.environ[key] = old - return wrapped - return wrapper - -def skip_if_not_base_option(feature): - """Skip tests if The compiler does not support a given base option. - - for example, ICC doesn't currently support b_sanitize. - """ - def actual(f): - @functools.wraps(f) - def wrapped(*args, **kwargs): - env = get_fake_env() - cc = env.detect_c_compiler(MachineChoice.HOST) - if feature not in cc.base_options: - raise unittest.SkipTest( - '{} not available with {}'.format(feature, cc.id)) - return f(*args, **kwargs) - return wrapped - return actual - - -@contextmanager -def temp_filename(): - '''A context manager which provides a filename to an empty temporary file. - - On exit the file will be deleted. - ''' - - fd, filename = tempfile.mkstemp() - os.close(fd) - try: - yield filename - finally: - try: - os.remove(filename) - except OSError: - pass - -@contextmanager -def no_pkgconfig(): - ''' - A context manager that overrides shutil.which and ExternalProgram to force - them to return None for pkg-config to simulate it not existing. - ''' - old_which = shutil.which - old_search = ExternalProgram._search - - def new_search(self, name, search_dir): - if name == 'pkg-config': - return [None] - return old_search(self, name, search_dir) - - def new_which(cmd, *kwargs): - if cmd == 'pkg-config': - return None - return old_which(cmd, *kwargs) - - shutil.which = new_which - ExternalProgram._search = new_search - try: - yield - finally: - shutil.which = old_which - ExternalProgram._search = old_search - - -class InternalTests(unittest.TestCase): - - def test_version_number(self): - searchfunc = mesonbuild.environment.search_version - self.assertEqual(searchfunc('foobar 1.2.3'), '1.2.3') - self.assertEqual(searchfunc('1.2.3'), '1.2.3') - self.assertEqual(searchfunc('foobar 2016.10.28 1.2.3'), '1.2.3') - self.assertEqual(searchfunc('2016.10.28 1.2.3'), '1.2.3') - self.assertEqual(searchfunc('foobar 2016.10.128'), 'unknown version') - self.assertEqual(searchfunc('2016.10.128'), 'unknown version') - - def test_mode_symbolic_to_bits(self): - modefunc = mesonbuild.mesonlib.FileMode.perms_s_to_bits - self.assertEqual(modefunc('---------'), 0) - self.assertEqual(modefunc('r--------'), stat.S_IRUSR) - self.assertEqual(modefunc('---r-----'), stat.S_IRGRP) - self.assertEqual(modefunc('------r--'), stat.S_IROTH) - self.assertEqual(modefunc('-w-------'), stat.S_IWUSR) - self.assertEqual(modefunc('----w----'), stat.S_IWGRP) - self.assertEqual(modefunc('-------w-'), stat.S_IWOTH) - self.assertEqual(modefunc('--x------'), stat.S_IXUSR) - self.assertEqual(modefunc('-----x---'), stat.S_IXGRP) - self.assertEqual(modefunc('--------x'), stat.S_IXOTH) - self.assertEqual(modefunc('--S------'), stat.S_ISUID) - self.assertEqual(modefunc('-----S---'), stat.S_ISGID) - self.assertEqual(modefunc('--------T'), stat.S_ISVTX) - self.assertEqual(modefunc('--s------'), stat.S_ISUID | stat.S_IXUSR) - self.assertEqual(modefunc('-----s---'), stat.S_ISGID | stat.S_IXGRP) - self.assertEqual(modefunc('--------t'), stat.S_ISVTX | stat.S_IXOTH) - self.assertEqual(modefunc('rwx------'), stat.S_IRWXU) - self.assertEqual(modefunc('---rwx---'), stat.S_IRWXG) - self.assertEqual(modefunc('------rwx'), stat.S_IRWXO) - # We could keep listing combinations exhaustively but that seems - # tedious and pointless. Just test a few more. - self.assertEqual(modefunc('rwxr-xr-x'), - stat.S_IRWXU | - stat.S_IRGRP | stat.S_IXGRP | - stat.S_IROTH | stat.S_IXOTH) - self.assertEqual(modefunc('rw-r--r--'), - stat.S_IRUSR | stat.S_IWUSR | - stat.S_IRGRP | - stat.S_IROTH) - self.assertEqual(modefunc('rwsr-x---'), - stat.S_IRWXU | stat.S_ISUID | - stat.S_IRGRP | stat.S_IXGRP) - - def test_compiler_args_class(self): - cargsfunc = mesonbuild.compilers.CompilerArgs - cc = mesonbuild.compilers.CCompiler([], 'fake', False, MachineChoice.HOST, mock.Mock()) - # Test that empty initialization works - a = cargsfunc(cc) - self.assertEqual(a, []) - # Test that list initialization works - a = cargsfunc(cc, ['-I.', '-I..']) - self.assertEqual(a, ['-I.', '-I..']) - # Test that there is no de-dup on initialization - self.assertEqual(cargsfunc(cc, ['-I.', '-I.']), ['-I.', '-I.']) - - ## Test that appending works - a.append('-I..') - self.assertEqual(a, ['-I..', '-I.']) - a.append('-O3') - self.assertEqual(a, ['-I..', '-I.', '-O3']) - - ## Test that in-place addition works - a += ['-O2', '-O2'] - self.assertEqual(a, ['-I..', '-I.', '-O3', '-O2', '-O2']) - # Test that removal works - a.remove('-O2') - self.assertEqual(a, ['-I..', '-I.', '-O3', '-O2']) - # Test that de-dup happens on addition - a += ['-Ifoo', '-Ifoo'] - self.assertEqual(a, ['-Ifoo', '-I..', '-I.', '-O3', '-O2']) - - # .extend() is just +=, so we don't test it - - ## Test that addition works - # Test that adding a list with just one old arg works and yields the same array - a = a + ['-Ifoo'] - self.assertEqual(a, ['-Ifoo', '-I..', '-I.', '-O3', '-O2']) - # Test that adding a list with one arg new and one old works - a = a + ['-Ifoo', '-Ibaz'] - self.assertEqual(a, ['-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2']) - # Test that adding args that must be prepended and appended works - a = a + ['-Ibar', '-Wall'] - self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) - - ## Test that reflected addition works - # Test that adding to a list with just one old arg works and yields the same array - a = ['-Ifoo'] + a - self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) - # Test that adding to a list with just one new arg that is not pre-pended works - a = ['-Werror'] + a - self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Werror', '-O3', '-O2', '-Wall']) - # Test that adding to a list with two new args preserves the order - a = ['-Ldir', '-Lbah'] + a - self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) - # Test that adding to a list with old args does nothing - a = ['-Ibar', '-Ibaz', '-Ifoo'] + a - self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) - - ## Test that adding libraries works - l = cargsfunc(cc, ['-Lfoodir', '-lfoo']) - self.assertEqual(l, ['-Lfoodir', '-lfoo']) - # Adding a library and a libpath appends both correctly - l += ['-Lbardir', '-lbar'] - self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar']) - # Adding the same library again does nothing - l += ['-lbar'] - self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar']) - - ## Test that 'direct' append and extend works - l = cargsfunc(cc, ['-Lfoodir', '-lfoo']) - self.assertEqual(l, ['-Lfoodir', '-lfoo']) - # Direct-adding a library and a libpath appends both correctly - l.extend_direct(['-Lbardir', '-lbar']) - self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar']) - # Direct-adding the same library again still adds it - l.append_direct('-lbar') - self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar']) - # Direct-adding with absolute path deduplicates - l.append_direct('/libbaz.a') - self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a']) - # Adding libbaz again does nothing - l.append_direct('/libbaz.a') - self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a']) - - def test_compiler_args_class_gnuld(self): - cargsfunc = mesonbuild.compilers.CompilerArgs - ## Test --start/end-group - linker = mesonbuild.linkers.GnuDynamicLinker([], MachineChoice.HOST, 'fake', '-Wl,', []) - gcc = mesonbuild.compilers.GnuCCompiler([], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker) - ## Ensure that the fake compiler is never called by overriding the relevant function - gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] - ## Test that 'direct' append and extend works - l = cargsfunc(gcc, ['-Lfoodir', '-lfoo']) - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group']) - # Direct-adding a library and a libpath appends both correctly - l.extend_direct(['-Lbardir', '-lbar']) - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-Wl,--end-group']) - # Direct-adding the same library again still adds it - l.append_direct('-lbar') - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '-Wl,--end-group']) - # Direct-adding with absolute path deduplicates - l.append_direct('/libbaz.a') - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group']) - # Adding libbaz again does nothing - l.append_direct('/libbaz.a') - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group']) - # Adding a non-library argument doesn't include it in the group - l += ['-Lfoo', '-Wl,--export-dynamic'] - self.assertEqual(l.to_native(copy=True), ['-Lfoo', '-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group', '-Wl,--export-dynamic']) - # -Wl,-lfoo is detected as a library and gets added to the group - l.append('-Wl,-ldl') - self.assertEqual(l.to_native(copy=True), ['-Lfoo', '-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--export-dynamic', '-Wl,-ldl', '-Wl,--end-group']) - - def test_compiler_args_remove_system(self): - cargsfunc = mesonbuild.compilers.CompilerArgs - ## Test --start/end-group - linker = mesonbuild.linkers.GnuDynamicLinker([], MachineChoice.HOST, 'fake', '-Wl,', []) - gcc = mesonbuild.compilers.GnuCCompiler([], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker) - ## Ensure that the fake compiler is never called by overriding the relevant function - gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] - ## Test that 'direct' append and extend works - l = cargsfunc(gcc, ['-Lfoodir', '-lfoo']) - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group']) - ## Test that to_native removes all system includes - l += ['-isystem/usr/include', '-isystem=/usr/share/include', '-DSOMETHING_IMPORTANT=1', '-isystem', '/usr/local/include'] - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group', '-DSOMETHING_IMPORTANT=1']) - - def test_string_templates_substitution(self): - dictfunc = mesonbuild.mesonlib.get_filenames_templates_dict - substfunc = mesonbuild.mesonlib.substitute_values - ME = mesonbuild.mesonlib.MesonException - - # Identity - self.assertEqual(dictfunc([], []), {}) - - # One input, no outputs - inputs = ['bar/foo.c.in'] - outputs = [] - ret = dictfunc(inputs, outputs) - d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], - '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c'} - # Check dictionary - self.assertEqual(ret, d) - # Check substitutions - cmd = ['some', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), cmd) - cmd = ['@INPUT@.out', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out'] + cmd[1:]) - cmd = ['@INPUT0@.out', '@PLAINNAME@.ok', 'strings'] - self.assertEqual(substfunc(cmd, d), - [inputs[0] + '.out'] + [d['@PLAINNAME@'] + '.ok'] + cmd[2:]) - cmd = ['@INPUT@', '@BASENAME@.hah', 'strings'] - self.assertEqual(substfunc(cmd, d), - inputs + [d['@BASENAME@'] + '.hah'] + cmd[2:]) - cmd = ['@OUTPUT@'] - self.assertRaises(ME, substfunc, cmd, d) - - # One input, one output - inputs = ['bar/foo.c.in'] - outputs = ['out.c'] - ret = dictfunc(inputs, outputs) - d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], - '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c', - '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': '.'} - # Check dictionary - self.assertEqual(ret, d) - # Check substitutions - cmd = ['some', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), cmd) - cmd = ['@INPUT@.out', '@OUTPUT@', 'strings'] - self.assertEqual(substfunc(cmd, d), - [inputs[0] + '.out'] + outputs + cmd[2:]) - cmd = ['@INPUT0@.out', '@PLAINNAME@.ok', '@OUTPUT0@'] - self.assertEqual(substfunc(cmd, d), - [inputs[0] + '.out', d['@PLAINNAME@'] + '.ok'] + outputs) - cmd = ['@INPUT@', '@BASENAME@.hah', 'strings'] - self.assertEqual(substfunc(cmd, d), - inputs + [d['@BASENAME@'] + '.hah'] + cmd[2:]) - - # One input, one output with a subdir - outputs = ['dir/out.c'] - ret = dictfunc(inputs, outputs) - d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], - '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c', - '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'} - # Check dictionary - self.assertEqual(ret, d) - - # Two inputs, no outputs - inputs = ['bar/foo.c.in', 'baz/foo.c.in'] - outputs = [] - ret = dictfunc(inputs, outputs) - d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1]} - # Check dictionary - self.assertEqual(ret, d) - # Check substitutions - cmd = ['some', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), cmd) - cmd = ['@INPUT@', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), inputs + cmd[1:]) - cmd = ['@INPUT0@.out', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out'] + cmd[1:]) - cmd = ['@INPUT0@.out', '@INPUT1@.ok', 'strings'] - self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out', inputs[1] + '.ok'] + cmd[2:]) - cmd = ['@INPUT0@', '@INPUT1@', 'strings'] - self.assertEqual(substfunc(cmd, d), inputs + cmd[2:]) - # Many inputs, can't use @INPUT@ like this - cmd = ['@INPUT@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - # Not enough inputs - cmd = ['@INPUT2@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - # Too many inputs - cmd = ['@PLAINNAME@'] - self.assertRaises(ME, substfunc, cmd, d) - cmd = ['@BASENAME@'] - self.assertRaises(ME, substfunc, cmd, d) - # No outputs - cmd = ['@OUTPUT@'] - self.assertRaises(ME, substfunc, cmd, d) - cmd = ['@OUTPUT0@'] - self.assertRaises(ME, substfunc, cmd, d) - cmd = ['@OUTDIR@'] - self.assertRaises(ME, substfunc, cmd, d) - - # Two inputs, one output - outputs = ['dir/out.c'] - ret = dictfunc(inputs, outputs) - d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], - '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'} - # Check dictionary - self.assertEqual(ret, d) - # Check substitutions - cmd = ['some', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), cmd) - cmd = ['@OUTPUT@', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), outputs + cmd[1:]) - cmd = ['@OUTPUT@.out', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out'] + cmd[1:]) - cmd = ['@OUTPUT0@.out', '@INPUT1@.ok', 'strings'] - self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out', inputs[1] + '.ok'] + cmd[2:]) - # Many inputs, can't use @INPUT@ like this - cmd = ['@INPUT@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - # Not enough inputs - cmd = ['@INPUT2@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - # Not enough outputs - cmd = ['@OUTPUT2@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - - # Two inputs, two outputs - outputs = ['dir/out.c', 'dir/out2.c'] - ret = dictfunc(inputs, outputs) - d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], - '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTPUT1@': outputs[1], - '@OUTDIR@': 'dir'} - # Check dictionary - self.assertEqual(ret, d) - # Check substitutions - cmd = ['some', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), cmd) - cmd = ['@OUTPUT@', 'ordinary', 'strings'] - self.assertEqual(substfunc(cmd, d), outputs + cmd[1:]) - cmd = ['@OUTPUT0@', '@OUTPUT1@', 'strings'] - self.assertEqual(substfunc(cmd, d), outputs + cmd[2:]) - cmd = ['@OUTPUT0@.out', '@INPUT1@.ok', '@OUTDIR@'] - self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out', inputs[1] + '.ok', 'dir']) - # Many inputs, can't use @INPUT@ like this - cmd = ['@INPUT@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - # Not enough inputs - cmd = ['@INPUT2@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - # Not enough outputs - cmd = ['@OUTPUT2@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - # Many outputs, can't use @OUTPUT@ like this - cmd = ['@OUTPUT@.out', 'ordinary', 'strings'] - self.assertRaises(ME, substfunc, cmd, d) - - def test_needs_exe_wrapper_override(self): - config = ConfigParser() - config['binaries'] = { - 'c': '\'/usr/bin/gcc\'', - } - config['host_machine'] = { - 'system': '\'linux\'', - 'cpu_family': '\'arm\'', - 'cpu': '\'armv7\'', - 'endian': '\'little\'', - } - # Can not be used as context manager because we need to - # open it a second time and this is not possible on - # Windows. - configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False) - configfilename = configfile.name - config.write(configfile) - configfile.flush() - configfile.close() - opts = get_fake_options() - opts.cross_file = (configfilename,) - env = get_fake_env(opts=opts) - detected_value = env.need_exe_wrapper() - os.unlink(configfilename) - - desired_value = not detected_value - config['properties'] = { - 'needs_exe_wrapper': 'true' if desired_value else 'false' - } - - configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False) - configfilename = configfile.name - config.write(configfile) - configfile.close() - opts = get_fake_options() - opts.cross_file = (configfilename,) - env = get_fake_env(opts=opts) - forced_value = env.need_exe_wrapper() - os.unlink(configfilename) - - self.assertEqual(forced_value, desired_value) - - def test_listify(self): - listify = mesonbuild.mesonlib.listify - # Test sanity - self.assertEqual([1], listify(1)) - self.assertEqual([], listify([])) - self.assertEqual([1], listify([1])) - # Test flattening - self.assertEqual([1, 2, 3], listify([1, [2, 3]])) - self.assertEqual([1, 2, 3], listify([1, [2, [3]]])) - self.assertEqual([1, [2, [3]]], listify([1, [2, [3]]], flatten=False)) - # Test flattening and unholdering - holder1 = ObjectHolder(1) - holder3 = ObjectHolder(3) - self.assertEqual([holder1], listify(holder1)) - self.assertEqual([holder1], listify([holder1])) - self.assertEqual([holder1, 2], listify([holder1, 2])) - self.assertEqual([holder1, 2, 3], listify([holder1, 2, [3]])) - self.assertEqual([1], listify(holder1, unholder=True)) - self.assertEqual([1], listify([holder1], unholder=True)) - self.assertEqual([1, 2], listify([holder1, 2], unholder=True)) - self.assertEqual([1, 2, 3], listify([holder1, 2, [holder3]], unholder=True)) - # Unholding doesn't work recursively when not flattening - self.assertEqual([1, [2], [holder3]], listify([holder1, [2], [holder3]], unholder=True, flatten=False)) - - def test_extract_as_list(self): - extract = mesonbuild.mesonlib.extract_as_list - # Test sanity - kwargs = {'sources': [1, 2, 3]} - self.assertEqual([1, 2, 3], extract(kwargs, 'sources')) - self.assertEqual(kwargs, {'sources': [1, 2, 3]}) - self.assertEqual([1, 2, 3], extract(kwargs, 'sources', pop=True)) - self.assertEqual(kwargs, {}) - # Test unholding - holder3 = ObjectHolder(3) - kwargs = {'sources': [1, 2, holder3]} - self.assertEqual([1, 2, 3], extract(kwargs, 'sources', unholder=True)) - self.assertEqual(kwargs, {'sources': [1, 2, holder3]}) - self.assertEqual([1, 2, 3], extract(kwargs, 'sources', unholder=True, pop=True)) - self.assertEqual(kwargs, {}) - # Test listification - kwargs = {'sources': [1, 2, 3], 'pch_sources': [4, 5, 6]} - self.assertEqual([[1, 2, 3], [4, 5, 6]], extract(kwargs, 'sources', 'pch_sources')) - - def test_pkgconfig_module(self): - - class Mock: - pass - - mock = Mock() - mock.pcdep = Mock() - mock.pcdep.name = "some_name" - mock.version_reqs = [] - - # pkgconfig dependency as lib - deps = mesonbuild.modules.pkgconfig.DependenciesHelper("thislib") - deps.add_pub_libs([mock]) - self.assertEqual(deps.format_reqs(deps.pub_reqs), "some_name") - - # pkgconfig dependency as requires - deps = mesonbuild.modules.pkgconfig.DependenciesHelper("thislib") - deps.add_pub_reqs([mock]) - self.assertEqual(deps.format_reqs(deps.pub_reqs), "some_name") - - def _test_all_naming(self, cc, env, patterns, platform): - shr = patterns[platform]['shared'] - stc = patterns[platform]['static'] - shrstc = shr + tuple([x for x in stc if x not in shr]) - stcshr = stc + tuple([x for x in shr if x not in stc]) - p = cc.get_library_naming(env, LibType.SHARED) - self.assertEqual(p, shr) - p = cc.get_library_naming(env, LibType.STATIC) - self.assertEqual(p, stc) - p = cc.get_library_naming(env, LibType.PREFER_STATIC) - self.assertEqual(p, stcshr) - p = cc.get_library_naming(env, LibType.PREFER_SHARED) - self.assertEqual(p, shrstc) - # Test find library by mocking up openbsd - if platform != 'openbsd': - return - with tempfile.TemporaryDirectory() as tmpdir: - with open(os.path.join(tmpdir, 'libfoo.so.6.0'), 'w') as f: - f.write('') - with open(os.path.join(tmpdir, 'libfoo.so.5.0'), 'w') as f: - f.write('') - with open(os.path.join(tmpdir, 'libfoo.so.54.0'), 'w') as f: - f.write('') - with open(os.path.join(tmpdir, 'libfoo.so.66a.0b'), 'w') as f: - f.write('') - with open(os.path.join(tmpdir, 'libfoo.so.70.0.so.1'), 'w') as f: - f.write('') - found = cc.find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED) - self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0') - - def test_find_library_patterns(self): - ''' - Unit test for the library search patterns used by find_library() - ''' - unix_static = ('lib{}.a', '{}.a') - msvc_static = ('lib{}.a', 'lib{}.lib', '{}.a', '{}.lib') - # This is the priority list of pattern matching for library searching - patterns = {'openbsd': {'shared': ('lib{}.so', '{}.so', 'lib{}.so.[0-9]*.[0-9]*', '{}.so.[0-9]*.[0-9]*'), - 'static': unix_static}, - 'linux': {'shared': ('lib{}.so', '{}.so'), - 'static': unix_static}, - 'darwin': {'shared': ('lib{}.dylib', 'lib{}.so', '{}.dylib', '{}.so'), - 'static': unix_static}, - 'cygwin': {'shared': ('cyg{}.dll', 'cyg{}.dll.a', 'lib{}.dll', - 'lib{}.dll.a', '{}.dll', '{}.dll.a'), - 'static': ('cyg{}.a',) + unix_static}, - 'windows-msvc': {'shared': ('lib{}.lib', '{}.lib'), - 'static': msvc_static}, - 'windows-mingw': {'shared': ('lib{}.dll.a', 'lib{}.lib', 'lib{}.dll', - '{}.dll.a', '{}.lib', '{}.dll'), - 'static': msvc_static}} - env = get_fake_env() - cc = env.detect_c_compiler(MachineChoice.HOST) - if is_osx(): - self._test_all_naming(cc, env, patterns, 'darwin') - elif is_cygwin(): - self._test_all_naming(cc, env, patterns, 'cygwin') - elif is_windows(): - if cc.get_argument_syntax() == 'msvc': - self._test_all_naming(cc, env, patterns, 'windows-msvc') - else: - self._test_all_naming(cc, env, patterns, 'windows-mingw') - elif is_openbsd(): - self._test_all_naming(cc, env, patterns, 'openbsd') - else: - self._test_all_naming(cc, env, patterns, 'linux') - env.machines.host.system = 'openbsd' - self._test_all_naming(cc, env, patterns, 'openbsd') - env.machines.host.system = 'darwin' - self._test_all_naming(cc, env, patterns, 'darwin') - env.machines.host.system = 'cygwin' - self._test_all_naming(cc, env, patterns, 'cygwin') - env.machines.host.system = 'windows' - self._test_all_naming(cc, env, patterns, 'windows-mingw') - - def test_pkgconfig_parse_libs(self): - ''' - Unit test for parsing of pkg-config output to search for libraries - - https://github.com/mesonbuild/meson/issues/3951 - ''' - def create_static_lib(name): - if not is_osx(): - name.open('w').close() - return - src = name.with_suffix('.c') - out = name.with_suffix('.o') - with src.open('w') as f: - f.write('int meson_foobar (void) { return 0; }') - subprocess.check_call(['clang', '-c', str(src), '-o', str(out)]) - subprocess.check_call(['ar', 'csr', str(name), str(out)]) - - with tempfile.TemporaryDirectory() as tmpdir: - pkgbin = ExternalProgram('pkg-config', command=['pkg-config'], silent=True) - env = get_fake_env() - compiler = env.detect_c_compiler(MachineChoice.HOST) - env.coredata.compilers.host = {'c': compiler} - env.coredata.compiler_options.host['c_link_args'] = FakeCompilerOptions() - p1 = Path(tmpdir) / '1' - p2 = Path(tmpdir) / '2' - p1.mkdir() - p2.mkdir() - # libfoo.a is in one prefix - create_static_lib(p1 / 'libfoo.a') - # libbar.a is in both prefixes - create_static_lib(p1 / 'libbar.a') - create_static_lib(p2 / 'libbar.a') - # Ensure that we never statically link to these - create_static_lib(p1 / 'libpthread.a') - create_static_lib(p1 / 'libm.a') - create_static_lib(p1 / 'libc.a') - create_static_lib(p1 / 'libdl.a') - create_static_lib(p1 / 'librt.a') - - def fake_call_pkgbin(self, args, env=None): - if '--libs' not in args: - return 0, '', '' - if args[0] == 'foo': - return 0, '-L{} -lfoo -L{} -lbar'.format(p2.as_posix(), p1.as_posix()), '' - if args[0] == 'bar': - return 0, '-L{} -lbar'.format(p2.as_posix()), '' - if args[0] == 'internal': - return 0, '-L{} -lpthread -lm -lc -lrt -ldl'.format(p1.as_posix()), '' - - old_call = PkgConfigDependency._call_pkgbin - old_check = PkgConfigDependency.check_pkgconfig - PkgConfigDependency._call_pkgbin = fake_call_pkgbin - PkgConfigDependency.check_pkgconfig = lambda x, _: pkgbin - # Test begins - try: - kwargs = {'required': True, 'silent': True} - foo_dep = PkgConfigDependency('foo', env, kwargs) - self.assertEqual(foo_dep.get_link_args(), - [(p1 / 'libfoo.a').as_posix(), (p2 / 'libbar.a').as_posix()]) - bar_dep = PkgConfigDependency('bar', env, kwargs) - self.assertEqual(bar_dep.get_link_args(), [(p2 / 'libbar.a').as_posix()]) - internal_dep = PkgConfigDependency('internal', env, kwargs) - if compiler.get_argument_syntax() == 'msvc': - self.assertEqual(internal_dep.get_link_args(), []) - else: - link_args = internal_dep.get_link_args() - for link_arg in link_args: - for lib in ('pthread', 'm', 'c', 'dl', 'rt'): - self.assertNotIn('lib{}.a'.format(lib), link_arg, msg=link_args) - finally: - # Test ends - PkgConfigDependency._call_pkgbin = old_call - PkgConfigDependency.check_pkgconfig = old_check - # Reset dependency class to ensure that in-process configure doesn't mess up - PkgConfigDependency.pkgbin_cache = {} - PkgConfigDependency.class_pkgbin = PerMachine(None, None) - - def test_version_compare(self): - comparefunc = mesonbuild.mesonlib.version_compare_many - for (a, b, result) in [ - ('0.99.beta19', '>= 0.99.beta14', True), - ]: - self.assertEqual(comparefunc(a, b)[0], result) - - for (a, b, op) in [ - # examples from https://fedoraproject.org/wiki/Archive:Tools/RPM/VersionComparison - ("1.0010", "1.9", operator.gt), - ("1.05", "1.5", operator.eq), - ("1.0", "1", operator.gt), - ("2.50", "2.5", operator.gt), - ("fc4", "fc.4", operator.eq), - ("FC5", "fc4", operator.lt), - ("2a", "2.0", operator.lt), - ("1.0", "1.fc4", operator.gt), - ("3.0.0_fc", "3.0.0.fc", operator.eq), - # from RPM tests - ("1.0", "1.0", operator.eq), - ("1.0", "2.0", operator.lt), - ("2.0", "1.0", operator.gt), - ("2.0.1", "2.0.1", operator.eq), - ("2.0", "2.0.1", operator.lt), - ("2.0.1", "2.0", operator.gt), - ("2.0.1a", "2.0.1a", operator.eq), - ("2.0.1a", "2.0.1", operator.gt), - ("2.0.1", "2.0.1a", operator.lt), - ("5.5p1", "5.5p1", operator.eq), - ("5.5p1", "5.5p2", operator.lt), - ("5.5p2", "5.5p1", operator.gt), - ("5.5p10", "5.5p10", operator.eq), - ("5.5p1", "5.5p10", operator.lt), - ("5.5p10", "5.5p1", operator.gt), - ("10xyz", "10.1xyz", operator.lt), - ("10.1xyz", "10xyz", operator.gt), - ("xyz10", "xyz10", operator.eq), - ("xyz10", "xyz10.1", operator.lt), - ("xyz10.1", "xyz10", operator.gt), - ("xyz.4", "xyz.4", operator.eq), - ("xyz.4", "8", operator.lt), - ("8", "xyz.4", operator.gt), - ("xyz.4", "2", operator.lt), - ("2", "xyz.4", operator.gt), - ("5.5p2", "5.6p1", operator.lt), - ("5.6p1", "5.5p2", operator.gt), - ("5.6p1", "6.5p1", operator.lt), - ("6.5p1", "5.6p1", operator.gt), - ("6.0.rc1", "6.0", operator.gt), - ("6.0", "6.0.rc1", operator.lt), - ("10b2", "10a1", operator.gt), - ("10a2", "10b2", operator.lt), - ("1.0aa", "1.0aa", operator.eq), - ("1.0a", "1.0aa", operator.lt), - ("1.0aa", "1.0a", operator.gt), - ("10.0001", "10.0001", operator.eq), - ("10.0001", "10.1", operator.eq), - ("10.1", "10.0001", operator.eq), - ("10.0001", "10.0039", operator.lt), - ("10.0039", "10.0001", operator.gt), - ("4.999.9", "5.0", operator.lt), - ("5.0", "4.999.9", operator.gt), - ("20101121", "20101121", operator.eq), - ("20101121", "20101122", operator.lt), - ("20101122", "20101121", operator.gt), - ("2_0", "2_0", operator.eq), - ("2.0", "2_0", operator.eq), - ("2_0", "2.0", operator.eq), - ("a", "a", operator.eq), - ("a+", "a+", operator.eq), - ("a+", "a_", operator.eq), - ("a_", "a+", operator.eq), - ("+a", "+a", operator.eq), - ("+a", "_a", operator.eq), - ("_a", "+a", operator.eq), - ("+_", "+_", operator.eq), - ("_+", "+_", operator.eq), - ("_+", "_+", operator.eq), - ("+", "_", operator.eq), - ("_", "+", operator.eq), - # other tests - ('0.99.beta19', '0.99.beta14', operator.gt), - ("1.0.0", "2.0.0", operator.lt), - (".0.0", "2.0.0", operator.lt), - ("alpha", "beta", operator.lt), - ("1.0", "1.0.0", operator.lt), - ("2.456", "2.1000", operator.lt), - ("2.1000", "3.111", operator.lt), - ("2.001", "2.1", operator.eq), - ("2.34", "2.34", operator.eq), - ("6.1.2", "6.3.8", operator.lt), - ("1.7.3.0", "2.0.0", operator.lt), - ("2.24.51", "2.25", operator.lt), - ("2.1.5+20120813+gitdcbe778", "2.1.5", operator.gt), - ("3.4.1", "3.4b1", operator.gt), - ("041206", "200090325", operator.lt), - ("0.6.2+git20130413", "0.6.2", operator.gt), - ("2.6.0+bzr6602", "2.6.0", operator.gt), - ("2.6.0", "2.6b2", operator.gt), - ("2.6.0+bzr6602", "2.6b2x", operator.gt), - ("0.6.7+20150214+git3a710f9", "0.6.7", operator.gt), - ("15.8b", "15.8.0.1", operator.lt), - ("1.2rc1", "1.2.0", operator.lt), - ]: - ver_a = Version(a) - ver_b = Version(b) - if op is operator.eq: - for o, name in [(op, 'eq'), (operator.ge, 'ge'), (operator.le, 'le')]: - self.assertTrue(o(ver_a, ver_b), '{} {} {}'.format(ver_a, name, ver_b)) - if op is operator.lt: - for o, name in [(op, 'lt'), (operator.le, 'le'), (operator.ne, 'ne')]: - self.assertTrue(o(ver_a, ver_b), '{} {} {}'.format(ver_a, name, ver_b)) - for o, name in [(operator.gt, 'gt'), (operator.ge, 'ge'), (operator.eq, 'eq')]: - self.assertFalse(o(ver_a, ver_b), '{} {} {}'.format(ver_a, name, ver_b)) - if op is operator.gt: - for o, name in [(op, 'gt'), (operator.ge, 'ge'), (operator.ne, 'ne')]: - self.assertTrue(o(ver_a, ver_b), '{} {} {}'.format(ver_a, name, ver_b)) - for o, name in [(operator.lt, 'lt'), (operator.le, 'le'), (operator.eq, 'eq')]: - self.assertFalse(o(ver_a, ver_b), '{} {} {}'.format(ver_a, name, ver_b)) - - def test_msvc_toolset_version(self): - ''' - Ensure that the toolset version returns the correct value for this MSVC - ''' - env = get_fake_env() - cc = env.detect_c_compiler(MachineChoice.HOST) - if cc.get_argument_syntax() != 'msvc': - raise unittest.SkipTest('Test only applies to MSVC-like compilers') - toolset_ver = cc.get_toolset_version() - self.assertIsNotNone(toolset_ver) - # Visual Studio 2015 and older versions do not define VCToolsVersion - # TODO: ICL doesn't set this in the VSC2015 profile either - if cc.id == 'msvc' and int(''.join(cc.version.split('.')[0:2])) < 1910: - return - if 'VCToolsVersion' in os.environ: - vctools_ver = os.environ['VCToolsVersion'] - else: - self.assertIn('VCINSTALLDIR', os.environ) - # See https://devblogs.microsoft.com/cppblog/finding-the-visual-c-compiler-tools-in-visual-studio-2017/ - vctools_ver = (Path(os.environ['VCINSTALLDIR']) / 'Auxiliary' / 'Build' / 'Microsoft.VCToolsVersion.default.txt').read_text() - self.assertTrue(vctools_ver.startswith(toolset_ver), - msg='{!r} does not start with {!r}'.format(vctools_ver, toolset_ver)) - - def test_split_args(self): - split_args = mesonbuild.mesonlib.split_args - join_args = mesonbuild.mesonlib.join_args - if is_windows(): - test_data = [ - # examples from https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments - (r'"a b c" d e', ['a b c', 'd', 'e'], True), - (r'"ab\"c" "\\" d', ['ab"c', '\\', 'd'], False), - (r'a\\\b d"e f"g h', [r'a\\\b', 'de fg', 'h'], False), - (r'a\\\"b c d', [r'a\"b', 'c', 'd'], False), - (r'a\\\\"b c" d e', [r'a\\b c', 'd', 'e'], False), - # other basics - (r'""', [''], True), - (r'a b c d "" e', ['a', 'b', 'c', 'd', '', 'e'], True), - (r"'a b c' d e", ["'a", 'b', "c'", 'd', 'e'], True), - (r"'a&b&c' d e", ["'a&b&c'", 'd', 'e'], True), - (r"a & b & c d e", ['a', '&', 'b', '&', 'c', 'd', 'e'], True), - (r"'a & b & c d e'", ["'a", '&', 'b', '&', 'c', 'd', "e'"], True), - ('a b\nc\rd \n\re', ['a', 'b', 'c', 'd', 'e'], False), - # more illustrative tests - (r'cl test.cpp /O1 /Fe:test.exe', ['cl', 'test.cpp', '/O1', '/Fe:test.exe'], True), - (r'cl "test.cpp /O1 /Fe:test.exe"', ['cl', 'test.cpp /O1 /Fe:test.exe'], True), - (r'cl /DNAME=\"Bob\" test.cpp', ['cl', '/DNAME="Bob"', 'test.cpp'], False), - (r'cl "/DNAME=\"Bob\"" test.cpp', ['cl', '/DNAME="Bob"', 'test.cpp'], True), - (r'cl /DNAME=\"Bob, Alice\" test.cpp', ['cl', '/DNAME="Bob,', 'Alice"', 'test.cpp'], False), - (r'cl "/DNAME=\"Bob, Alice\"" test.cpp', ['cl', '/DNAME="Bob, Alice"', 'test.cpp'], True), - (r'cl C:\path\with\backslashes.cpp', ['cl', r'C:\path\with\backslashes.cpp'], True), - (r'cl C:\\path\\with\\double\\backslashes.cpp', ['cl', r'C:\\path\\with\\double\\backslashes.cpp'], True), - (r'cl "C:\\path\\with\\double\\backslashes.cpp"', ['cl', r'C:\\path\\with\\double\\backslashes.cpp'], False), - (r'cl C:\path with spaces\test.cpp', ['cl', r'C:\path', 'with', r'spaces\test.cpp'], False), - (r'cl "C:\path with spaces\test.cpp"', ['cl', r'C:\path with spaces\test.cpp'], True), - (r'cl /DPATH="C:\path\with\backslashes test.cpp', ['cl', r'/DPATH=C:\path\with\backslashes test.cpp'], False), - (r'cl /DPATH=\"C:\\ends\\with\\backslashes\\\" test.cpp', ['cl', r'/DPATH="C:\\ends\\with\\backslashes\"', 'test.cpp'], False), - (r'cl /DPATH="C:\\ends\\with\\backslashes\\" test.cpp', ['cl', '/DPATH=C:\\\\ends\\\\with\\\\backslashes\\', 'test.cpp'], False), - (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\"', 'test.cpp'], True), - (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\\ test.cpp'], False), - (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\\"', 'test.cpp'], True), - ] - else: - test_data = [ - (r"'a b c' d e", ['a b c', 'd', 'e'], True), - (r"a/b/c d e", ['a/b/c', 'd', 'e'], True), - (r"a\b\c d e", [r'abc', 'd', 'e'], False), - (r"a\\b\\c d e", [r'a\b\c', 'd', 'e'], False), - (r'"a b c" d e', ['a b c', 'd', 'e'], False), - (r'"a\\b\\c\\" d e', ['a\\b\\c\\', 'd', 'e'], False), - (r"'a\b\c\' d e", ['a\\b\\c\\', 'd', 'e'], True), - (r"'a&b&c' d e", ['a&b&c', 'd', 'e'], True), - (r"a & b & c d e", ['a', '&', 'b', '&', 'c', 'd', 'e'], False), - (r"'a & b & c d e'", ['a & b & c d e'], True), - (r"abd'e f'g h", [r'abde fg', 'h'], False), - ('a b\nc\rd \n\re', ['a', 'b', 'c', 'd', 'e'], False), - - ('g++ -DNAME="Bob" test.cpp', ['g++', '-DNAME=Bob', 'test.cpp'], False), - ("g++ '-DNAME=\"Bob\"' test.cpp", ['g++', '-DNAME="Bob"', 'test.cpp'], True), - ('g++ -DNAME="Bob, Alice" test.cpp', ['g++', '-DNAME=Bob, Alice', 'test.cpp'], False), - ("g++ '-DNAME=\"Bob, Alice\"' test.cpp", ['g++', '-DNAME="Bob, Alice"', 'test.cpp'], True), - ] - - for (cmd, expected, roundtrip) in test_data: - self.assertEqual(split_args(cmd), expected) - if roundtrip: - self.assertEqual(join_args(expected), cmd) - - def test_quote_arg(self): - split_args = mesonbuild.mesonlib.split_args - quote_arg = mesonbuild.mesonlib.quote_arg - if is_windows(): - test_data = [ - ('', '""'), - ('arg1', 'arg1'), - ('/option1', '/option1'), - ('/Ovalue', '/Ovalue'), - ('/OBob&Alice', '/OBob&Alice'), - ('/Ovalue with spaces', r'"/Ovalue with spaces"'), - (r'/O"value with spaces"', r'"/O\"value with spaces\""'), - (r'/OC:\path with spaces\test.exe', r'"/OC:\path with spaces\test.exe"'), - ('/LIBPATH:C:\\path with spaces\\ends\\with\\backslashes\\', r'"/LIBPATH:C:\path with spaces\ends\with\backslashes\\"'), - ('/LIBPATH:"C:\\path with spaces\\ends\\with\\backslashes\\\\"', r'"/LIBPATH:\"C:\path with spaces\ends\with\backslashes\\\\\""'), - (r'/DMSG="Alice said: \"Let\'s go\""', r'"/DMSG=\"Alice said: \\\"Let\'s go\\\"\""'), - ] - else: - test_data = [ - ('arg1', 'arg1'), - ('--option1', '--option1'), - ('-O=value', '-O=value'), - ('-O=Bob&Alice', "'-O=Bob&Alice'"), - ('-O=value with spaces', "'-O=value with spaces'"), - ('-O="value with spaces"', '\'-O=\"value with spaces\"\''), - ('-O=/path with spaces/test', '\'-O=/path with spaces/test\''), - ('-DMSG="Alice said: \\"Let\'s go\\""', "'-DMSG=\"Alice said: \\\"Let'\"'\"'s go\\\"\"'"), - ] - - for (arg, expected) in test_data: - self.assertEqual(quote_arg(arg), expected) - self.assertEqual(split_args(expected)[0], arg) - - def test_depfile(self): - for (f, target, expdeps) in [ - # empty, unknown target - ([''], 'unknown', set()), - # simple target & deps - (['meson/foo.o : foo.c foo.h'], 'meson/foo.o', set({'foo.c', 'foo.h'})), - (['meson/foo.o: foo.c foo.h'], 'foo.c', set()), - # get all deps - (['meson/foo.o: foo.c foo.h', - 'foo.c: gen.py'], 'meson/foo.o', set({'foo.c', 'foo.h', 'gen.py'})), - (['meson/foo.o: foo.c foo.h', - 'foo.c: gen.py'], 'foo.c', set({'gen.py'})), - # linue continuation, multiple targets - (['foo.o \\', 'foo.h: bar'], 'foo.h', set({'bar'})), - (['foo.o \\', 'foo.h: bar'], 'foo.o', set({'bar'})), - # \\ handling - (['foo: Program\\ F\\iles\\\\X'], 'foo', set({'Program Files\\X'})), - # $ handling - (['f$o.o: c/b'], 'f$o.o', set({'c/b'})), - (['f$$o.o: c/b'], 'f$o.o', set({'c/b'})), - # cycles - (['a: b', 'b: a'], 'a', set({'a', 'b'})), - (['a: b', 'b: a'], 'b', set({'a', 'b'})), - ]: - d = mesonbuild.depfile.DepFile(f) - deps = d.get_all_dependencies(target) - self.assertEqual(deps, expdeps) - - def test_log_once(self): - f = io.StringIO() - with mock.patch('mesonbuild.mlog.log_file', f), \ - mock.patch('mesonbuild.mlog._logged_once', set()): - mesonbuild.mlog.log_once('foo') - mesonbuild.mlog.log_once('foo') - actual = f.getvalue().strip() - self.assertEqual(actual, 'foo', actual) - - def test_log_once_ansi(self): - f = io.StringIO() - with mock.patch('mesonbuild.mlog.log_file', f), \ - mock.patch('mesonbuild.mlog._logged_once', set()): - mesonbuild.mlog.log_once(mesonbuild.mlog.bold('foo')) - mesonbuild.mlog.log_once(mesonbuild.mlog.bold('foo')) - actual = f.getvalue().strip() - self.assertEqual(actual.count('foo'), 1, actual) - - mesonbuild.mlog.log_once('foo') - actual = f.getvalue().strip() - self.assertEqual(actual.count('foo'), 1, actual) - - f.truncate() - - mesonbuild.mlog.warning('bar', once=True) - mesonbuild.mlog.warning('bar', once=True) - actual = f.getvalue().strip() - self.assertEqual(actual.count('bar'), 1, actual) - - def test_sort_libpaths(self): - sort_libpaths = mesonbuild.dependencies.base.sort_libpaths - self.assertEqual(sort_libpaths( - ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib'], - ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), - ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) - self.assertEqual(sort_libpaths( - ['/usr/local/lib', '/home/mesonuser/.local/lib', '/usr/lib'], - ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), - ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) - self.assertEqual(sort_libpaths( - ['/usr/lib', '/usr/local/lib', '/home/mesonuser/.local/lib'], - ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), - ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) - self.assertEqual(sort_libpaths( - ['/usr/lib', '/usr/local/lib', '/home/mesonuser/.local/lib'], - ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/libdata/pkgconfig']), - ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) - - -@unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release') -class DataTests(unittest.TestCase): - - def test_snippets(self): - hashcounter = re.compile('^ *(#)+') - snippet_dir = Path('docs/markdown/snippets') - self.assertTrue(snippet_dir.is_dir()) - for f in snippet_dir.glob('*'): - self.assertTrue(f.is_file()) - if f.parts[-1].endswith('~'): - continue - if f.suffix == '.md': - in_code_block = False - with f.open() as snippet: - for line in snippet: - if line.startswith(' '): - continue - if line.startswith('```'): - in_code_block = not in_code_block - if in_code_block: - continue - m = re.match(hashcounter, line) - if m: - self.assertEqual(len(m.group(0)), 2, 'All headings in snippets must have two hash symbols: ' + f.name) - self.assertFalse(in_code_block, 'Unclosed code block.') - else: - if f.name != 'add_release_note_snippets_here': - self.assertTrue(False, 'A file without .md suffix in snippets dir: ' + f.name) - - def test_compiler_options_documented(self): - ''' - Test that C and C++ compiler options and base options are documented in - Builtin-Options.md. Only tests the default compiler for the current - platform on the CI. - ''' - md = None - with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f: - md = f.read() - self.assertIsNotNone(md) - env = get_fake_env() - # FIXME: Support other compilers - cc = env.detect_c_compiler(MachineChoice.HOST) - cpp = env.detect_cpp_compiler(MachineChoice.HOST) - for comp in (cc, cpp): - for opt in comp.get_options().keys(): - self.assertIn(opt, md) - for opt in comp.base_options: - self.assertIn(opt, md) - self.assertNotIn('b_unknown', md) - - def test_builtin_options_documented(self): - ''' - Test that universal options and base options are documented in - Builtin-Options.md. - ''' - md = None - with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f: - md = f.read() - self.assertIsNotNone(md) - - found_entries = set() - sections = list(re.finditer(r"^## (.+)$", md, re.MULTILINE)) + [None] - - for s1, s2 in zip(sections[:], sections[1:]): - if s1.group(1) == "Universal options": - # Extract the content for this section - end = s2.start() if s2 is not None else len(md) - content = md[s1.end():end] - subsections = list(re.finditer(r"^### (.+)$", content, re.MULTILINE)) + [None] - - for sub1, sub2 in zip(subsections[:], subsections[1:]): - if sub1.group(1) == "Directories" or sub1.group(1) == "Core options": - # Extract the content for this subsection - sub_end = sub2.start() if sub2 is not None else len(content) - subcontent = content[sub1.end():sub_end] - # Find the list entries - arches = [m.group(1) for m in re.finditer(r"^\| (\w+) .* \|", subcontent, re.MULTILINE)] - # Drop the header - arches = set(arches[1:]) - - self.assertEqual(len(found_entries & arches), 0) - found_entries |= arches - break - - self.assertEqual(found_entries, set([ - *mesonbuild.coredata.builtin_options.keys(), - *mesonbuild.coredata.builtin_options_per_machine.keys() - ])) - - def test_cpu_families_documented(self): - with open("docs/markdown/Reference-tables.md", encoding='utf-8') as f: - md = f.read() - self.assertIsNotNone(md) - - sections = list(re.finditer(r"^## (.+)$", md, re.MULTILINE)) - for s1, s2 in zip(sections[::2], sections[1::2]): - if s1.group(1) == "CPU families": - # Extract the content for this section - content = md[s1.end():s2.start()] - # Find the list entries - arches = [m.group(1) for m in re.finditer(r"^\| (\w+) +\|", content, re.MULTILINE)] - # Drop the header - arches = set(arches[1:]) - self.assertEqual(arches, set(mesonbuild.environment.known_cpu_families)) - - def test_markdown_files_in_sitemap(self): - ''' - Test that each markdown files in docs/markdown is referenced in sitemap.txt - ''' - with open("docs/sitemap.txt", encoding='utf-8') as f: - md = f.read() - self.assertIsNotNone(md) - toc = list(m.group(1) for m in re.finditer(r"^\s*(\w.*)$", md, re.MULTILINE)) - markdownfiles = [f.name for f in Path("docs/markdown").iterdir() if f.is_file() and f.suffix == '.md'] - exceptions = ['_Sidebar.md'] - for f in markdownfiles: - if f not in exceptions: - self.assertIn(f, toc) - - def test_vim_syntax_highlighting(self): - ''' - Ensure that vim syntax highlighting files were updated for new - functions in the global namespace in build files. - ''' - env = get_fake_env() - interp = Interpreter(FakeBuild(env), mock=True) - with open('data/syntax-highlighting/vim/syntax/meson.vim') as f: - res = re.search(r'syn keyword mesonBuiltin(\s+\\\s\w+)+', f.read(), re.MULTILINE) - defined = set([a.strip() for a in res.group().split('\\')][1:]) - self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys()))) - - @unittest.skipIf(is_pull(), 'Skipping because this is a pull request') - def test_json_grammar_syntax_highlighting(self): - ''' - Ensure that syntax highlighting JSON grammar written by TingPing was - updated for new functions in the global namespace in build files. - https://github.com/TingPing/language-meson/ - ''' - env = get_fake_env() - interp = Interpreter(FakeBuild(env), mock=True) - url = 'https://raw.githubusercontent.com/TingPing/language-meson/master/grammars/meson.json' - try: - # Use a timeout to avoid blocking forever in case the network is - # slow or unavailable in a weird way - r = urllib.request.urlopen(url, timeout=URLOPEN_TIMEOUT) - except urllib.error.URLError as e: - # Skip test when network is not available, such as during packaging - # by a distro or Flatpak - if not isinstance(e, urllib.error.HTTPError): - raise unittest.SkipTest('Network unavailable') - # Don't fail the test if github is down, but do fail if 4xx - if e.code >= 500: - raise unittest.SkipTest('Server error ' + str(e.code)) - raise e - # On Python 3.5, we must decode bytes to string. Newer versions don't require that. - grammar = json.loads(r.read().decode('utf-8', 'surrogatepass')) - for each in grammar['patterns']: - if 'name' in each and each['name'] == 'support.function.builtin.meson': - # The string is of the form: (?x)\\b(func1|func2|...\n)\\b\\s*(?=\\() and - # we convert that to [func1, func2, ...] without using regex to parse regex - funcs = set(each['match'].split('\\b(')[1].split('\n')[0].split('|')) - if 'name' in each and each['name'] == 'support.variable.meson': - # \\b(builtin1|builtin2...)\\b - builtin = set(each['match'].split('\\b(')[1].split(')\\b')[0].split('|')) - self.assertEqual(builtin, set(interp.builtin.keys())) - self.assertEqual(funcs, set(interp.funcs.keys())) - - def test_all_functions_defined_in_ast_interpreter(self): - ''' - Ensure that the all functions defined in the Interpreter are also defined - in the AstInterpreter (and vice versa). - ''' - env = get_fake_env() - interp = Interpreter(FakeBuild(env), mock=True) - astint = AstInterpreter('.', '') - self.assertEqual(set(interp.funcs.keys()), set(astint.funcs.keys())) - - -class BasePlatformTests(unittest.TestCase): - def setUp(self): - super().setUp() - self.maxDiff = None - src_root = os.path.dirname(__file__) - src_root = os.path.join(os.getcwd(), src_root) - self.src_root = src_root - self.prefix = '/usr' - self.libdir = 'lib' - # Get the backend - # FIXME: Extract this from argv? - self.backend = getattr(Backend, os.environ.get('MESON_UNIT_TEST_BACKEND', 'ninja')) - self.meson_args = ['--backend=' + self.backend.name] - self.meson_cross_file = None - self.meson_command = python_command + [get_meson_script()] - self.setup_command = self.meson_command + self.meson_args - self.mconf_command = self.meson_command + ['configure'] - self.mintro_command = self.meson_command + ['introspect'] - self.wrap_command = self.meson_command + ['wrap'] - self.rewrite_command = self.meson_command + ['rewrite'] - # Backend-specific build commands - self.build_command, self.clean_command, self.test_command, self.install_command, \ - self.uninstall_command = get_backend_commands(self.backend) - # Test directories - self.common_test_dir = os.path.join(src_root, 'test cases/common') - self.vala_test_dir = os.path.join(src_root, 'test cases/vala') - self.framework_test_dir = os.path.join(src_root, 'test cases/frameworks') - self.unit_test_dir = os.path.join(src_root, 'test cases/unit') - self.rewrite_test_dir = os.path.join(src_root, 'test cases/rewrite') - # Misc stuff - self.orig_env = os.environ.copy() - if self.backend is Backend.ninja: - self.no_rebuild_stdout = ['ninja: no work to do.', 'samu: nothing to do'] - else: - # VS doesn't have a stable output when no changes are done - # XCode backend is untested with unit tests, help welcome! - self.no_rebuild_stdout = ['UNKNOWN BACKEND {!r}'.format(self.backend.name)] - - self.builddirs = [] - self.new_builddir() - - def change_builddir(self, newdir): - self.builddir = newdir - self.privatedir = os.path.join(self.builddir, 'meson-private') - self.logdir = os.path.join(self.builddir, 'meson-logs') - self.installdir = os.path.join(self.builddir, 'install') - self.distdir = os.path.join(self.builddir, 'meson-dist') - self.mtest_command = self.meson_command + ['test', '-C', self.builddir] - self.builddirs.append(self.builddir) - - def new_builddir(self): - if not is_cygwin(): - # Keep builddirs inside the source tree so that virus scanners - # don't complain - newdir = tempfile.mkdtemp(dir=os.getcwd()) - else: - # But not on Cygwin because that breaks the umask tests. See: - # https://github.com/mesonbuild/meson/pull/5546#issuecomment-509666523 - newdir = tempfile.mkdtemp() - # In case the directory is inside a symlinked directory, find the real - # path otherwise we might not find the srcdir from inside the builddir. - newdir = os.path.realpath(newdir) - self.change_builddir(newdir) - - def _print_meson_log(self): - log = os.path.join(self.logdir, 'meson-log.txt') - if not os.path.isfile(log): - print("{!r} doesn't exist".format(log)) - return - with open(log, 'r', encoding='utf-8') as f: - print(f.read()) - - def tearDown(self): - for path in self.builddirs: - try: - windows_proof_rmtree(path) - except FileNotFoundError: - pass - os.environ.clear() - os.environ.update(self.orig_env) - super().tearDown() - - def _run(self, command, *, workdir=None, override_envvars=None): - ''' - Run a command while printing the stdout and stderr to stdout, - and also return a copy of it - ''' - # If this call hangs CI will just abort. It is very hard to distinguish - # between CI issue and test bug in that case. Set timeout and fail loud - # instead. - if override_envvars is None: - env = None - else: - env = os.environ.copy() - env.update(override_envvars) - - p = subprocess.run(command, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, env=env, - universal_newlines=True, cwd=workdir, timeout=60 * 5) - print(p.stdout) - if p.returncode != 0: - if 'MESON_SKIP_TEST' in p.stdout: - raise unittest.SkipTest('Project requested skipping.') - raise subprocess.CalledProcessError(p.returncode, command, output=p.stdout) - return p.stdout - - def init(self, srcdir, *, - extra_args=None, - default_args=True, - inprocess=False, - override_envvars=None): - self.assertPathExists(srcdir) - if extra_args is None: - extra_args = [] - if not isinstance(extra_args, list): - extra_args = [extra_args] - args = [srcdir, self.builddir] - if default_args: - args += ['--prefix', self.prefix, - '--libdir', self.libdir] - if self.meson_cross_file: - args += ['--cross-file', self.meson_cross_file] - self.privatedir = os.path.join(self.builddir, 'meson-private') - if inprocess: - try: - if override_envvars is not None: - old_envvars = os.environ.copy() - os.environ.update(override_envvars) - (returncode, out, err) = run_configure_inprocess(self.meson_args + args + extra_args) - if override_envvars is not None: - os.environ.clear() - os.environ.update(old_envvars) - if 'MESON_SKIP_TEST' in out: - raise unittest.SkipTest('Project requested skipping.') - if returncode != 0: - self._print_meson_log() - print('Stdout:\n') - print(out) - print('Stderr:\n') - print(err) - raise RuntimeError('Configure failed') - except Exception: - self._print_meson_log() - raise - finally: - # Close log file to satisfy Windows file locking - mesonbuild.mlog.shutdown() - mesonbuild.mlog.log_dir = None - mesonbuild.mlog.log_file = None - else: - try: - out = self._run(self.setup_command + args + extra_args, override_envvars=override_envvars) - except unittest.SkipTest: - raise unittest.SkipTest('Project requested skipping: ' + srcdir) - except Exception: - self._print_meson_log() - raise - return out - - def build(self, target=None, *, extra_args=None, override_envvars=None): - if extra_args is None: - extra_args = [] - # Add arguments for building the target (if specified), - # and using the build dir (if required, with VS) - args = get_builddir_target_args(self.backend, self.builddir, target) - return self._run(self.build_command + args + extra_args, workdir=self.builddir, override_envvars=override_envvars) - - def clean(self, *, override_envvars=None): - dir_args = get_builddir_target_args(self.backend, self.builddir, None) - self._run(self.clean_command + dir_args, workdir=self.builddir, override_envvars=override_envvars) - - def run_tests(self, *, inprocess=False, override_envvars=None): - if not inprocess: - self._run(self.test_command, workdir=self.builddir, override_envvars=override_envvars) - else: - if override_envvars is not None: - old_envvars = os.environ.copy() - os.environ.update(override_envvars) - try: - run_mtest_inprocess(['-C', self.builddir]) - finally: - if override_envvars is not None: - os.environ.clear() - os.environ.update(old_envvars) - - def install(self, *, use_destdir=True, override_envvars=None): - if self.backend is not Backend.ninja: - raise unittest.SkipTest('{!r} backend can\'t install files'.format(self.backend.name)) - if use_destdir: - destdir = {'DESTDIR': self.installdir} - if override_envvars is None: - override_envvars = destdir - else: - override_envvars.update(destdir) - 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) - - def run_target(self, target, *, override_envvars=None): - ''' - Run a Ninja target while printing the stdout and stderr to stdout, - and also return a copy of it - ''' - return self.build(target=target, override_envvars=override_envvars) - - def setconf(self, arg, will_build=True): - if not isinstance(arg, list): - arg = [arg] - if will_build: - ensure_backend_detects_changes(self.backend) - self._run(self.mconf_command + arg + [self.builddir]) - - def wipe(self): - windows_proof_rmtree(self.builddir) - - def utime(self, f): - ensure_backend_detects_changes(self.backend) - os.utime(f) - - def get_compdb(self): - if self.backend is not Backend.ninja: - raise unittest.SkipTest('Compiler db not available with {} backend'.format(self.backend.name)) - try: - with open(os.path.join(self.builddir, 'compile_commands.json')) as ifile: - contents = json.load(ifile) - except FileNotFoundError: - raise unittest.SkipTest('Compiler db not found') - # If Ninja is using .rsp files, generate them, read their contents, and - # replace it as the command for all compile commands in the parsed json. - if len(contents) > 0 and contents[0]['command'].endswith('.rsp'): - # Pretend to build so that the rsp files are generated - self.build(extra_args=['-d', 'keeprsp', '-n']) - for each in contents: - # Extract the actual command from the rsp file - compiler, rsp = each['command'].split(' @') - rsp = os.path.join(self.builddir, rsp) - # Replace the command with its contents - with open(rsp, 'r', encoding='utf-8') as f: - each['command'] = compiler + ' ' + f.read() - return contents - - def get_meson_log(self): - with open(os.path.join(self.builddir, 'meson-logs', 'meson-log.txt')) as f: - return f.readlines() - - def get_meson_log_compiler_checks(self): - ''' - Fetch a list command-lines run by meson for compiler checks. - Each command-line is returned as a list of arguments. - ''' - log = self.get_meson_log() - prefix = 'Command line:' - cmds = [l[len(prefix):].split() for l in log if l.startswith(prefix)] - return cmds - - def introspect(self, args): - if isinstance(args, str): - args = [args] - out = subprocess.check_output(self.mintro_command + args + [self.builddir], - universal_newlines=True) - return json.loads(out) - - def introspect_directory(self, directory, args): - if isinstance(args, str): - args = [args] - out = subprocess.check_output(self.mintro_command + args + [directory], - universal_newlines=True) - try: - obj = json.loads(out) - except Exception as e: - print(out) - raise e - return obj - - def assertPathEqual(self, path1, path2): - ''' - Handles a lot of platform-specific quirks related to paths such as - separator, case-sensitivity, etc. - ''' - self.assertEqual(PurePath(path1), PurePath(path2)) - - def assertPathListEqual(self, pathlist1, pathlist2): - self.assertEqual(len(pathlist1), len(pathlist2)) - worklist = list(zip(pathlist1, pathlist2)) - for i in worklist: - if i[0] is None: - self.assertEqual(i[0], i[1]) - else: - self.assertPathEqual(i[0], i[1]) - - def assertPathBasenameEqual(self, path, basename): - msg = '{!r} does not end with {!r}'.format(path, basename) - # We cannot use os.path.basename because it returns '' when the path - # ends with '/' for some silly reason. This is not how the UNIX utility - # `basename` works. - path_basename = PurePath(path).parts[-1] - self.assertEqual(PurePath(path_basename), PurePath(basename), msg) - - def assertBuildIsNoop(self): - ret = self.build() - if self.backend is Backend.ninja: - self.assertIn(ret.split('\n')[-2], self.no_rebuild_stdout) - elif self.backend is Backend.vs: - # Ensure that some target said that no rebuild was done - self.assertIn('CustomBuild:\n All outputs are up-to-date.', ret) - self.assertIn('ClCompile:\n All outputs are up-to-date.', ret) - self.assertIn('Link:\n All outputs are up-to-date.', ret) - # Ensure that no targets were built - clre = re.compile('ClCompile:\n [^\n]*cl', flags=re.IGNORECASE) - linkre = re.compile('Link:\n [^\n]*link', flags=re.IGNORECASE) - self.assertNotRegex(ret, clre) - self.assertNotRegex(ret, linkre) - elif self.backend is Backend.xcode: - raise unittest.SkipTest('Please help us fix this test on the xcode backend') - else: - raise RuntimeError('Invalid backend: {!r}'.format(self.backend.name)) - - def assertRebuiltTarget(self, target): - ret = self.build() - if self.backend is Backend.ninja: - self.assertIn('Linking target {}'.format(target), ret) - elif self.backend is Backend.vs: - # Ensure that this target was rebuilt - linkre = re.compile('Link:\n [^\n]*link[^\n]*' + target, flags=re.IGNORECASE) - self.assertRegex(ret, linkre) - elif self.backend is Backend.xcode: - raise unittest.SkipTest('Please help us fix this test on the xcode backend') - else: - raise RuntimeError('Invalid backend: {!r}'.format(self.backend.name)) - - def assertPathExists(self, path): - m = 'Path {!r} should exist'.format(path) - self.assertTrue(os.path.exists(path), msg=m) - - def assertPathDoesNotExist(self, path): - m = 'Path {!r} should not exist'.format(path) - self.assertFalse(os.path.exists(path), msg=m) - - -class AllPlatformTests(BasePlatformTests): - ''' - Tests that should run on all platforms - ''' - - def test_default_options_prefix(self): - ''' - Tests that setting a prefix in default_options in project() works. - Can't be an ordinary test because we pass --prefix to meson there. - https://github.com/mesonbuild/meson/issues/1349 - ''' - testdir = os.path.join(self.common_test_dir, '90 default options') - self.init(testdir, default_args=False) - opts = self.introspect('--buildoptions') - for opt in opts: - if opt['name'] == 'prefix': - prefix = opt['value'] - self.assertEqual(prefix, '/absoluteprefix') - - def test_do_conf_file_preserve_newlines(self): - - def conf_file(in_data, confdata): - with temp_filename() as fin: - with open(fin, 'wb') as fobj: - fobj.write(in_data.encode('utf-8')) - with temp_filename() as fout: - mesonbuild.mesonlib.do_conf_file(fin, fout, confdata, 'meson') - with open(fout, 'rb') as fobj: - return fobj.read().decode('utf-8') - - confdata = {'VAR': ('foo', 'bar')} - self.assertEqual(conf_file('@VAR@\n@VAR@\n', confdata), 'foo\nfoo\n') - self.assertEqual(conf_file('@VAR@\r\n@VAR@\r\n', confdata), 'foo\r\nfoo\r\n') - - def test_absolute_prefix_libdir(self): - ''' - Tests that setting absolute paths for --prefix and --libdir work. Can't - be an ordinary test because these are set via the command-line. - https://github.com/mesonbuild/meson/issues/1341 - https://github.com/mesonbuild/meson/issues/1345 - ''' - testdir = os.path.join(self.common_test_dir, '90 default options') - prefix = '/someabs' - libdir = 'libdir' - extra_args = ['--prefix=' + prefix, - # This can just be a relative path, but we want to test - # that passing this as an absolute path also works - '--libdir=' + prefix + '/' + libdir] - self.init(testdir, extra_args=extra_args, default_args=False) - opts = self.introspect('--buildoptions') - for opt in opts: - if opt['name'] == 'prefix': - self.assertEqual(prefix, opt['value']) - elif opt['name'] == 'libdir': - self.assertEqual(libdir, opt['value']) - - def test_libdir_must_be_inside_prefix(self): - ''' - Tests that libdir is forced to be inside prefix no matter how it is set. - Must be a unit test for obvious reasons. - ''' - testdir = os.path.join(self.common_test_dir, '1 trivial') - # libdir being inside prefix is ok - args = ['--prefix', '/opt', '--libdir', '/opt/lib32'] - self.init(testdir, extra_args=args) - self.wipe() - # libdir not being inside prefix is not ok - args = ['--prefix', '/usr', '--libdir', '/opt/lib32'] - self.assertRaises(subprocess.CalledProcessError, self.init, testdir, extra_args=args) - self.wipe() - # libdir must be inside prefix even when set via mesonconf - self.init(testdir) - self.assertRaises(subprocess.CalledProcessError, self.setconf, '-Dlibdir=/opt', False) - - def test_prefix_dependent_defaults(self): - ''' - Tests that configured directory paths are set to prefix dependent - defaults. - ''' - testdir = os.path.join(self.common_test_dir, '1 trivial') - expected = { - '/opt': {'prefix': '/opt', - 'bindir': 'bin', 'datadir': 'share', 'includedir': 'include', - 'infodir': 'share/info', - 'libexecdir': 'libexec', 'localedir': 'share/locale', - 'localstatedir': 'var', 'mandir': 'share/man', - 'sbindir': 'sbin', 'sharedstatedir': 'com', - 'sysconfdir': 'etc'}, - '/usr': {'prefix': '/usr', - 'bindir': 'bin', 'datadir': 'share', 'includedir': 'include', - 'infodir': 'share/info', - 'libexecdir': 'libexec', 'localedir': 'share/locale', - 'localstatedir': '/var', 'mandir': 'share/man', - 'sbindir': 'sbin', 'sharedstatedir': '/var/lib', - 'sysconfdir': '/etc'}, - '/usr/local': {'prefix': '/usr/local', - 'bindir': 'bin', 'datadir': 'share', - 'includedir': 'include', 'infodir': 'share/info', - 'libexecdir': 'libexec', - 'localedir': 'share/locale', - 'localstatedir': '/var/local', 'mandir': 'share/man', - 'sbindir': 'sbin', 'sharedstatedir': '/var/local/lib', - 'sysconfdir': 'etc'}, - # N.B. We don't check 'libdir' as it's platform dependent, see - # default_libdir(): - } - - if mesonbuild.mesonlib.default_prefix() == '/usr/local': - expected[None] = expected['/usr/local'] - - for prefix in expected: - args = [] - if prefix: - args += ['--prefix', prefix] - self.init(testdir, extra_args=args, default_args=False) - opts = self.introspect('--buildoptions') - for opt in opts: - name = opt['name'] - value = opt['value'] - if name in expected[prefix]: - self.assertEqual(value, expected[prefix][name]) - self.wipe() - - def test_default_options_prefix_dependent_defaults(self): - ''' - Tests that setting a prefix in default_options in project() sets prefix - dependent defaults for other options, and that those defaults can - be overridden in default_options or by the command line. - ''' - testdir = os.path.join(self.common_test_dir, '168 default options prefix dependent defaults') - expected = { - '': - {'prefix': '/usr', - 'sysconfdir': '/etc', - 'localstatedir': '/var', - 'sharedstatedir': '/sharedstate'}, - '--prefix=/usr': - {'prefix': '/usr', - 'sysconfdir': '/etc', - 'localstatedir': '/var', - 'sharedstatedir': '/sharedstate'}, - '--sharedstatedir=/var/state': - {'prefix': '/usr', - 'sysconfdir': '/etc', - 'localstatedir': '/var', - 'sharedstatedir': '/var/state'}, - '--sharedstatedir=/var/state --prefix=/usr --sysconfdir=sysconf': - {'prefix': '/usr', - 'sysconfdir': 'sysconf', - 'localstatedir': '/var', - 'sharedstatedir': '/var/state'}, - } - for args in expected: - self.init(testdir, extra_args=args.split(), default_args=False) - opts = self.introspect('--buildoptions') - for opt in opts: - name = opt['name'] - value = opt['value'] - if name in expected[args]: - self.assertEqual(value, expected[args][name]) - self.wipe() - - def test_clike_get_library_dirs(self): - env = get_fake_env() - cc = env.detect_c_compiler(MachineChoice.HOST) - for d in cc.get_library_dirs(env): - self.assertTrue(os.path.exists(d)) - self.assertTrue(os.path.isdir(d)) - self.assertTrue(os.path.isabs(d)) - - def test_static_library_overwrite(self): - ''' - Tests that static libraries are never appended to, always overwritten. - Has to be a unit test because this involves building a project, - reconfiguring, and building it again so that `ar` is run twice on the - same static library. - https://github.com/mesonbuild/meson/issues/1355 - ''' - testdir = os.path.join(self.common_test_dir, '3 static') - env = get_fake_env(testdir, self.builddir, self.prefix) - cc = env.detect_c_compiler(MachineChoice.HOST) - static_linker = env.detect_static_linker(cc) - if is_windows(): - raise unittest.SkipTest('https://github.com/mesonbuild/meson/issues/1526') - if not isinstance(static_linker, mesonbuild.linkers.ArLinker): - raise unittest.SkipTest('static linker is not `ar`') - # Configure - self.init(testdir) - # Get name of static library - targets = self.introspect('--targets') - self.assertEqual(len(targets), 1) - libname = targets[0]['filename'][0] - # Build and get contents of static library - self.build() - before = self._run(['ar', 't', os.path.join(self.builddir, libname)]).split() - # Filter out non-object-file contents - before = [f for f in before if f.endswith(('.o', '.obj'))] - # Static library should contain only one object - self.assertEqual(len(before), 1, msg=before) - # Change the source to be built into the static library - self.setconf('-Dsource=libfile2.c') - self.build() - after = self._run(['ar', 't', os.path.join(self.builddir, libname)]).split() - # Filter out non-object-file contents - after = [f for f in after if f.endswith(('.o', '.obj'))] - # Static library should contain only one object - self.assertEqual(len(after), 1, msg=after) - # and the object must have changed - self.assertNotEqual(before, after) - - def test_static_compile_order(self): - ''' - Test that the order of files in a compiler command-line while compiling - and linking statically is deterministic. This can't be an ordinary test - case because we need to inspect the compiler database. - https://github.com/mesonbuild/meson/pull/951 - ''' - testdir = os.path.join(self.common_test_dir, '5 linkstatic') - self.init(testdir) - compdb = self.get_compdb() - # Rules will get written out in this order - self.assertTrue(compdb[0]['file'].endswith("libfile.c")) - self.assertTrue(compdb[1]['file'].endswith("libfile2.c")) - self.assertTrue(compdb[2]['file'].endswith("libfile3.c")) - self.assertTrue(compdb[3]['file'].endswith("libfile4.c")) - # FIXME: We don't have access to the linker command - - def test_run_target_files_path(self): - ''' - Test that run_targets are run from the correct directory - https://github.com/mesonbuild/meson/issues/957 - ''' - testdir = os.path.join(self.common_test_dir, '54 run target') - self.init(testdir) - self.run_target('check_exists') - - def test_install_introspection(self): - ''' - Tests that the Meson introspection API exposes install filenames correctly - https://github.com/mesonbuild/meson/issues/829 - ''' - if self.backend is not Backend.ninja: - raise unittest.SkipTest('{!r} backend can\'t install files'.format(self.backend.name)) - testdir = os.path.join(self.common_test_dir, '8 install') - self.init(testdir) - intro = self.introspect('--targets') - if intro[0]['type'] == 'executable': - intro = intro[::-1] - self.assertPathListEqual(intro[0]['install_filename'], ['/usr/lib/libstat.a']) - self.assertPathListEqual(intro[1]['install_filename'], ['/usr/bin/prog' + exe_suffix]) - - def test_install_subdir_introspection(self): - ''' - Test that the Meson introspection API also contains subdir install information - https://github.com/mesonbuild/meson/issues/5556 - ''' - testdir = os.path.join(self.common_test_dir, '62 install subdir') - self.init(testdir) - intro = self.introspect('--installed') - expected = { - 'sub2': 'share/sub2', - 'subdir/sub1': 'share/sub1', - 'subdir/sub_elided': 'share', - 'sub1': 'share/sub1', - 'sub/sub1': 'share/sub1', - 'sub_elided': 'share', - 'nested_elided/sub': 'share', - } - - self.assertEqual(len(intro), len(expected)) - - # Convert expected to PurePath - expected_converted = {PurePath(os.path.join(testdir, key)): PurePath(os.path.join(self.prefix, val)) for key, val in expected.items()} - intro_converted = {PurePath(key): PurePath(val) for key, val in intro.items()} - - for src, dst in expected_converted.items(): - self.assertIn(src, intro_converted) - self.assertEqual(dst, intro_converted[src]) - - def test_install_introspection_multiple_outputs(self): - ''' - Tests that the Meson introspection API exposes multiple install filenames correctly without crashing - https://github.com/mesonbuild/meson/pull/4555 - - Reverted to the first file only because of https://github.com/mesonbuild/meson/pull/4547#discussion_r244173438 - TODO Change the format to a list officially in a followup PR - ''' - if self.backend is not Backend.ninja: - raise unittest.SkipTest('{!r} backend can\'t install files'.format(self.backend.name)) - testdir = os.path.join(self.common_test_dir, '144 custom target multiple outputs') - self.init(testdir) - intro = self.introspect('--targets') - if intro[0]['type'] == 'executable': - intro = intro[::-1] - self.assertPathListEqual(intro[0]['install_filename'], ['/usr/include/diff.h', '/usr/bin/diff.sh']) - self.assertPathListEqual(intro[1]['install_filename'], ['/opt/same.h', '/opt/same.sh']) - self.assertPathListEqual(intro[2]['install_filename'], ['/usr/include/first.h', None]) - self.assertPathListEqual(intro[3]['install_filename'], [None, '/usr/bin/second.sh']) - - def test_install_log_content(self): - ''' - Tests that the install-log.txt is consistent with the installed files and directories. - Specifically checks that the log file only contains one entry per file/directory. - https://github.com/mesonbuild/meson/issues/4499 - ''' - testdir = os.path.join(self.common_test_dir, '62 install subdir') - self.init(testdir) - self.install() - installpath = Path(self.installdir) - # Find installed files and directories - expected = {installpath: 0} - for name in installpath.rglob('*'): - expected[name] = 0 - # Find logged files and directories - with Path(self.builddir, 'meson-logs', 'install-log.txt').open() as f: - logged = list(map(lambda l: Path(l.strip()), - filter(lambda l: not l.startswith('#'), - f.readlines()))) - for name in logged: - self.assertTrue(name in expected, 'Log contains extra entry {}'.format(name)) - expected[name] += 1 - - for name, count in expected.items(): - self.assertGreater(count, 0, 'Log is missing entry for {}'.format(name)) - self.assertLess(count, 2, 'Log has multiple entries for {}'.format(name)) - - def test_uninstall(self): - exename = os.path.join(self.installdir, 'usr/bin/prog' + exe_suffix) - testdir = os.path.join(self.common_test_dir, '8 install') - self.init(testdir) - self.assertPathDoesNotExist(exename) - self.install() - self.assertPathExists(exename) - self.uninstall() - self.assertPathDoesNotExist(exename) - - def test_forcefallback(self): - testdir = os.path.join(self.unit_test_dir, '31 forcefallback') - self.init(testdir, extra_args=['--wrap-mode=forcefallback']) - self.build() - self.run_tests() - - def test_env_ops_dont_stack(self): - ''' - Test that env ops prepend/append do not stack, and that this usage issues a warning - ''' - testdir = os.path.join(self.unit_test_dir, '63 test env does not stack') - out = self.init(testdir) - self.assertRegex(out, r'WARNING: Overriding.*TEST_VAR_APPEND') - self.assertRegex(out, r'WARNING: Overriding.*TEST_VAR_PREPEND') - self.assertNotRegex(out, r'WARNING: Overriding.*TEST_VAR_SET') - self.run_tests() - - def test_testsetups(self): - if not shutil.which('valgrind'): - raise unittest.SkipTest('Valgrind not installed.') - testdir = os.path.join(self.unit_test_dir, '2 testsetups') - self.init(testdir) - self.build() - # Run tests without setup - self.run_tests() - with open(os.path.join(self.logdir, 'testlog.txt')) as f: - basic_log = f.read() - # Run buggy test with setup that has env that will make it fail - self.assertRaises(subprocess.CalledProcessError, - self._run, self.mtest_command + ['--setup=valgrind']) - with open(os.path.join(self.logdir, 'testlog-valgrind.txt')) as f: - vg_log = f.read() - self.assertFalse('TEST_ENV is set' in basic_log) - self.assertFalse('Memcheck' in basic_log) - self.assertTrue('TEST_ENV is set' in vg_log) - self.assertTrue('Memcheck' in vg_log) - # Run buggy test with setup without env that will pass - self._run(self.mtest_command + ['--setup=wrapper']) - # Setup with no properties works - self._run(self.mtest_command + ['--setup=empty']) - # Setup with only env works - self._run(self.mtest_command + ['--setup=onlyenv']) - self._run(self.mtest_command + ['--setup=onlyenv2']) - self._run(self.mtest_command + ['--setup=onlyenv3']) - # Setup with only a timeout works - self._run(self.mtest_command + ['--setup=timeout']) - - def test_testsetup_selection(self): - testdir = os.path.join(self.unit_test_dir, '14 testsetup selection') - self.init(testdir) - self.build() - - # Run tests without setup - self.run_tests() - - self.assertRaises(subprocess.CalledProcessError, self._run, self.mtest_command + ['--setup=missingfromfoo']) - self._run(self.mtest_command + ['--setup=missingfromfoo', '--no-suite=foo:']) - - self._run(self.mtest_command + ['--setup=worksforall']) - self._run(self.mtest_command + ['--setup=main:worksforall']) - - self.assertRaises(subprocess.CalledProcessError, self._run, - self.mtest_command + ['--setup=onlyinbar']) - self.assertRaises(subprocess.CalledProcessError, self._run, - self.mtest_command + ['--setup=onlyinbar', '--no-suite=main:']) - self._run(self.mtest_command + ['--setup=onlyinbar', '--no-suite=main:', '--no-suite=foo:']) - self._run(self.mtest_command + ['--setup=bar:onlyinbar']) - self.assertRaises(subprocess.CalledProcessError, self._run, - self.mtest_command + ['--setup=foo:onlyinbar']) - self.assertRaises(subprocess.CalledProcessError, self._run, - self.mtest_command + ['--setup=main:onlyinbar']) - - def test_testsetup_default(self): - testdir = os.path.join(self.unit_test_dir, '49 testsetup default') - self.init(testdir) - self.build() - - # Run tests without --setup will cause the default setup to be used - self.run_tests() - with open(os.path.join(self.logdir, 'testlog.txt')) as f: - default_log = f.read() - - # Run tests with explicitly using the same setup that is set as default - self._run(self.mtest_command + ['--setup=mydefault']) - with open(os.path.join(self.logdir, 'testlog-mydefault.txt')) as f: - mydefault_log = f.read() - - # Run tests with another setup - self._run(self.mtest_command + ['--setup=other']) - with open(os.path.join(self.logdir, 'testlog-other.txt')) as f: - other_log = f.read() - - self.assertTrue('ENV_A is 1' in default_log) - self.assertTrue('ENV_B is 2' in default_log) - self.assertTrue('ENV_C is 2' in default_log) - - self.assertTrue('ENV_A is 1' in mydefault_log) - self.assertTrue('ENV_B is 2' in mydefault_log) - self.assertTrue('ENV_C is 2' in mydefault_log) - - self.assertTrue('ENV_A is 1' in other_log) - self.assertTrue('ENV_B is 3' in other_log) - self.assertTrue('ENV_C is 2' in other_log) - - def assertFailedTestCount(self, failure_count, command): - try: - self._run(command) - self.assertEqual(0, failure_count, 'Expected %d tests to fail.' % failure_count) - except subprocess.CalledProcessError as e: - self.assertEqual(e.returncode, failure_count) - - def test_suite_selection(self): - testdir = os.path.join(self.unit_test_dir, '4 suite selection') - self.init(testdir) - self.build() - - self.assertFailedTestCount(4, self.mtest_command) - - self.assertFailedTestCount(0, self.mtest_command + ['--suite', ':success']) - self.assertFailedTestCount(3, self.mtest_command + ['--suite', ':fail']) - self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', ':success']) - self.assertFailedTestCount(1, self.mtest_command + ['--no-suite', ':fail']) - - self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'mainprj']) - self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc']) - self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail']) - self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjmix']) - self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj']) - self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc']) - self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail']) - self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix']) - - self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'mainprj:fail']) - self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'mainprj:success']) - self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj:fail']) - self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'mainprj:success']) - - self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail:fail']) - self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjfail:success']) - self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail:fail']) - self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjfail:success']) - - self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc:fail']) - self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc:success']) - self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc:fail']) - self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc:success']) - - self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjmix:fail']) - self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjmix:success']) - self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix:fail']) - self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjmix:success']) - - self.assertFailedTestCount(2, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix:fail']) - self.assertFailedTestCount(3, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj']) - self.assertFailedTestCount(2, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj', '--no-suite', 'subprjmix:fail']) - self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj', '--no-suite', 'subprjmix:fail', 'mainprj-failing_test']) - - self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'subprjfail:fail', '--no-suite', 'subprjmix:fail']) - - def test_build_by_default(self): - testdir = os.path.join(self.common_test_dir, '133 build by default') - self.init(testdir) - self.build() - genfile1 = os.path.join(self.builddir, 'generated1.dat') - genfile2 = os.path.join(self.builddir, 'generated2.dat') - exe1 = os.path.join(self.builddir, 'fooprog' + exe_suffix) - exe2 = os.path.join(self.builddir, 'barprog' + exe_suffix) - self.assertPathExists(genfile1) - self.assertPathExists(genfile2) - self.assertPathDoesNotExist(exe1) - self.assertPathDoesNotExist(exe2) - self.build(target=('fooprog' + exe_suffix)) - self.assertPathExists(exe1) - self.build(target=('barprog' + exe_suffix)) - self.assertPathExists(exe2) - - def test_internal_include_order(self): - testdir = os.path.join(self.common_test_dir, '134 include order') - self.init(testdir) - execmd = fxecmd = None - for cmd in self.get_compdb(): - if 'someexe' in cmd['command']: - execmd = cmd['command'] - continue - if 'somefxe' in cmd['command']: - fxecmd = cmd['command'] - continue - if not execmd or not fxecmd: - raise Exception('Could not find someexe and somfxe commands') - # Check include order for 'someexe' - incs = [a for a in split_args(execmd) if a.startswith("-I")] - self.assertEqual(len(incs), 9) - # target private dir - someexe_id = Target.construct_id_from_path("sub4", "someexe", "@exe") - self.assertPathEqual(incs[0], "-I" + os.path.join("sub4", someexe_id)) - # target build subdir - self.assertPathEqual(incs[1], "-Isub4") - # target source subdir - self.assertPathBasenameEqual(incs[2], 'sub4') - # include paths added via per-target c_args: ['-I'...] - self.assertPathBasenameEqual(incs[3], 'sub3') - # target include_directories: build dir - self.assertPathEqual(incs[4], "-Isub2") - # target include_directories: source dir - self.assertPathBasenameEqual(incs[5], 'sub2') - # target internal dependency include_directories: build dir - self.assertPathEqual(incs[6], "-Isub1") - # target internal dependency include_directories: source dir - self.assertPathBasenameEqual(incs[7], 'sub1') - # custom target include dir - self.assertPathEqual(incs[8], '-Ictsub') - # Check include order for 'somefxe' - incs = [a for a in split_args(fxecmd) if a.startswith('-I')] - self.assertEqual(len(incs), 9) - # target private dir - self.assertPathEqual(incs[0], '-Isomefxe@exe') - # target build dir - self.assertPathEqual(incs[1], '-I.') - # target source dir - self.assertPathBasenameEqual(incs[2], os.path.basename(testdir)) - # target internal dependency correct include_directories: build dir - self.assertPathEqual(incs[3], "-Isub4") - # target internal dependency correct include_directories: source dir - self.assertPathBasenameEqual(incs[4], 'sub4') - # target internal dependency dep include_directories: build dir - self.assertPathEqual(incs[5], "-Isub1") - # target internal dependency dep include_directories: source dir - self.assertPathBasenameEqual(incs[6], 'sub1') - # target internal dependency wrong include_directories: build dir - self.assertPathEqual(incs[7], "-Isub2") - # target internal dependency wrong include_directories: source dir - self.assertPathBasenameEqual(incs[8], 'sub2') - - def test_compiler_detection(self): - ''' - Test that automatic compiler detection and setting from the environment - both work just fine. This is needed because while running project tests - and other unit tests, we always read CC/CXX/etc from the environment. - ''' - gnu = mesonbuild.compilers.GnuCompiler - clang = mesonbuild.compilers.ClangCompiler - intel = mesonbuild.compilers.IntelGnuLikeCompiler - msvc = (mesonbuild.compilers.VisualStudioCCompiler, mesonbuild.compilers.VisualStudioCPPCompiler) - clangcl = (mesonbuild.compilers.ClangClCCompiler, mesonbuild.compilers.ClangClCPPCompiler) - ar = mesonbuild.linkers.ArLinker - lib = mesonbuild.linkers.VisualStudioLinker - langs = [('c', 'CC'), ('cpp', 'CXX')] - if not is_windows() and platform.machine().lower() != 'e2k': - langs += [('objc', 'OBJC'), ('objcpp', 'OBJCXX')] - testdir = os.path.join(self.unit_test_dir, '5 compiler detection') - env = get_fake_env(testdir, self.builddir, self.prefix) - for lang, evar in langs: - # Detect with evar and do sanity checks on that - if evar in os.environ: - ecc = getattr(env, 'detect_{}_compiler'.format(lang))(MachineChoice.HOST) - self.assertTrue(ecc.version) - elinker = env.detect_static_linker(ecc) - # Pop it so we don't use it for the next detection - evalue = os.environ.pop(evar) - # Very rough/strict heuristics. Would never work for actual - # compiler detection, but should be ok for the tests. - ebase = os.path.basename(evalue) - if ebase.startswith('g') or ebase.endswith(('-gcc', '-g++')): - self.assertIsInstance(ecc, gnu) - self.assertIsInstance(elinker, ar) - elif 'clang-cl' in ebase: - self.assertIsInstance(ecc, clangcl) - self.assertIsInstance(elinker, lib) - elif 'clang' in ebase: - self.assertIsInstance(ecc, clang) - self.assertIsInstance(elinker, ar) - elif ebase.startswith('ic'): - self.assertIsInstance(ecc, intel) - self.assertIsInstance(elinker, ar) - elif ebase.startswith('cl'): - self.assertIsInstance(ecc, msvc) - self.assertIsInstance(elinker, lib) - else: - raise AssertionError('Unknown compiler {!r}'.format(evalue)) - # Check that we actually used the evalue correctly as the compiler - self.assertEqual(ecc.get_exelist(), split_args(evalue)) - # Do auto-detection of compiler based on platform, PATH, etc. - cc = getattr(env, 'detect_{}_compiler'.format(lang))(MachineChoice.HOST) - self.assertTrue(cc.version) - linker = env.detect_static_linker(cc) - # Check compiler type - if isinstance(cc, gnu): - self.assertIsInstance(linker, ar) - if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) - else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin) - if isinstance(cc, clangcl): - self.assertIsInstance(linker, lib) - self.assertIsInstance(cc.linker, mesonbuild.linkers.ClangClDynamicLinker) - if isinstance(cc, clang): - self.assertIsInstance(linker, ar) - if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) - elif is_windows(): - # This is clang, not clang-cl - self.assertIsInstance(cc.linker, mesonbuild.linkers.MSVCDynamicLinker) - else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin) - if isinstance(cc, intel): - self.assertIsInstance(linker, ar) - if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) - elif is_windows(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.XilinkDynamicLinker) - else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuDynamicLinker) - if isinstance(cc, msvc): - self.assertTrue(is_windows()) - self.assertIsInstance(linker, lib) - self.assertEqual(cc.id, 'msvc') - self.assertTrue(hasattr(cc, 'is_64')) - self.assertIsInstance(cc.linker, mesonbuild.linkers.MSVCDynamicLinker) - # If we're on Windows CI, we know what the compiler will be - if 'arch' in os.environ: - if os.environ['arch'] == 'x64': - self.assertTrue(cc.is_64) - else: - self.assertFalse(cc.is_64) - # Set evar ourselves to a wrapper script that just calls the same - # exelist + some argument. This is meant to test that setting - # something like `ccache gcc -pipe` or `distcc ccache gcc` works. - wrapper = os.path.join(testdir, 'compiler wrapper.py') - wrappercc = python_command + [wrapper] + cc.get_exelist() + ['-DSOME_ARG'] - wrappercc_s = '' - for w in wrappercc: - wrappercc_s += quote_arg(w) + ' ' - os.environ[evar] = wrappercc_s - wcc = getattr(env, 'detect_{}_compiler'.format(lang))(MachineChoice.HOST) - # Check static linker too - wrapperlinker = python_command + [wrapper] + linker.get_exelist() + linker.get_always_args() - wrapperlinker_s = '' - for w in wrapperlinker: - wrapperlinker_s += quote_arg(w) + ' ' - os.environ['AR'] = wrapperlinker_s - wlinker = env.detect_static_linker(wcc) - # Pop it so we don't use it for the next detection - evalue = os.environ.pop('AR') - # Must be the same type since it's a wrapper around the same exelist - self.assertIs(type(cc), type(wcc)) - self.assertIs(type(linker), type(wlinker)) - # Ensure that the exelist is correct - self.assertEqual(wcc.get_exelist(), wrappercc) - self.assertEqual(wlinker.get_exelist(), wrapperlinker) - # Ensure that the version detection worked correctly - self.assertEqual(cc.version, wcc.version) - if hasattr(cc, 'is_64'): - self.assertEqual(cc.is_64, wcc.is_64) - - def test_always_prefer_c_compiler_for_asm(self): - testdir = os.path.join(self.common_test_dir, '137 c cpp and asm') - # Skip if building with MSVC - env = get_fake_env(testdir, self.builddir, self.prefix) - if env.detect_c_compiler(MachineChoice.HOST).get_id() == 'msvc': - raise unittest.SkipTest('MSVC can\'t compile assembly') - self.init(testdir) - commands = {'c-asm': {}, 'cpp-asm': {}, 'cpp-c-asm': {}, 'c-cpp-asm': {}} - for cmd in self.get_compdb(): - # Get compiler - split = split_args(cmd['command']) - if split[0] == 'ccache': - compiler = split[1] - else: - compiler = split[0] - # Classify commands - if 'Ic-asm' in cmd['command']: - if cmd['file'].endswith('.S'): - commands['c-asm']['asm'] = compiler - elif cmd['file'].endswith('.c'): - commands['c-asm']['c'] = compiler - else: - raise AssertionError('{!r} found in cpp-asm?'.format(cmd['command'])) - elif 'Icpp-asm' in cmd['command']: - if cmd['file'].endswith('.S'): - commands['cpp-asm']['asm'] = compiler - elif cmd['file'].endswith('.cpp'): - commands['cpp-asm']['cpp'] = compiler - else: - raise AssertionError('{!r} found in cpp-asm?'.format(cmd['command'])) - elif 'Ic-cpp-asm' in cmd['command']: - if cmd['file'].endswith('.S'): - commands['c-cpp-asm']['asm'] = compiler - elif cmd['file'].endswith('.c'): - commands['c-cpp-asm']['c'] = compiler - elif cmd['file'].endswith('.cpp'): - commands['c-cpp-asm']['cpp'] = compiler - else: - raise AssertionError('{!r} found in c-cpp-asm?'.format(cmd['command'])) - elif 'Icpp-c-asm' in cmd['command']: - if cmd['file'].endswith('.S'): - commands['cpp-c-asm']['asm'] = compiler - elif cmd['file'].endswith('.c'): - commands['cpp-c-asm']['c'] = compiler - elif cmd['file'].endswith('.cpp'): - commands['cpp-c-asm']['cpp'] = compiler - else: - raise AssertionError('{!r} found in cpp-c-asm?'.format(cmd['command'])) - else: - raise AssertionError('Unknown command {!r} found'.format(cmd['command'])) - # Check that .S files are always built with the C compiler - self.assertEqual(commands['c-asm']['asm'], commands['c-asm']['c']) - self.assertEqual(commands['c-asm']['asm'], commands['cpp-asm']['asm']) - self.assertEqual(commands['cpp-asm']['asm'], commands['c-cpp-asm']['c']) - self.assertEqual(commands['c-cpp-asm']['asm'], commands['c-cpp-asm']['c']) - self.assertEqual(commands['cpp-c-asm']['asm'], commands['cpp-c-asm']['c']) - self.assertNotEqual(commands['cpp-asm']['asm'], commands['cpp-asm']['cpp']) - self.assertNotEqual(commands['c-cpp-asm']['c'], commands['c-cpp-asm']['cpp']) - self.assertNotEqual(commands['cpp-c-asm']['c'], commands['cpp-c-asm']['cpp']) - # Check that the c-asm target is always linked with the C linker - build_ninja = os.path.join(self.builddir, 'build.ninja') - with open(build_ninja, 'r', encoding='utf-8') as f: - contents = f.read() - m = re.search('build c-asm.*: c_LINKER', contents) - self.assertIsNotNone(m, msg=contents) - - def test_preprocessor_checks_CPPFLAGS(self): - ''' - Test that preprocessor compiler checks read CPPFLAGS and also CFLAGS but - not LDFLAGS. - ''' - testdir = os.path.join(self.common_test_dir, '136 get define') - define = 'MESON_TEST_DEFINE_VALUE' - # NOTE: this list can't have \n, ' or " - # \n is never substituted by the GNU pre-processor via a -D define - # ' and " confuse split_args() even when they are escaped - # % and # confuse the MSVC preprocessor - # !, ^, *, and < confuse lcc preprocessor - value = 'spaces and fun@$&()-=_+{}[]:;>?,./~`' - for env_var in ['CPPFLAGS', 'CFLAGS']: - env = {} - env[env_var] = '-D{}="{}"'.format(define, value) - env['LDFLAGS'] = '-DMESON_FAIL_VALUE=cflags-read'.format(define) - self.init(testdir, extra_args=['-D{}={}'.format(define, value)], override_envvars=env) - - def test_custom_target_exe_data_deterministic(self): - testdir = os.path.join(self.common_test_dir, '113 custom target capture') - self.init(testdir) - meson_exe_dat1 = glob(os.path.join(self.privatedir, 'meson_exe*.dat')) - self.wipe() - self.init(testdir) - meson_exe_dat2 = glob(os.path.join(self.privatedir, 'meson_exe*.dat')) - self.assertListEqual(meson_exe_dat1, meson_exe_dat2) - - def test_source_changes_cause_rebuild(self): - ''' - Test that changes to sources and headers cause rebuilds, but not - changes to unused files (as determined by the dependency file) in the - input files list. - ''' - testdir = os.path.join(self.common_test_dir, '20 header in file list') - self.init(testdir) - self.build() - # Immediately rebuilding should not do anything - self.assertBuildIsNoop() - # Changing mtime of header.h should rebuild everything - self.utime(os.path.join(testdir, 'header.h')) - self.assertRebuiltTarget('prog') - - def test_custom_target_changes_cause_rebuild(self): - ''' - Test that in a custom target, changes to the input files, the - ExternalProgram, and any File objects on the command-line cause - a rebuild. - ''' - testdir = os.path.join(self.common_test_dir, '60 custom header generator') - self.init(testdir) - self.build() - # Immediately rebuilding should not do anything - self.assertBuildIsNoop() - # Changing mtime of these should rebuild everything - for f in ('input.def', 'makeheader.py', 'somefile.txt'): - self.utime(os.path.join(testdir, f)) - self.assertRebuiltTarget('prog') - - def test_source_generator_program_cause_rebuild(self): - ''' - Test that changes to generator programs in the source tree cause - a rebuild. - ''' - testdir = os.path.join(self.common_test_dir, '94 gen extra') - self.init(testdir) - self.build() - # Immediately rebuilding should not do anything - self.assertBuildIsNoop() - # Changing mtime of generator should rebuild the executable - self.utime(os.path.join(testdir, 'srcgen.py')) - self.assertRebuiltTarget('basic') - - def test_static_library_lto(self): - ''' - Test that static libraries can be built with LTO and linked to - executables. On Linux, this requires the use of gcc-ar. - https://github.com/mesonbuild/meson/issues/1646 - ''' - testdir = os.path.join(self.common_test_dir, '5 linkstatic') - - env = get_fake_env(testdir, self.builddir, self.prefix) - if env.detect_c_compiler(MachineChoice.HOST).get_id() == 'clang' and is_windows(): - raise unittest.SkipTest('LTO not (yet) supported by windows clang') - - self.init(testdir, extra_args='-Db_lto=true') - self.build() - self.run_tests() - - def test_dist_git(self): - if not shutil.which('git'): - raise unittest.SkipTest('Git not found') - if self.backend is not Backend.ninja: - raise unittest.SkipTest('Dist is only supported with Ninja') - - try: - self.dist_impl(_git_init) - except PermissionError: - # When run under Windows CI, something (virus scanner?) - # holds on to the git files so cleaning up the dir - # fails sometimes. - pass - - def test_dist_hg(self): - if not shutil.which('hg'): - raise unittest.SkipTest('Mercurial not found') - if self.backend is not Backend.ninja: - raise unittest.SkipTest('Dist is only supported with Ninja') - - def hg_init(project_dir): - subprocess.check_call(['hg', 'init'], cwd=project_dir) - with open(os.path.join(project_dir, '.hg', 'hgrc'), 'w') as f: - print('[ui]', file=f) - print('username=Author Person ', file=f) - subprocess.check_call(['hg', 'add', 'meson.build', 'distexe.c'], cwd=project_dir) - subprocess.check_call(['hg', 'commit', '-m', 'I am a project'], cwd=project_dir) - - try: - self.dist_impl(hg_init, include_subprojects=False) - except PermissionError: - # When run under Windows CI, something (virus scanner?) - # holds on to the hg files so cleaning up the dir - # fails sometimes. - pass - - def test_dist_git_script(self): - if not shutil.which('git'): - raise unittest.SkipTest('Git not found') - if self.backend is not Backend.ninja: - raise unittest.SkipTest('Dist is only supported with Ninja') - - try: - with tempfile.TemporaryDirectory() as tmpdir: - project_dir = os.path.join(tmpdir, 'a') - shutil.copytree(os.path.join(self.unit_test_dir, '35 dist script'), - project_dir) - _git_init(project_dir) - self.init(project_dir) - self.build('dist') - except PermissionError: - # When run under Windows CI, something (virus scanner?) - # holds on to the git files so cleaning up the dir - # fails sometimes. - pass - - def create_dummy_subproject(self, project_dir, name): - path = os.path.join(project_dir, 'subprojects', name) - os.makedirs(path) - with open(os.path.join(path, 'meson.build'), 'w') as ofile: - ofile.write("project('{}')".format(name)) - return path - - def dist_impl(self, vcs_init, include_subprojects=True): - # Create this on the fly because having rogue .git directories inside - # the source tree leads to all kinds of trouble. - with tempfile.TemporaryDirectory() as project_dir: - with open(os.path.join(project_dir, 'meson.build'), 'w') as ofile: - ofile.write('''project('disttest', 'c', version : '1.4.3') -e = executable('distexe', 'distexe.c') -test('dist test', e) -subproject('vcssub', required : false) -subproject('tarballsub', required : false) -''') - with open(os.path.join(project_dir, 'distexe.c'), 'w') as ofile: - ofile.write('''#include - -int main(int argc, char **argv) { - printf("I am a distribution test.\\n"); - return 0; -} -''') - xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz') - xz_checksumfile = xz_distfile + '.sha256sum' - zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip') - zip_checksumfile = zip_distfile + '.sha256sum' - vcs_init(project_dir) - if include_subprojects: - vcs_init(self.create_dummy_subproject(project_dir, 'vcssub')) - self.create_dummy_subproject(project_dir, 'tarballsub') - self.create_dummy_subproject(project_dir, 'unusedsub') - self.init(project_dir) - self.build('dist') - self.assertPathExists(xz_distfile) - self.assertPathExists(xz_checksumfile) - self.assertPathDoesNotExist(zip_distfile) - self.assertPathDoesNotExist(zip_checksumfile) - self._run(self.meson_command + ['dist', '--formats', 'zip'], - workdir=self.builddir) - self.assertPathExists(zip_distfile) - self.assertPathExists(zip_checksumfile) - - if include_subprojects: - z = zipfile.ZipFile(zip_distfile) - self.assertEqual(sorted(['disttest-1.4.3/', - 'disttest-1.4.3/meson.build', - 'disttest-1.4.3/distexe.c']), - sorted(z.namelist())) - - self._run(self.meson_command + ['dist', '--formats', 'zip', '--include-subprojects'], - workdir=self.builddir) - z = zipfile.ZipFile(zip_distfile) - self.assertEqual(sorted(['disttest-1.4.3/', - 'disttest-1.4.3/subprojects/', - 'disttest-1.4.3/meson.build', - 'disttest-1.4.3/distexe.c', - 'disttest-1.4.3/subprojects/tarballsub/', - 'disttest-1.4.3/subprojects/vcssub/', - 'disttest-1.4.3/subprojects/tarballsub/meson.build', - 'disttest-1.4.3/subprojects/vcssub/meson.build']), - sorted(z.namelist())) - - def test_rpath_uses_ORIGIN(self): - ''' - Test that built targets use $ORIGIN in rpath, which ensures that they - are relocatable and ensures that builds are reproducible since the - build directory won't get embedded into the built binaries. - ''' - if is_windows() or is_cygwin(): - raise unittest.SkipTest('Windows PE/COFF binaries do not use RPATH') - testdir = os.path.join(self.common_test_dir, '42 library chain') - self.init(testdir) - self.build() - for each in ('prog', 'subdir/liblib1.so', ): - rpath = get_rpath(os.path.join(self.builddir, each)) - self.assertTrue(rpath, 'Rpath could not be determined for {}.'.format(each)) - if is_dragonflybsd(): - # DragonflyBSD will prepend /usr/lib/gccVERSION to the rpath, - # so ignore that. - self.assertTrue(rpath.startswith('/usr/lib/gcc')) - rpaths = rpath.split(':')[1:] - else: - rpaths = rpath.split(':') - for path in rpaths: - self.assertTrue(path.startswith('$ORIGIN'), msg=(each, path)) - # These two don't link to anything else, so they do not need an rpath entry. - for each in ('subdir/subdir2/liblib2.so', 'subdir/subdir3/liblib3.so'): - rpath = get_rpath(os.path.join(self.builddir, each)) - if is_dragonflybsd(): - # The rpath should be equal to /usr/lib/gccVERSION - self.assertTrue(rpath.startswith('/usr/lib/gcc')) - self.assertEqual(len(rpath.split(':')), 1) - else: - self.assertTrue(rpath is None) - - def test_dash_d_dedup(self): - testdir = os.path.join(self.unit_test_dir, '9 d dedup') - self.init(testdir) - cmd = self.get_compdb()[0]['command'] - self.assertTrue('-D FOO -D BAR' in cmd or - '"-D" "FOO" "-D" "BAR"' in cmd or - '/D FOO /D BAR' in cmd or - '"/D" "FOO" "/D" "BAR"' in cmd) - - def test_all_forbidden_targets_tested(self): - ''' - Test that all forbidden targets are tested in the '154 reserved targets' - test. Needs to be a unit test because it accesses Meson internals. - ''' - testdir = os.path.join(self.common_test_dir, '154 reserved targets') - targets = mesonbuild.coredata.forbidden_target_names - # We don't actually define a target with this name - targets.pop('build.ninja') - # Remove this to avoid multiple entries with the same name - # but different case. - targets.pop('PHONY') - for i in targets: - self.assertPathExists(os.path.join(testdir, i)) - - def detect_prebuild_env(self): - env = get_fake_env() - cc = env.detect_c_compiler(MachineChoice.HOST) - stlinker = env.detect_static_linker(cc) - if mesonbuild.mesonlib.is_windows(): - object_suffix = 'obj' - shared_suffix = 'dll' - elif mesonbuild.mesonlib.is_cygwin(): - object_suffix = 'o' - shared_suffix = 'dll' - elif mesonbuild.mesonlib.is_osx(): - object_suffix = 'o' - shared_suffix = 'dylib' - else: - object_suffix = 'o' - shared_suffix = 'so' - return (cc, stlinker, object_suffix, shared_suffix) - - def pbcompile(self, compiler, source, objectfile, extra_args=None): - cmd = compiler.get_exelist() - extra_args = extra_args or [] - if compiler.get_argument_syntax() == 'msvc': - cmd += ['/nologo', '/Fo' + objectfile, '/c', source] + extra_args - else: - cmd += ['-c', source, '-o', objectfile] + extra_args - subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - - def test_prebuilt_object(self): - (compiler, _, object_suffix, _) = self.detect_prebuild_env() - tdir = os.path.join(self.unit_test_dir, '15 prebuilt object') - source = os.path.join(tdir, 'source.c') - objectfile = os.path.join(tdir, 'prebuilt.' + object_suffix) - self.pbcompile(compiler, source, objectfile) - try: - self.init(tdir) - self.build() - self.run_tests() - finally: - os.unlink(objectfile) - - def build_static_lib(self, compiler, linker, source, objectfile, outfile, extra_args=None): - if extra_args is None: - extra_args = [] - if compiler.get_argument_syntax() == 'msvc': - link_cmd = ['lib', '/NOLOGO', '/OUT:' + outfile, objectfile] - else: - link_cmd = ['ar', 'csr', outfile, objectfile] - link_cmd = linker.get_exelist() - link_cmd += linker.get_always_args() - link_cmd += linker.get_std_link_args() - link_cmd += linker.get_output_args(outfile) - link_cmd += [objectfile] - self.pbcompile(compiler, source, objectfile, extra_args=extra_args) - try: - subprocess.check_call(link_cmd) - finally: - os.unlink(objectfile) - - def test_prebuilt_static_lib(self): - (cc, stlinker, object_suffix, _) = self.detect_prebuild_env() - tdir = os.path.join(self.unit_test_dir, '16 prebuilt static') - source = os.path.join(tdir, 'libdir/best.c') - objectfile = os.path.join(tdir, 'libdir/best.' + object_suffix) - stlibfile = os.path.join(tdir, 'libdir/libbest.a') - self.build_static_lib(cc, stlinker, source, objectfile, stlibfile) - # Run the test - try: - self.init(tdir) - self.build() - self.run_tests() - finally: - os.unlink(stlibfile) - - def build_shared_lib(self, compiler, source, objectfile, outfile, impfile, extra_args=None): - if extra_args is None: - extra_args = [] - if compiler.get_argument_syntax() == 'msvc': - link_cmd = compiler.get_linker_exelist() + [ - '/NOLOGO', '/DLL', '/DEBUG', '/IMPLIB:' + impfile, - '/OUT:' + outfile, objectfile] - else: - if not (compiler.info.is_windows() or compiler.info.is_cygwin() or compiler.info.is_darwin()): - extra_args += ['-fPIC'] - link_cmd = compiler.get_exelist() + ['-shared', '-o', outfile, objectfile] - if not mesonbuild.mesonlib.is_osx(): - link_cmd += ['-Wl,-soname=' + os.path.basename(outfile)] - self.pbcompile(compiler, source, objectfile, extra_args=extra_args) - try: - subprocess.check_call(link_cmd) - finally: - os.unlink(objectfile) - - def test_prebuilt_shared_lib(self): - (cc, _, object_suffix, shared_suffix) = self.detect_prebuild_env() - tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') - source = os.path.join(tdir, 'alexandria.c') - objectfile = os.path.join(tdir, 'alexandria.' + object_suffix) - impfile = os.path.join(tdir, 'alexandria.lib') - if cc.get_argument_syntax() == 'msvc': - shlibfile = os.path.join(tdir, 'alexandria.' + shared_suffix) - elif is_cygwin(): - shlibfile = os.path.join(tdir, 'cygalexandria.' + shared_suffix) - else: - shlibfile = os.path.join(tdir, 'libalexandria.' + shared_suffix) - self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) - # Run the test - try: - self.init(tdir) - self.build() - self.run_tests() - finally: - os.unlink(shlibfile) - if mesonbuild.mesonlib.is_windows(): - # Clean up all the garbage MSVC writes in the - # source tree. - for fname in glob(os.path.join(tdir, 'alexandria.*')): - if os.path.splitext(fname)[1] not in ['.c', '.h']: - os.unlink(fname) - - @skipIfNoPkgconfig - def test_pkgconfig_static(self): - ''' - Test that the we prefer static libraries when `static: true` is - passed to dependency() with pkg-config. Can't be an ordinary test - because we need to build libs and try to find them from meson.build - - Also test that it's not a hard error to have unsatisfiable library deps - since system libraries -lm will never be found statically. - https://github.com/mesonbuild/meson/issues/2785 - ''' - (cc, stlinker, objext, shext) = self.detect_prebuild_env() - testdir = os.path.join(self.unit_test_dir, '18 pkgconfig static') - source = os.path.join(testdir, 'foo.c') - objectfile = os.path.join(testdir, 'foo.' + objext) - stlibfile = os.path.join(testdir, 'libfoo.a') - impfile = os.path.join(testdir, 'foo.lib') - if cc.get_argument_syntax() == 'msvc': - shlibfile = os.path.join(testdir, 'foo.' + shext) - elif is_cygwin(): - shlibfile = os.path.join(testdir, 'cygfoo.' + shext) - else: - shlibfile = os.path.join(testdir, 'libfoo.' + shext) - # Build libs - self.build_static_lib(cc, stlinker, source, objectfile, stlibfile, extra_args=['-DFOO_STATIC']) - self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) - # Run test - try: - self.init(testdir, override_envvars={'PKG_CONFIG_LIBDIR': self.builddir}) - self.build() - self.run_tests() - finally: - os.unlink(stlibfile) - os.unlink(shlibfile) - if mesonbuild.mesonlib.is_windows(): - # Clean up all the garbage MSVC writes in the - # source tree. - for fname in glob(os.path.join(testdir, 'foo.*')): - if os.path.splitext(fname)[1] not in ['.c', '.h', '.in']: - os.unlink(fname) - - @skipIfNoPkgconfig - def test_pkgconfig_gen_escaping(self): - testdir = os.path.join(self.common_test_dir, '47 pkgconfig-gen') - prefix = '/usr/with spaces' - libdir = 'lib' - self.init(testdir, extra_args=['--prefix=' + prefix, - '--libdir=' + libdir]) - # Find foo dependency - 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) - # Ensure link_args are properly quoted - libdir = PurePath(prefix) / PurePath(libdir) - link_args = ['-L' + libdir.as_posix(), '-lfoo'] - self.assertEqual(foo_dep.get_link_args(), link_args) - # Ensure include args are properly quoted - incdir = PurePath(prefix) / PurePath('include') - cargs = ['-I' + incdir.as_posix()] - self.assertEqual(foo_dep.get_compile_args(), cargs) - - def test_array_option_change(self): - def get_opt(): - opts = self.introspect('--buildoptions') - for x in opts: - if x.get('name') == 'list': - return x - raise Exception(opts) - - expected = { - 'name': 'list', - 'description': 'list', - 'section': 'user', - 'type': 'array', - 'value': ['foo', 'bar'], - 'machine': 'any', - } - tdir = os.path.join(self.unit_test_dir, '19 array option') - self.init(tdir) - original = get_opt() - self.assertDictEqual(original, expected) - - expected['value'] = ['oink', 'boink'] - self.setconf('-Dlist=oink,boink') - changed = get_opt() - self.assertEqual(changed, expected) - - def test_array_option_bad_change(self): - def get_opt(): - opts = self.introspect('--buildoptions') - for x in opts: - if x.get('name') == 'list': - return x - raise Exception(opts) - - expected = { - 'name': 'list', - 'description': 'list', - 'section': 'user', - 'type': 'array', - 'value': ['foo', 'bar'], - 'machine': 'any', - } - tdir = os.path.join(self.unit_test_dir, '19 array option') - self.init(tdir) - original = get_opt() - self.assertDictEqual(original, expected) - with self.assertRaises(subprocess.CalledProcessError): - self.setconf('-Dlist=bad') - changed = get_opt() - self.assertDictEqual(changed, expected) - - def test_array_option_empty_equivalents(self): - """Array options treat -Dopt=[] and -Dopt= as equivalent.""" - def get_opt(): - opts = self.introspect('--buildoptions') - for x in opts: - if x.get('name') == 'list': - return x - raise Exception(opts) - - expected = { - 'name': 'list', - 'description': 'list', - 'section': 'user', - 'type': 'array', - 'value': [], - 'machine': 'any', - } - tdir = os.path.join(self.unit_test_dir, '19 array option') - self.init(tdir, extra_args='-Dlist=') - original = get_opt() - self.assertDictEqual(original, expected) - - def opt_has(self, name, value): - res = self.introspect('--buildoptions') - found = False - for i in res: - if i['name'] == name: - self.assertEqual(i['value'], value) - found = True - break - self.assertTrue(found, "Array option not found in introspect data.") - - def test_free_stringarray_setting(self): - testdir = os.path.join(self.common_test_dir, '43 options') - self.init(testdir) - self.opt_has('free_array_opt', []) - self.setconf('-Dfree_array_opt=foo,bar', will_build=False) - self.opt_has('free_array_opt', ['foo', 'bar']) - self.setconf("-Dfree_array_opt=['a,b', 'c,d']", will_build=False) - self.opt_has('free_array_opt', ['a,b', 'c,d']) - - def test_subproject_promotion(self): - testdir = os.path.join(self.unit_test_dir, '12 promote') - workdir = os.path.join(self.builddir, 'work') - shutil.copytree(testdir, workdir) - spdir = os.path.join(workdir, 'subprojects') - s3dir = os.path.join(spdir, 's3') - scommondir = os.path.join(spdir, 'scommon') - self.assertFalse(os.path.isdir(s3dir)) - subprocess.check_call(self.wrap_command + ['promote', 's3'], cwd=workdir) - self.assertTrue(os.path.isdir(s3dir)) - self.assertFalse(os.path.isdir(scommondir)) - self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'scommon'], - cwd=workdir, - stdout=subprocess.DEVNULL), 0) - self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'invalid/path/to/scommon'], - cwd=workdir, - stderr=subprocess.DEVNULL), 0) - self.assertFalse(os.path.isdir(scommondir)) - subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/scommon'], cwd=workdir) - self.assertTrue(os.path.isdir(scommondir)) - promoted_wrap = os.path.join(spdir, 'athing.wrap') - self.assertFalse(os.path.isfile(promoted_wrap)) - subprocess.check_call(self.wrap_command + ['promote', 'athing'], cwd=workdir) - self.assertTrue(os.path.isfile(promoted_wrap)) - self.init(workdir) - self.build() - - def test_subproject_promotion_wrap(self): - testdir = os.path.join(self.unit_test_dir, '44 promote wrap') - workdir = os.path.join(self.builddir, 'work') - shutil.copytree(testdir, workdir) - spdir = os.path.join(workdir, 'subprojects') - - ambiguous_wrap = os.path.join(spdir, 'ambiguous.wrap') - self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'ambiguous'], - cwd=workdir, - stdout=subprocess.DEVNULL), 0) - self.assertFalse(os.path.isfile(ambiguous_wrap)) - subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/ambiguous.wrap'], cwd=workdir) - self.assertTrue(os.path.isfile(ambiguous_wrap)) - - def test_warning_location(self): - tdir = os.path.join(self.unit_test_dir, '22 warning location') - out = self.init(tdir) - for expected in [ - r'meson.build:4: WARNING: Keyword argument "link_with" defined multiple times.', - r'sub' + os.path.sep + r'meson.build:3: WARNING: Keyword argument "link_with" defined multiple times.', - r'meson.build:6: WARNING: a warning of some sort', - r'sub' + os.path.sep + r'meson.build:4: WARNING: subdir warning', - r'meson.build:7: WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases.', - r"meson.build:11: WARNING: The variable(s) 'MISSING' in the input file 'conf.in' are not present in the given configuration data.", - r'meson.build:1: WARNING: Passed invalid keyword argument "invalid".', - ]: - self.assertRegex(out, re.escape(expected)) - - def test_permitted_method_kwargs(self): - tdir = os.path.join(self.unit_test_dir, '25 non-permitted kwargs') - out = self.init(tdir) - for expected in [ - r'WARNING: Passed invalid keyword argument "prefixxx".', - r'WARNING: Passed invalid keyword argument "argsxx".', - r'WARNING: Passed invalid keyword argument "invalidxx".', - ]: - self.assertRegex(out, re.escape(expected)) - - def test_templates(self): - ninja = detect_ninja() - if ninja is None: - raise unittest.SkipTest('This test currently requires ninja. Fix this once "meson build" works.') - langs = ['c'] - env = get_fake_env() - try: - env.detect_cpp_compiler(MachineChoice.HOST) - langs.append('cpp') - except EnvironmentException: - pass - try: - env.detect_d_compiler(MachineChoice.HOST) - langs.append('d') - except EnvironmentException: - pass - try: - env.detect_fortran_compiler(MachineChoice.HOST) - if is_windows() or platform.machine().lower() != 'e2k': - # Elbrus Fortran compiler can't generate debug information - langs.append('fortran') - except EnvironmentException: - pass - try: - env.detect_objc_compiler(MachineChoice.HOST) - langs.append('objc') - except EnvironmentException: - pass - # FIXME: omitting rust as Windows AppVeyor CI finds Rust but doesn't link correctly - - for lang in langs: - for target_type in ('executable', 'library'): - # test empty directory - with tempfile.TemporaryDirectory() as tmpdir: - self._run(self.meson_command + ['init', '--language', lang, '--type', target_type], - workdir=tmpdir) - self._run(self.setup_command + ['--backend=ninja', 'builddir'], - workdir=tmpdir) - self._run(ninja, - workdir=os.path.join(tmpdir, 'builddir')) - # test directory with existing code file - if lang in ('c', 'cpp'): - with tempfile.TemporaryDirectory() as tmpdir: - with open(os.path.join(tmpdir, 'foo.' + lang), 'w') as f: - f.write('int main(void) {}') - self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) - - # The test uses mocking and thus requires that - # the current process is the one to run the Meson steps. - # If we are using an external test executable (most commonly - # in Debian autopkgtests) then the mocking won't work. - @unittest.skipIf('MESON_EXE' in os.environ, 'MESON_EXE is defined, can not use mocking.') - def test_cross_file_system_paths(self): - if is_windows(): - raise unittest.SkipTest('system crossfile paths not defined for Windows (yet)') - if is_sunos(): - cc = 'gcc' - else: - cc = 'cc' - - testdir = os.path.join(self.common_test_dir, '1 trivial') - cross_content = textwrap.dedent("""\ - [binaries] - c = '/usr/bin/{}' - ar = '/usr/bin/ar' - strip = '/usr/bin/ar' - - [properties] - - [host_machine] - system = 'linux' - cpu_family = 'x86' - cpu = 'i686' - endian = 'little' - """.format(cc)) - - with tempfile.TemporaryDirectory() as d: - dir_ = os.path.join(d, 'meson', 'cross') - os.makedirs(dir_) - with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f: - f.write(cross_content) - name = os.path.basename(f.name) - - with mock.patch.dict(os.environ, {'XDG_DATA_HOME': d}): - self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) - self.wipe() - - with mock.patch.dict(os.environ, {'XDG_DATA_DIRS': d}): - os.environ.pop('XDG_DATA_HOME', None) - self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) - self.wipe() - - with tempfile.TemporaryDirectory() as d: - dir_ = os.path.join(d, '.local', 'share', 'meson', 'cross') - os.makedirs(dir_) - with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f: - f.write(cross_content) - name = os.path.basename(f.name) - - # If XDG_DATA_HOME is set in the environment running the - # tests this test will fail, os mock the environment, pop - # it, then test - with mock.patch.dict(os.environ): - os.environ.pop('XDG_DATA_HOME', None) - with mock.patch('mesonbuild.coredata.os.path.expanduser', lambda x: x.replace('~', d)): - self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) - self.wipe() - - def test_compiler_run_command(self): - ''' - The test checks that the compiler object can be passed to - run_command(). - ''' - testdir = os.path.join(self.unit_test_dir, '24 compiler run_command') - self.init(testdir) - - def test_identical_target_name_in_subproject_flat_layout(self): - ''' - Test that identical targets in different subprojects do not collide - if layout is flat. - ''' - testdir = os.path.join(self.common_test_dir, '177 identical target name in subproject flat layout') - self.init(testdir, extra_args=['--layout=flat']) - self.build() - - def test_identical_target_name_in_subdir_flat_layout(self): - ''' - Test that identical targets in different subdirs do not collide - if layout is flat. - ''' - testdir = os.path.join(self.common_test_dir, '186 same target name flat layout') - self.init(testdir, extra_args=['--layout=flat']) - self.build() - - def test_flock(self): - exception_raised = False - with tempfile.TemporaryDirectory() as tdir: - os.mkdir(os.path.join(tdir, 'meson-private')) - with BuildDirLock(tdir): - try: - with BuildDirLock(tdir): - pass - except MesonException: - exception_raised = True - self.assertTrue(exception_raised, 'Double locking did not raise exception.') - - @unittest.skipIf(is_osx(), 'Test not applicable to OSX') - def test_check_module_linking(self): - """ - Test that link_with: a shared module issues a warning - https://github.com/mesonbuild/meson/issues/2865 - (That an error is raised on OSX is exercised by test failing/78) - """ - tdir = os.path.join(self.unit_test_dir, '30 shared_mod linking') - out = self.init(tdir) - msg = ('''WARNING: target links against shared modules. This is not -recommended as it is not supported on some platforms''') - self.assertIn(msg, out) - - def test_ndebug_if_release_disabled(self): - testdir = os.path.join(self.unit_test_dir, '28 ndebug if-release') - self.init(testdir, extra_args=['--buildtype=release', '-Db_ndebug=if-release']) - self.build() - exe = os.path.join(self.builddir, 'main') - self.assertEqual(b'NDEBUG=1', subprocess.check_output(exe).strip()) - - def test_ndebug_if_release_enabled(self): - testdir = os.path.join(self.unit_test_dir, '28 ndebug if-release') - self.init(testdir, extra_args=['--buildtype=debugoptimized', '-Db_ndebug=if-release']) - self.build() - exe = os.path.join(self.builddir, 'main') - self.assertEqual(b'NDEBUG=0', subprocess.check_output(exe).strip()) - - def test_guessed_linker_dependencies(self): - ''' - Test that meson adds dependencies for libraries based on the final - linker command line. - ''' - testdirbase = os.path.join(self.unit_test_dir, '29 guessed linker dependencies') - testdirlib = os.path.join(testdirbase, 'lib') - - extra_args = None - libdir_flags = ['-L'] - env = get_fake_env(testdirlib, self.builddir, self.prefix) - if env.detect_c_compiler(MachineChoice.HOST).get_id() in {'msvc', 'clang-cl', 'intel-cl'}: - # msvc-like compiler, also test it with msvc-specific flags - libdir_flags += ['/LIBPATH:', '-LIBPATH:'] - else: - # static libraries are not linkable with -l with msvc because meson installs them - # as .a files which unix_args_to_native will not know as it expects libraries to use - # .lib as extension. For a DLL the import library is installed as .lib. Thus for msvc - # this tests needs to use shared libraries to test the path resolving logic in the - # dependency generation code path. - extra_args = ['--default-library', 'static'] - - initial_builddir = self.builddir - initial_installdir = self.installdir - - for libdir_flag in libdir_flags: - # build library - self.new_builddir() - self.init(testdirlib, extra_args=extra_args) - self.build() - self.install() - libbuilddir = self.builddir - installdir = self.installdir - libdir = os.path.join(self.installdir, self.prefix.lstrip('/').lstrip('\\'), 'lib') - - # build user of library - self.new_builddir() - # replace is needed because meson mangles platform paths passed via LDFLAGS - self.init(os.path.join(testdirbase, 'exe'), - override_envvars={"LDFLAGS": '{}{}'.format(libdir_flag, libdir.replace('\\', '/'))}) - self.build() - self.assertBuildIsNoop() - - # rebuild library - exebuilddir = self.builddir - self.installdir = installdir - self.builddir = libbuilddir - # Microsoft's compiler is quite smart about touching import libs on changes, - # so ensure that there is actually a change in symbols. - self.setconf('-Dmore_exports=true') - self.build() - self.install() - # no ensure_backend_detects_changes needed because self.setconf did that already - - # assert user of library will be rebuild - self.builddir = exebuilddir - self.assertRebuiltTarget('app') - - # restore dirs for the next test case - self.installdir = initial_builddir - self.builddir = initial_installdir - - def test_conflicting_d_dash_option(self): - testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') - with self.assertRaises(subprocess.CalledProcessError) as e: - self.init(testdir, extra_args=['-Dbindir=foo', '--bindir=bar']) - # Just to ensure that we caught the correct error - self.assertIn('passed as both', e.stderr) - - def _test_same_option_twice(self, arg, args): - testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') - self.init(testdir, extra_args=args) - opts = self.introspect('--buildoptions') - for item in opts: - if item['name'] == arg: - self.assertEqual(item['value'], 'bar') - return - raise Exception('Missing {} value?'.format(arg)) - - def test_same_dash_option_twice(self): - self._test_same_option_twice('bindir', ['--bindir=foo', '--bindir=bar']) - - def test_same_d_option_twice(self): - self._test_same_option_twice('bindir', ['-Dbindir=foo', '-Dbindir=bar']) - - def test_same_project_d_option_twice(self): - self._test_same_option_twice('one', ['-Done=foo', '-Done=bar']) - - def _test_same_option_twice_configure(self, arg, args): - testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') - self.init(testdir) - self.setconf(args) - opts = self.introspect('--buildoptions') - for item in opts: - if item['name'] == arg: - self.assertEqual(item['value'], 'bar') - return - raise Exception('Missing {} value?'.format(arg)) - - def test_same_dash_option_twice_configure(self): - self._test_same_option_twice_configure( - 'bindir', ['--bindir=foo', '--bindir=bar']) - - def test_same_d_option_twice_configure(self): - self._test_same_option_twice_configure( - 'bindir', ['-Dbindir=foo', '-Dbindir=bar']) - - def test_same_project_d_option_twice_configure(self): - self._test_same_option_twice_configure( - 'one', ['-Done=foo', '-Done=bar']) - - def test_command_line(self): - testdir = os.path.join(self.unit_test_dir, '34 command line') - - # Verify default values when passing no args - self.init(testdir) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['default_library'].value, 'static') - self.assertEqual(obj.builtins['warning_level'].value, '1') - self.assertEqual(obj.user_options['set_sub_opt'].value, True) - self.assertEqual(obj.user_options['subp:subp_opt'].value, 'default3') - self.wipe() - - # warning_level is special, it's --warnlevel instead of --warning-level - # for historical reasons - self.init(testdir, extra_args=['--warnlevel=2']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '2') - self.setconf('--warnlevel=3') - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '3') - self.wipe() - - # But when using -D syntax, it should be 'warning_level' - self.init(testdir, extra_args=['-Dwarning_level=2']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '2') - self.setconf('-Dwarning_level=3') - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '3') - self.wipe() - - # Mixing --option and -Doption is forbidden - with self.assertRaises(subprocess.CalledProcessError) as cm: - self.init(testdir, extra_args=['--warnlevel=1', '-Dwarning_level=3']) - self.assertNotEqual(0, cm.exception.returncode) - self.assertIn('as both', cm.exception.output) - self.init(testdir) - with self.assertRaises(subprocess.CalledProcessError) as cm: - self.setconf(['--warnlevel=1', '-Dwarning_level=3']) - self.assertNotEqual(0, cm.exception.returncode) - self.assertIn('as both', cm.exception.output) - self.wipe() - - # --default-library should override default value from project() - self.init(testdir, extra_args=['--default-library=both']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['default_library'].value, 'both') - self.setconf('--default-library=shared') - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['default_library'].value, 'shared') - if self.backend is Backend.ninja: - # reconfigure target works only with ninja backend - self.build('reconfigure') - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['default_library'].value, 'shared') - self.wipe() - - # Should warn on unknown options - out = self.init(testdir, extra_args=['-Dbad=1', '-Dfoo=2', '-Dwrong_link_args=foo']) - self.assertIn('Unknown options: "bad, foo, wrong_link_args"', out) - self.wipe() - - # Should fail on malformed option - with self.assertRaises(subprocess.CalledProcessError) as cm: - self.init(testdir, extra_args=['-Dfoo']) - self.assertNotEqual(0, cm.exception.returncode) - self.assertIn('Option \'foo\' must have a value separated by equals sign.', cm.exception.output) - self.init(testdir) - with self.assertRaises(subprocess.CalledProcessError) as cm: - self.setconf('-Dfoo') - self.assertNotEqual(0, cm.exception.returncode) - self.assertIn('Option \'foo\' must have a value separated by equals sign.', cm.exception.output) - self.wipe() - - # It is not an error to set wrong option for unknown subprojects or - # language because we don't have control on which one will be selected. - self.init(testdir, extra_args=['-Dc_wrong=1', '-Dwrong:bad=1', '-Db_wrong=1']) - self.wipe() - - # Test we can set subproject option - self.init(testdir, extra_args=['-Dsubp:subp_opt=foo']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.user_options['subp:subp_opt'].value, 'foo') - self.wipe() - - # c_args value should be parsed with split_args - self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.compiler_options.host['c_args'].value, ['-Dfoo', '-Dbar', '-Dthird=one two']) - - self.setconf('-Dc_args="foo bar" one two') - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.compiler_options.host['c_args'].value, ['foo bar', 'one', 'two']) - self.wipe() - - self.init(testdir, extra_args=['-Dset_percent_opt=myoption%']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.user_options['set_percent_opt'].value, 'myoption%') - self.wipe() - - # Setting a 2nd time the same option should override the first value - try: - self.init(testdir, extra_args=['--bindir=foo', '--bindir=bar', - '-Dbuildtype=plain', '-Dbuildtype=release', - '-Db_sanitize=address', '-Db_sanitize=thread', - '-Dc_args=-Dfoo', '-Dc_args=-Dbar']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['bindir'].value, 'bar') - self.assertEqual(obj.builtins['buildtype'].value, 'release') - self.assertEqual(obj.base_options['b_sanitize'].value, 'thread') - self.assertEqual(obj.compiler_options.host['c_args'].value, ['-Dbar']) - self.setconf(['--bindir=bar', '--bindir=foo', - '-Dbuildtype=release', '-Dbuildtype=plain', - '-Db_sanitize=thread', '-Db_sanitize=address', - '-Dc_args=-Dbar', '-Dc_args=-Dfoo']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['bindir'].value, 'foo') - self.assertEqual(obj.builtins['buildtype'].value, 'plain') - self.assertEqual(obj.base_options['b_sanitize'].value, 'address') - self.assertEqual(obj.compiler_options.host['c_args'].value, ['-Dfoo']) - self.wipe() - except KeyError: - # Ignore KeyError, it happens on CI for compilers that does not - # support b_sanitize. We have to test with a base option because - # they used to fail this test with Meson 0.46 an earlier versions. - pass - - def test_warning_level_0(self): - testdir = os.path.join(self.common_test_dir, '214 warning level 0') - - # Verify default values when passing no args - self.init(testdir) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '0') - self.wipe() - - # verify we can override w/ --warnlevel - self.init(testdir, extra_args=['--warnlevel=1']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '1') - self.setconf('--warnlevel=0') - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '0') - self.wipe() - - # verify we can override w/ -Dwarning_level - self.init(testdir, extra_args=['-Dwarning_level=1']) - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '1') - self.setconf('-Dwarning_level=0') - obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.builtins['warning_level'].value, '0') - self.wipe() - - def test_feature_check_usage_subprojects(self): - testdir = os.path.join(self.unit_test_dir, '41 featurenew subprojects') - out = self.init(testdir) - # Parent project warns correctly - self.assertRegex(out, "WARNING: Project targeting '>=0.45'.*'0.47.0': dict") - # Subprojects warn correctly - self.assertRegex(out, r"\|WARNING: Project targeting '>=0.40'.*'0.44.0': disabler") - self.assertRegex(out, r"\|WARNING: Project targeting '!=0.40'.*'0.44.0': disabler") - # Subproject has a new-enough meson_version, no warning - self.assertNotRegex(out, "WARNING: Project targeting.*Python") - # Ensure a summary is printed in the subproject and the outer project - self.assertRegex(out, r"\|WARNING: Project specifies a minimum meson_version '>=0.40'") - self.assertRegex(out, r"\| \* 0.44.0: {'disabler'}") - self.assertRegex(out, "WARNING: Project specifies a minimum meson_version '>=0.45'") - self.assertRegex(out, " * 0.47.0: {'dict'}") - - def test_configure_file_warnings(self): - testdir = os.path.join(self.common_test_dir, "14 configure file") - out = self.init(testdir) - self.assertRegex(out, "WARNING:.*'empty'.*config.h.in.*not present.*") - self.assertRegex(out, "WARNING:.*'FOO_BAR'.*nosubst-nocopy2.txt.in.*not present.*") - self.assertRegex(out, "WARNING:.*'empty'.*config.h.in.*not present.*") - self.assertRegex(out, "WARNING:.*empty configuration_data.*test.py.in") - # Warnings for configuration files that are overwritten. - self.assertRegex(out, "WARNING:.*\"double_output.txt\".*overwrites") - self.assertRegex(out, "WARNING:.*\"subdir.double_output2.txt\".*overwrites") - self.assertNotRegex(out, "WARNING:.*no_write_conflict.txt.*overwrites") - self.assertNotRegex(out, "WARNING:.*@BASENAME@.*overwrites") - self.assertRegex(out, "WARNING:.*\"sameafterbasename\".*overwrites") - # No warnings about empty configuration data objects passed to files with substitutions - self.assertNotRegex(out, "WARNING:.*empty configuration_data.*nosubst-nocopy1.txt.in") - self.assertNotRegex(out, "WARNING:.*empty configuration_data.*nosubst-nocopy2.txt.in") - with open(os.path.join(self.builddir, 'nosubst-nocopy1.txt'), 'rb') as f: - 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: - with tempfile.TemporaryDirectory(dir=containing) as srcdir: - mfile = os.path.join(srcdir, 'meson.build') - of = open(mfile, 'w') - of.write("project('foobar', 'c')\n") - of.close() - pc = subprocess.run(self.setup_command, - cwd=srcdir, - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) - self.assertIn(b'Must specify at least one directory name', pc.stdout) - with tempfile.TemporaryDirectory(dir=srcdir) as builddir: - subprocess.run(self.setup_command, - check=True, - cwd=builddir, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) - - def get_opts_as_dict(self): - result = {} - for i in self.introspect('--buildoptions'): - result[i['name']] = i['value'] - return result - - def test_buildtype_setting(self): - testdir = os.path.join(self.common_test_dir, '1 trivial') - self.init(testdir) - opts = self.get_opts_as_dict() - self.assertEqual(opts['buildtype'], 'debug') - self.assertEqual(opts['debug'], True) - self.setconf('-Ddebug=false') - opts = self.get_opts_as_dict() - self.assertEqual(opts['debug'], False) - self.assertEqual(opts['buildtype'], 'plain') - self.assertEqual(opts['optimization'], '0') - - # Setting optimizations to 3 should cause buildtype - # to go to release mode. - self.setconf('-Doptimization=3') - opts = self.get_opts_as_dict() - self.assertEqual(opts['buildtype'], 'release') - self.assertEqual(opts['debug'], False) - self.assertEqual(opts['optimization'], '3') - - # Going to debug build type should reset debugging - # and optimization - self.setconf('-Dbuildtype=debug') - opts = self.get_opts_as_dict() - self.assertEqual(opts['buildtype'], 'debug') - self.assertEqual(opts['debug'], True) - self.assertEqual(opts['optimization'], '0') - - @skipIfNoPkgconfig - @unittest.skipIf(is_windows(), 'Help needed with fixing this test on windows') - def test_native_dep_pkgconfig(self): - testdir = os.path.join(self.unit_test_dir, - '46 native dep pkgconfig var') - with tempfile.NamedTemporaryFile(mode='w', delete=False) as crossfile: - crossfile.write(textwrap.dedent( - '''[binaries] - pkgconfig = r'{0}' - - [properties] - - [host_machine] - system = 'linux' - cpu_family = 'arm' - cpu = 'armv7' - endian = 'little' - '''.format(os.path.join(testdir, 'cross_pkgconfig.py')))) - crossfile.flush() - self.meson_cross_file = crossfile.name - - env = {'PKG_CONFIG_LIBDIR': os.path.join(testdir, - 'native_pkgconfig')} - self.init(testdir, extra_args=['-Dstart_native=false'], override_envvars=env) - self.wipe() - self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env) - - def __reconfigure(self, change_minor=False): - # Set an older version to force a reconfigure from scratch - filename = os.path.join(self.privatedir, 'coredata.dat') - with open(filename, 'rb') as f: - obj = pickle.load(f) - if change_minor: - v = mesonbuild.coredata.version.split('.') - obj.version = '.'.join(v[0:2] + [str(int(v[2]) + 1)]) - else: - obj.version = '0.47.0' - with open(filename, 'wb') as f: - pickle.dump(obj, f) - - def test_reconfigure(self): - testdir = os.path.join(self.unit_test_dir, '48 reconfigure') - self.init(testdir, extra_args=['-Dopt1=val1']) - self.setconf('-Dopt2=val2') - - self.__reconfigure() - - out = self.init(testdir, extra_args=['--reconfigure', '-Dopt3=val3']) - self.assertRegex(out, 'WARNING:.*Regenerating configuration from scratch') - self.assertRegex(out, 'opt1 val1') - self.assertRegex(out, 'opt2 val2') - self.assertRegex(out, 'opt3 val3') - self.assertRegex(out, 'opt4 default4') - self.build() - self.run_tests() - - # Create a file in builddir and verify wipe command removes it - filename = os.path.join(self.builddir, 'something') - open(filename, 'w').close() - self.assertTrue(os.path.exists(filename)) - out = self.init(testdir, extra_args=['--wipe', '-Dopt4=val4']) - self.assertFalse(os.path.exists(filename)) - self.assertRegex(out, 'opt1 val1') - self.assertRegex(out, 'opt2 val2') - self.assertRegex(out, 'opt3 val3') - self.assertRegex(out, 'opt4 val4') - self.build() - self.run_tests() - - def test_wipe_from_builddir(self): - testdir = os.path.join(self.common_test_dir, '161 custom target subdir depend files') - self.init(testdir) - self.__reconfigure() - - with Path(self.builddir): - self.init(testdir, extra_args=['--wipe']) - - def test_minor_version_does_not_reconfigure_wipe(self): - testdir = os.path.join(self.unit_test_dir, '48 reconfigure') - self.init(testdir, extra_args=['-Dopt1=val1']) - self.setconf('-Dopt2=val2') - - self.__reconfigure(change_minor=True) - - out = self.init(testdir, extra_args=['--reconfigure', '-Dopt3=val3']) - self.assertNotRegex(out, 'WARNING:.*Regenerating configuration from scratch') - self.assertRegex(out, 'opt1 val1') - self.assertRegex(out, 'opt2 val2') - self.assertRegex(out, 'opt3 val3') - self.assertRegex(out, 'opt4 default4') - self.build() - self.run_tests() - - def test_target_construct_id_from_path(self): - # This id is stable but not guessable. - # The test is supposed to prevent unintentional - # changes of target ID generation. - target_id = Target.construct_id_from_path('some/obscure/subdir', - 'target-id', '@suffix') - self.assertEqual('5e002d3@@target-id@suffix', target_id) - target_id = Target.construct_id_from_path('subproject/foo/subdir/bar', - 'target2-id', '@other') - self.assertEqual('81d46d1@@target2-id@other', target_id) - - def test_introspect_projectinfo_without_configured_build(self): - testfile = os.path.join(self.common_test_dir, '35 run program', 'meson.build') - res = self.introspect_directory(testfile, '--projectinfo') - self.assertEqual(set(res['buildsystem_files']), set(['meson.build'])) - self.assertEqual(res['version'], 'undefined') - self.assertEqual(res['descriptive_name'], 'run command') - self.assertEqual(res['subprojects'], []) - - testfile = os.path.join(self.common_test_dir, '43 options', 'meson.build') - res = self.introspect_directory(testfile, '--projectinfo') - self.assertEqual(set(res['buildsystem_files']), set(['meson_options.txt', 'meson.build'])) - self.assertEqual(res['version'], 'undefined') - self.assertEqual(res['descriptive_name'], 'options') - self.assertEqual(res['subprojects'], []) - - testfile = os.path.join(self.common_test_dir, '46 subproject options', 'meson.build') - res = self.introspect_directory(testfile, '--projectinfo') - self.assertEqual(set(res['buildsystem_files']), set(['meson_options.txt', 'meson.build'])) - self.assertEqual(res['version'], 'undefined') - self.assertEqual(res['descriptive_name'], 'suboptions') - self.assertEqual(len(res['subprojects']), 1) - subproject_files = set(f.replace('\\', '/') for f in res['subprojects'][0]['buildsystem_files']) - self.assertEqual(subproject_files, set(['subprojects/subproject/meson_options.txt', 'subprojects/subproject/meson.build'])) - self.assertEqual(res['subprojects'][0]['name'], 'subproject') - self.assertEqual(res['subprojects'][0]['version'], 'undefined') - self.assertEqual(res['subprojects'][0]['descriptive_name'], 'subproject') - - def test_introspect_projectinfo_subprojects(self): - testdir = os.path.join(self.common_test_dir, '102 subproject subdir') - self.init(testdir) - res = self.introspect('--projectinfo') - expected = { - 'descriptive_name': 'proj', - 'version': 'undefined', - 'subproject_dir': 'subprojects', - 'subprojects': [ - { - 'descriptive_name': 'sub', - 'name': 'sub', - 'version': 'undefined' - } - ] - } - self.assertDictEqual(res, expected) - - def test_introspection_target_subproject(self): - testdir = os.path.join(self.common_test_dir, '45 subproject') - self.init(testdir) - res = self.introspect('--targets') - - expected = { - 'sublib': 'sublib', - 'simpletest': 'sublib', - 'user': None - } - - for entry in res: - name = entry['name'] - self.assertEqual(entry['subproject'], expected[name]) - - def test_introspect_projectinfo_subproject_dir(self): - testdir = os.path.join(self.common_test_dir, '78 custom subproject dir') - self.init(testdir) - res = self.introspect('--projectinfo') - - self.assertEqual(res['subproject_dir'], 'custom_subproject_dir') - - def test_introspect_projectinfo_subproject_dir_from_source(self): - testfile = os.path.join(self.common_test_dir, '78 custom subproject dir', 'meson.build') - res = self.introspect_directory(testfile, '--projectinfo') - - self.assertEqual(res['subproject_dir'], 'custom_subproject_dir') - - @skipIfNoExecutable('clang-format') - def test_clang_format(self): - if self.backend is not Backend.ninja: - raise unittest.SkipTest('Clang-format is for now only supported on Ninja, not {}'.format(self.backend.name)) - testdir = os.path.join(self.unit_test_dir, '54 clang-format') - testfile = os.path.join(testdir, 'prog.c') - badfile = os.path.join(testdir, 'prog_orig_c') - goodfile = os.path.join(testdir, 'prog_expected_c') - testheader = os.path.join(testdir, 'header.h') - badheader = os.path.join(testdir, 'header_orig_h') - goodheader = os.path.join(testdir, 'header_expected_h') - try: - shutil.copyfile(badfile, testfile) - shutil.copyfile(badheader, testheader) - self.init(testdir) - self.assertNotEqual(Path(testfile).read_text(), - Path(goodfile).read_text()) - self.assertNotEqual(Path(testheader).read_text(), - Path(goodheader).read_text()) - self.run_target('clang-format') - self.assertEqual(Path(testheader).read_text(), - Path(goodheader).read_text()) - finally: - if os.path.exists(testfile): - os.unlink(testfile) - if os.path.exists(testheader): - os.unlink(testheader) - - @skipIfNoExecutable('clang-tidy') - def test_clang_tidy(self): - if self.backend is not Backend.ninja: - raise unittest.SkipTest('Clang-tidy is for now only supported on Ninja, not {}'.format(self.backend.name)) - if shutil.which('c++') is None: - raise unittest.SkipTest('Clang-tidy breaks when ccache is used and "c++" not in path.') - if is_osx(): - raise unittest.SkipTest('Apple ships a broken clang-tidy that chokes on -pipe.') - testdir = os.path.join(self.unit_test_dir, '70 clang-tidy') - self.init(testdir, override_envvars={'CXX': 'c++'}) - out = self.run_target('clang-tidy') - self.assertIn('cttest.cpp:4:20', out) - - def test_identity_cross(self): - testdir = os.path.join(self.unit_test_dir, '71 cross') - # Do a build to generate a cross file where the host is this target - self.init(testdir, extra_args=['-Dgenerate=true']) - self.meson_cross_file = os.path.join(self.builddir, "crossfile") - self.assertTrue(os.path.exists(self.meson_cross_file)) - # Now verify that this is detected as cross - self.new_builddir() - self.init(testdir) - - def test_introspect_buildoptions_without_configured_build(self): - testdir = os.path.join(self.unit_test_dir, '59 introspect buildoptions') - testfile = os.path.join(testdir, 'meson.build') - res_nb = self.introspect_directory(testfile, ['--buildoptions'] + self.meson_args) - self.init(testdir, default_args=False) - res_wb = self.introspect('--buildoptions') - self.maxDiff = None - self.assertListEqual(res_nb, res_wb) - - def test_meson_configure_from_source_does_not_crash(self): - testdir = os.path.join(self.unit_test_dir, '59 introspect buildoptions') - self._run(self.mconf_command + [testdir]) - - def test_introspect_json_dump(self): - testdir = os.path.join(self.unit_test_dir, '57 introspection') - self.init(testdir) - infodir = os.path.join(self.builddir, 'meson-info') - self.assertPathExists(infodir) - - def assertKeyTypes(key_type_list, obj): - for i in key_type_list: - self.assertIn(i[0], obj) - self.assertIsInstance(obj[i[0]], i[1]) - - root_keylist = [ - ('benchmarks', list), - ('buildoptions', list), - ('buildsystem_files', list), - ('dependencies', list), - ('installed', dict), - ('projectinfo', dict), - ('targets', list), - ('tests', list), - ] - - test_keylist = [ - ('cmd', list), - ('env', dict), - ('name', str), - ('timeout', int), - ('suite', list), - ('is_parallel', bool), - ('protocol', str), - ] - - buildoptions_keylist = [ - ('name', str), - ('section', str), - ('type', str), - ('description', str), - ('machine', str), - ] - - buildoptions_typelist = [ - ('combo', str, [('choices', list)]), - ('string', str, []), - ('boolean', bool, []), - ('integer', int, []), - ('array', list, []), - ] - - buildoptions_sections = ['core', 'backend', 'base', 'compiler', 'directory', 'user', 'test'] - buildoptions_machines = ['any', 'build', 'host'] - - dependencies_typelist = [ - ('name', str), - ('version', str), - ('compile_args', list), - ('link_args', list), - ] - - targets_typelist = [ - ('name', str), - ('id', str), - ('type', str), - ('defined_in', str), - ('filename', list), - ('build_by_default', bool), - ('target_sources', list), - ('installed', bool), - ] - - targets_sources_typelist = [ - ('language', str), - ('compiler', list), - ('parameters', list), - ('sources', list), - ('generated_sources', list), - ] - - # First load all files - res = {} - for i in root_keylist: - curr = os.path.join(infodir, 'intro-{}.json'.format(i[0])) - self.assertPathExists(curr) - with open(curr, 'r') as fp: - res[i[0]] = json.load(fp) - - assertKeyTypes(root_keylist, res) - - # Check Tests and benchmarks - tests_to_find = ['test case 1', 'test case 2', 'benchmark 1'] - for i in res['benchmarks'] + res['tests']: - assertKeyTypes(test_keylist, i) - if i['name'] in tests_to_find: - tests_to_find.remove(i['name']) - self.assertListEqual(tests_to_find, []) - - # Check buildoptions - buildopts_to_find = {'cpp_std': 'c++11'} - for i in res['buildoptions']: - assertKeyTypes(buildoptions_keylist, i) - valid_type = False - for j in buildoptions_typelist: - if i['type'] == j[0]: - self.assertIsInstance(i['value'], j[1]) - assertKeyTypes(j[2], i) - valid_type = True - break - - self.assertIn(i['section'], buildoptions_sections) - self.assertIn(i['machine'], buildoptions_machines) - self.assertTrue(valid_type) - if i['name'] in buildopts_to_find: - self.assertEqual(i['value'], buildopts_to_find[i['name']]) - buildopts_to_find.pop(i['name'], None) - self.assertDictEqual(buildopts_to_find, {}) - - # Check buildsystem_files - bs_files = ['meson.build', 'meson_options.txt', 'sharedlib/meson.build', 'staticlib/meson.build'] - bs_files = [os.path.join(testdir, x) for x in bs_files] - self.assertPathListEqual(list(sorted(res['buildsystem_files'])), list(sorted(bs_files))) - - # Check dependencies - dependencies_to_find = ['threads'] - for i in res['dependencies']: - assertKeyTypes(dependencies_typelist, i) - if i['name'] in dependencies_to_find: - dependencies_to_find.remove(i['name']) - self.assertListEqual(dependencies_to_find, []) - - # Check projectinfo - self.assertDictEqual(res['projectinfo'], {'version': '1.2.3', 'descriptive_name': 'introspection', 'subproject_dir': 'subprojects', 'subprojects': []}) - - # Check targets - targets_to_find = { - 'sharedTestLib': ('shared library', True, False, 'sharedlib/meson.build'), - 'staticTestLib': ('static library', True, False, 'staticlib/meson.build'), - 'test1': ('executable', True, True, 'meson.build'), - 'test2': ('executable', True, False, 'meson.build'), - 'test3': ('executable', True, False, 'meson.build'), - } - for i in res['targets']: - assertKeyTypes(targets_typelist, i) - if i['name'] in targets_to_find: - tgt = targets_to_find[i['name']] - self.assertEqual(i['type'], tgt[0]) - self.assertEqual(i['build_by_default'], tgt[1]) - self.assertEqual(i['installed'], tgt[2]) - self.assertPathEqual(i['defined_in'], os.path.join(testdir, tgt[3])) - targets_to_find.pop(i['name'], None) - for j in i['target_sources']: - assertKeyTypes(targets_sources_typelist, j) - self.assertDictEqual(targets_to_find, {}) - - def test_introspect_file_dump_equals_all(self): - testdir = os.path.join(self.unit_test_dir, '57 introspection') - self.init(testdir) - res_all = self.introspect('--all') - res_file = {} - - root_keylist = [ - 'benchmarks', - 'buildoptions', - 'buildsystem_files', - 'dependencies', - 'installed', - 'projectinfo', - 'targets', - 'tests', - ] - - infodir = os.path.join(self.builddir, 'meson-info') - self.assertPathExists(infodir) - for i in root_keylist: - curr = os.path.join(infodir, 'intro-{}.json'.format(i)) - self.assertPathExists(curr) - with open(curr, 'r') as fp: - res_file[i] = json.load(fp) - - self.assertEqual(res_all, res_file) - - def test_introspect_meson_info(self): - testdir = os.path.join(self.unit_test_dir, '57 introspection') - introfile = os.path.join(self.builddir, 'meson-info', 'meson-info.json') - self.init(testdir) - self.assertPathExists(introfile) - with open(introfile, 'r') as fp: - res1 = json.load(fp) - - for i in ['meson_version', 'directories', 'introspection', 'build_files_updated', 'error']: - self.assertIn(i, res1) - - self.assertEqual(res1['error'], False) - self.assertEqual(res1['build_files_updated'], True) - - def test_introspect_config_update(self): - testdir = os.path.join(self.unit_test_dir, '57 introspection') - introfile = os.path.join(self.builddir, 'meson-info', 'intro-buildoptions.json') - self.init(testdir) - self.assertPathExists(introfile) - with open(introfile, 'r') as fp: - res1 = json.load(fp) - - self.setconf('-Dcpp_std=c++14') - self.setconf('-Dbuildtype=release') - - for idx, i in enumerate(res1): - if i['name'] == 'cpp_std': - res1[idx]['value'] = 'c++14' - if i['name'] == 'build.cpp_std': - res1[idx]['value'] = 'c++14' - if i['name'] == 'buildtype': - res1[idx]['value'] = 'release' - if i['name'] == 'optimization': - res1[idx]['value'] = '3' - if i['name'] == 'debug': - res1[idx]['value'] = False - - with open(introfile, 'r') as fp: - res2 = json.load(fp) - - self.assertListEqual(res1, res2) - - def test_introspect_targets_from_source(self): - testdir = os.path.join(self.unit_test_dir, '57 introspection') - testfile = os.path.join(testdir, 'meson.build') - introfile = os.path.join(self.builddir, 'meson-info', 'intro-targets.json') - self.init(testdir) - self.assertPathExists(introfile) - with open(introfile, 'r') as fp: - res_wb = json.load(fp) - - res_nb = self.introspect_directory(testfile, ['--targets'] + self.meson_args) - - # Account for differences in output - for i in res_wb: - i['filename'] = [os.path.relpath(x, self.builddir) for x in i['filename']] - if 'install_filename' in i: - del i['install_filename'] - - sources = [] - for j in i['target_sources']: - sources += j['sources'] - i['target_sources'] = [{ - 'language': 'unknown', - 'compiler': [], - 'parameters': [], - 'sources': sources, - 'generated_sources': [] - }] - - self.maxDiff = None - self.assertListEqual(res_nb, res_wb) - - def test_introspect_dependencies_from_source(self): - testdir = os.path.join(self.unit_test_dir, '57 introspection') - testfile = os.path.join(testdir, 'meson.build') - res_nb = self.introspect_directory(testfile, ['--scan-dependencies'] + self.meson_args) - expected = [ - { - 'name': 'threads', - 'required': True, - 'version': [], - 'has_fallback': False, - 'conditional': False - }, - { - 'name': 'zlib', - 'required': False, - 'version': [], - 'has_fallback': False, - 'conditional': False - }, - { - 'name': 'bugDep1', - 'required': True, - 'version': [], - 'has_fallback': False, - 'conditional': False - }, - { - 'name': 'somethingthatdoesnotexist', - 'required': True, - 'version': ['>=1.2.3'], - 'has_fallback': False, - 'conditional': True - }, - { - 'name': 'look_i_have_a_fallback', - 'required': True, - 'version': ['>=1.0.0', '<=99.9.9'], - 'has_fallback': True, - 'conditional': True - } - ] - self.maxDiff = None - self.assertListEqual(res_nb, expected) - - def test_unstable_coredata(self): - testdir = os.path.join(self.common_test_dir, '1 trivial') - self.init(testdir) - # just test that the command does not fail (e.g. because it throws an exception) - self._run([*self.meson_command, 'unstable-coredata', self.builddir]) - - @skip_if_no_cmake - def test_cmake_prefix_path(self): - testdir = os.path.join(self.unit_test_dir, '64 cmake_prefix_path') - self.init(testdir, extra_args=['-Dcmake_prefix_path=' + os.path.join(testdir, 'prefix')]) - - @skip_if_no_cmake - def test_cmake_parser(self): - testdir = os.path.join(self.unit_test_dir, '65 cmake parser') - self.init(testdir, extra_args=['-Dcmake_prefix_path=' + os.path.join(testdir, 'prefix')]) - - def test_alias_target(self): - if self.backend is Backend.vs: - # FIXME: This unit test is broken with vs backend, needs investigation - raise unittest.SkipTest('Skipping alias_target test with {} backend'.format(self.backend.name)) - testdir = os.path.join(self.unit_test_dir, '66 alias target') - self.init(testdir) - self.build() - self.assertPathDoesNotExist(os.path.join(self.builddir, 'prog' + exe_suffix)) - self.assertPathDoesNotExist(os.path.join(self.builddir, 'hello.txt')) - self.run_target('build-all') - self.assertPathExists(os.path.join(self.builddir, 'prog' + exe_suffix)) - self.assertPathExists(os.path.join(self.builddir, 'hello.txt')) - - def test_configure(self): - testdir = os.path.join(self.common_test_dir, '2 cpp') - self.init(testdir) - self._run(self.mconf_command + [self.builddir]) - - def test_summary(self): - testdir = os.path.join(self.unit_test_dir, '74 summary') - out = self.init(testdir) - expected = textwrap.dedent(r''' - Some Subproject 2.0 - - string: bar - integer: 1 - boolean: True - - My Project 1.0 - - Configuration - Some boolean: False - Another boolean: True - Some string: Hello World - A list: string - 1 - True - empty list: - A number: 1 - yes: YES - no: NO - - Subprojects - sub: YES - sub2: NO - ''') - 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 - self.assertEqual(sorted(expected_lines), sorted(out_lines)) - else: - self.assertEqual(expected_lines, out_lines) - - -class FailureTests(BasePlatformTests): - ''' - Tests that test failure conditions. Build files here should be dynamically - generated and static tests should go into `test cases/failing*`. - This is useful because there can be many ways in which a particular - function can fail, and creating failing tests for all of them is tedious - and slows down testing. - ''' - dnf = "[Dd]ependency.*not found(:.*)?" - nopkg = '[Pp]kg-config.*not found' - - def setUp(self): - super().setUp() - self.srcdir = os.path.realpath(tempfile.mkdtemp()) - self.mbuild = os.path.join(self.srcdir, 'meson.build') - self.moptions = os.path.join(self.srcdir, 'meson_options.txt') - - def tearDown(self): - super().tearDown() - windows_proof_rmtree(self.srcdir) - - def assertMesonRaises(self, contents, match, *, - extra_args=None, - langs=None, - meson_version=None, - options=None, - override_envvars=None): - ''' - Assert that running meson configure on the specified @contents raises - a error message matching regex @match. - ''' - if langs is None: - langs = [] - with open(self.mbuild, 'w') as f: - f.write("project('failure test', 'c', 'cpp'") - if meson_version: - f.write(", meson_version: '{}'".format(meson_version)) - f.write(")\n") - for lang in langs: - f.write("add_languages('{}', required : false)\n".format(lang)) - f.write(contents) - if options is not None: - with open(self.moptions, 'w') as f: - f.write(options) - o = {'MESON_FORCE_BACKTRACE': '1'} - if override_envvars is None: - override_envvars = o - else: - override_envvars.update(o) - # Force tracebacks so we can detect them properly - with self.assertRaisesRegex(MesonException, match, msg=contents): - # Must run in-process or we'll get a generic CalledProcessError - self.init(self.srcdir, extra_args=extra_args, - inprocess=True, - override_envvars = override_envvars) - - def obtainMesonOutput(self, contents, match, extra_args, langs, meson_version=None): - if langs is None: - langs = [] - with open(self.mbuild, 'w') as f: - f.write("project('output test', 'c', 'cpp'") - if meson_version: - f.write(", meson_version: '{}'".format(meson_version)) - f.write(")\n") - for lang in langs: - f.write("add_languages('{}', required : false)\n".format(lang)) - f.write(contents) - # Run in-process for speed and consistency with assertMesonRaises - return self.init(self.srcdir, extra_args=extra_args, inprocess=True) - - def assertMesonOutputs(self, contents, match, extra_args=None, langs=None, meson_version=None): - ''' - Assert that running meson configure on the specified @contents outputs - something that matches regex @match. - ''' - out = self.obtainMesonOutput(contents, match, extra_args, langs, meson_version) - self.assertRegex(out, match) - - def assertMesonDoesNotOutput(self, contents, match, extra_args=None, langs=None, meson_version=None): - ''' - Assert that running meson configure on the specified @contents does not output - something that matches regex @match. - ''' - out = self.obtainMesonOutput(contents, match, extra_args, langs, meson_version) - self.assertNotRegex(out, match) - - @skipIfNoPkgconfig - def test_dependency(self): - if subprocess.call(['pkg-config', '--exists', 'zlib']) != 0: - raise unittest.SkipTest('zlib not found with pkg-config') - a = (("dependency('zlib', method : 'fail')", "'fail' is invalid"), - ("dependency('zlib', static : '1')", "[Ss]tatic.*boolean"), - ("dependency('zlib', version : 1)", "[Vv]ersion.*string or list"), - ("dependency('zlib', required : 1)", "[Rr]equired.*boolean"), - ("dependency('zlib', method : 1)", "[Mm]ethod.*string"), - ("dependency('zlibfail')", self.dnf),) - for contents, match in a: - self.assertMesonRaises(contents, match) - - def test_apple_frameworks_dependency(self): - if not is_osx(): - raise unittest.SkipTest('only run on macOS') - self.assertMesonRaises("dependency('appleframeworks')", - "requires at least one module") - - def test_extraframework_dependency_method(self): - code = "dependency('python', method : 'extraframework')" - if not is_osx(): - self.assertMesonRaises(code, self.dnf) - else: - # Python2 framework is always available on macOS - self.assertMesonOutputs(code, '[Dd]ependency.*python.*found.*YES') - - def test_sdl2_notfound_dependency(self): - # Want to test failure, so skip if available - if shutil.which('sdl2-config'): - raise unittest.SkipTest('sdl2-config found') - self.assertMesonRaises("dependency('sdl2', method : 'sdlconfig')", self.dnf) - if shutil.which('pkg-config'): - self.assertMesonRaises("dependency('sdl2', method : 'pkg-config')", self.dnf) - with no_pkgconfig(): - # Look for pkg-config, cache it, then - # Use cached pkg-config without erroring out, then - # Use cached pkg-config to error out - code = "dependency('foobarrr', method : 'pkg-config', required : false)\n" \ - "dependency('foobarrr2', method : 'pkg-config', required : false)\n" \ - "dependency('sdl2', method : 'pkg-config')" - self.assertMesonRaises(code, self.nopkg) - - def test_gnustep_notfound_dependency(self): - # Want to test failure, so skip if available - if shutil.which('gnustep-config'): - raise unittest.SkipTest('gnustep-config found') - self.assertMesonRaises("dependency('gnustep')", - "(requires a Objc compiler|{})".format(self.dnf), - langs = ['objc']) - - def test_wx_notfound_dependency(self): - # Want to test failure, so skip if available - if shutil.which('wx-config-3.0') or shutil.which('wx-config') or shutil.which('wx-config-gtk3'): - raise unittest.SkipTest('wx-config, wx-config-3.0 or wx-config-gtk3 found') - self.assertMesonRaises("dependency('wxwidgets')", self.dnf) - self.assertMesonOutputs("dependency('wxwidgets', required : false)", - "Run-time dependency .*WxWidgets.* found: .*NO.*") - - def test_wx_dependency(self): - if not shutil.which('wx-config-3.0') and not shutil.which('wx-config') and not shutil.which('wx-config-gtk3'): - raise unittest.SkipTest('Neither wx-config, wx-config-3.0 nor wx-config-gtk3 found') - self.assertMesonRaises("dependency('wxwidgets', modules : 1)", - "module argument is not a string") - - def test_llvm_dependency(self): - self.assertMesonRaises("dependency('llvm', modules : 'fail')", - "(required.*fail|{})".format(self.dnf)) - - def test_boost_notfound_dependency(self): - # Can be run even if Boost is found or not - self.assertMesonRaises("dependency('boost', modules : 1)", - "module.*not a string") - self.assertMesonRaises("dependency('boost', modules : 'fail')", - "(fail.*not found|{})".format(self.dnf)) - - def test_boost_BOOST_ROOT_dependency(self): - # Test BOOST_ROOT; can be run even if Boost is found or not - self.assertMesonRaises("dependency('boost')", - "(BOOST_ROOT.*absolute|{})".format(self.dnf), - override_envvars = {'BOOST_ROOT': 'relative/path'}) - - def test_dependency_invalid_method(self): - code = '''zlib_dep = dependency('zlib', required : false) - zlib_dep.get_configtool_variable('foo') - ''' - self.assertMesonRaises(code, ".* is not a config-tool dependency") - code = '''zlib_dep = dependency('zlib', required : false) - dep = declare_dependency(dependencies : zlib_dep) - dep.get_pkgconfig_variable('foo') - ''' - self.assertMesonRaises(code, "Method.*pkgconfig.*is invalid.*internal") - code = '''zlib_dep = dependency('zlib', required : false) - dep = declare_dependency(dependencies : zlib_dep) - dep.get_configtool_variable('foo') - ''' - self.assertMesonRaises(code, "Method.*configtool.*is invalid.*internal") - - def test_objc_cpp_detection(self): - ''' - Test that when we can't detect objc or objcpp, we fail gracefully. - ''' - env = get_fake_env() - try: - env.detect_objc_compiler(MachineChoice.HOST) - env.detect_objcpp_compiler(MachineChoice.HOST) - except EnvironmentException: - code = "add_languages('objc')\nadd_languages('objcpp')" - self.assertMesonRaises(code, "Unknown compiler") - return - raise unittest.SkipTest("objc and objcpp found, can't test detection failure") - - def test_subproject_variables(self): - ''' - Test that: - 1. The correct message is outputted when a not-required dep is not - found and the fallback subproject is also not found. - 2. A not-required fallback dependency is not found because the - subproject failed to parse. - 3. A not-found not-required dep with a fallback subproject outputs the - correct message when the fallback subproject is found but the - variable inside it is not. - 4. A fallback dependency is found from the subproject parsed in (3) - 5. The correct message is outputted when the .wrap file is missing for - a sub-subproject. - ''' - tdir = os.path.join(self.unit_test_dir, '20 subproj dep variables') - out = self.init(tdir, inprocess=True) - self.assertRegex(out, r"Subproject directory not found and .*nosubproj.wrap.* file not found") - self.assertRegex(out, r'Function does not take positional arguments.') - self.assertRegex(out, r'WARNING:.* Dependency .*subsubproject.* not found but it is available in a sub-subproject.') - self.assertRegex(out, r'Subproject directory not found and .*subsubproject.wrap.* file not found') - self.assertRegex(out, r'Dependency .*zlibproxy.* from subproject .*subprojects.*somesubproj.* found: .*YES.*') - - def test_exception_exit_status(self): - ''' - Test exit status on python exception - ''' - tdir = os.path.join(self.unit_test_dir, '21 exit status') - with self.assertRaises(subprocess.CalledProcessError) as cm: - self.init(tdir, inprocess=False, override_envvars = {'MESON_UNIT_TEST': '1'}) - self.assertEqual(cm.exception.returncode, 2) - self.wipe() - - def test_dict_requires_key_value_pairs(self): - self.assertMesonRaises("dict = {3, 'foo': 'bar'}", - 'Only key:value pairs are valid in dict construction.') - self.assertMesonRaises("{'foo': 'bar', 3}", - 'Only key:value pairs are valid in dict construction.') - - def test_dict_forbids_duplicate_keys(self): - self.assertMesonRaises("dict = {'a': 41, 'a': 42}", - 'Duplicate dictionary key: a.*') - - def test_dict_forbids_integer_key(self): - self.assertMesonRaises("dict = {3: 'foo'}", - 'Key must be a string.*') - - def test_using_too_recent_feature(self): - # Here we use a dict, which was introduced in 0.47.0 - self.assertMesonOutputs("dict = {}", - ".*WARNING.*Project targeting.*but.*", - meson_version='>= 0.46.0') - - def test_using_recent_feature(self): - # Same as above, except the meson version is now appropriate - self.assertMesonDoesNotOutput("dict = {}", - ".*WARNING.*Project targeting.*but.*", - meson_version='>= 0.47') - - def test_using_too_recent_feature_dependency(self): - self.assertMesonOutputs("dependency('pcap', required: false)", - ".*WARNING.*Project targeting.*but.*", - meson_version='>= 0.41.0') - - def test_vcs_tag_featurenew_build_always_stale(self): - 'https://github.com/mesonbuild/meson/issues/3904' - vcs_tag = '''version_data = configuration_data() - version_data.set('PROJVER', '@VCS_TAG@') - vf = configure_file(output : 'version.h.in', configuration: version_data) - f = vcs_tag(input : vf, output : 'version.h') - ''' - msg = '.*WARNING:.*feature.*build_always_stale.*custom_target.*' - self.assertMesonDoesNotOutput(vcs_tag, msg, meson_version='>=0.43') - - def test_missing_subproject_not_required_and_required(self): - self.assertMesonRaises("sub1 = subproject('not-found-subproject', required: false)\n" + - "sub2 = subproject('not-found-subproject', required: true)", - """.*Subproject "subprojects/not-found-subproject" required but not found.*""") - - def test_get_variable_on_not_found_project(self): - self.assertMesonRaises("sub1 = subproject('not-found-subproject', required: false)\n" + - "sub1.get_variable('naaa')", - """Subproject "subprojects/not-found-subproject" disabled can't get_variable on it.""") - - def test_version_checked_before_parsing_options(self): - ''' - https://github.com/mesonbuild/meson/issues/5281 - ''' - options = "option('some-option', type: 'foo', value: '')" - match = 'Meson version is.*but project requires >=2000' - self.assertMesonRaises("", match, meson_version='>=2000', options=options) - - def test_assert_default_message(self): - self.assertMesonRaises("k1 = 'a'\n" + - "assert({\n" + - " k1: 1,\n" + - "}['a'] == 2)\n", - r"Assert failed: {k1 : 1}\['a'\] == 2") - -@unittest.skipUnless(is_windows() or is_cygwin(), "requires Windows (or Windows via Cygwin)") -class WindowsTests(BasePlatformTests): - ''' - Tests that should run on Cygwin, MinGW, and MSVC - ''' - - def setUp(self): - super().setUp() - self.platform_test_dir = os.path.join(self.src_root, 'test cases/windows') - - @unittest.skipIf(is_cygwin(), 'Test only applicable to Windows') - def test_find_program(self): - ''' - Test that Windows-specific edge-cases in find_program are functioning - correctly. Cannot be an ordinary test because it involves manipulating - PATH to point to a directory with Python scripts. - ''' - testdir = os.path.join(self.platform_test_dir, '8 find program') - # Find `cmd` and `cmd.exe` - prog1 = ExternalProgram('cmd') - self.assertTrue(prog1.found(), msg='cmd not found') - prog2 = ExternalProgram('cmd.exe') - self.assertTrue(prog2.found(), msg='cmd.exe not found') - self.assertPathEqual(prog1.get_path(), prog2.get_path()) - # Find cmd with an absolute path that's missing the extension - cmd_path = prog2.get_path()[:-4] - prog = ExternalProgram(cmd_path) - self.assertTrue(prog.found(), msg='{!r} not found'.format(cmd_path)) - # Finding a script with no extension inside a directory works - prog = ExternalProgram(os.path.join(testdir, 'test-script')) - self.assertTrue(prog.found(), msg='test-script not found') - # Finding a script with an extension inside a directory works - prog = ExternalProgram(os.path.join(testdir, 'test-script-ext.py')) - self.assertTrue(prog.found(), msg='test-script-ext.py not found') - # Finding a script in PATH - os.environ['PATH'] += os.pathsep + testdir - # Finding a script in PATH w/o extension works and adds the interpreter - # (check only if `.PY` is in PATHEXT) - if '.PY' in [ext.upper() for ext in os.environ['PATHEXT'].split(';')]: - prog = ExternalProgram('test-script-ext') - self.assertTrue(prog.found(), msg='test-script-ext not found in PATH') - self.assertPathEqual(prog.get_command()[0], python_command[0]) - self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py') - # Finding a script in PATH with extension works and adds the interpreter - prog = ExternalProgram('test-script-ext.py') - self.assertTrue(prog.found(), msg='test-script-ext.py not found in PATH') - self.assertPathEqual(prog.get_command()[0], python_command[0]) - self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py') - # Ensure that WindowsApps gets removed from PATH - path = os.environ['PATH'] - if 'WindowsApps' not in path: - username = os.environ['USERNAME'] - appstore_dir = r'C:\Users\{}\AppData\Local\Microsoft\WindowsApps'.format(username) - path = os.pathsep + appstore_dir - path = ExternalProgram._windows_sanitize_path(path) - self.assertNotIn('WindowsApps', path) - - def test_ignore_libs(self): - ''' - Test that find_library on libs that are to be ignored returns an empty - array of arguments. Must be a unit test because we cannot inspect - ExternalLibraryHolder from build files. - ''' - testdir = os.path.join(self.platform_test_dir, '1 basic') - env = get_fake_env(testdir, self.builddir, self.prefix) - cc = env.detect_c_compiler(MachineChoice.HOST) - if cc.get_argument_syntax() != 'msvc': - raise unittest.SkipTest('Not using MSVC') - # To force people to update this test, and also test - self.assertEqual(set(cc.ignore_libs), {'c', 'm', 'pthread', 'dl', 'rt', 'execinfo'}) - for l in cc.ignore_libs: - self.assertEqual(cc.find_library(l, env, []), []) - - def test_rc_depends_files(self): - testdir = os.path.join(self.platform_test_dir, '5 resources') - - # resource compiler depfile generation is not yet implemented for msvc - env = get_fake_env(testdir, self.builddir, self.prefix) - depfile_works = env.detect_c_compiler(MachineChoice.HOST).get_id() not in {'msvc', 'clang-cl', 'intel-cl'} - - self.init(testdir) - self.build() - # Immediately rebuilding should not do anything - self.assertBuildIsNoop() - # Test compile_resources(depend_file:) - # Changing mtime of sample.ico should rebuild prog - self.utime(os.path.join(testdir, 'res', 'sample.ico')) - self.assertRebuiltTarget('prog') - # Test depfile generation by compile_resources - # Changing mtime of resource.h should rebuild myres.rc and then prog - if depfile_works: - self.utime(os.path.join(testdir, 'inc', 'resource', 'resource.h')) - self.assertRebuiltTarget('prog') - self.wipe() - - if depfile_works: - testdir = os.path.join(self.platform_test_dir, '12 resources with custom targets') - self.init(testdir) - self.build() - # Immediately rebuilding should not do anything - self.assertBuildIsNoop() - # Changing mtime of resource.h should rebuild myres_1.rc and then prog_1 - self.utime(os.path.join(testdir, 'res', 'resource.h')) - self.assertRebuiltTarget('prog_1') - - def test_msvc_cpp17(self): - testdir = os.path.join(self.unit_test_dir, '45 vscpp17') - - env = get_fake_env(testdir, self.builddir, self.prefix) - cc = env.detect_c_compiler(MachineChoice.HOST) - if cc.get_argument_syntax() != 'msvc': - raise unittest.SkipTest('Test only applies to MSVC-like compilers') - - try: - self.init(testdir) - except subprocess.CalledProcessError: - # According to Python docs, output is only stored when - # using check_output. We don't use it, so we can't check - # that the output is correct (i.e. that it failed due - # to the right reason). - return - self.build() - - def test_install_pdb_introspection(self): - testdir = os.path.join(self.platform_test_dir, '1 basic') - - env = get_fake_env(testdir, self.builddir, self.prefix) - cc = env.detect_c_compiler(MachineChoice.HOST) - if cc.get_argument_syntax() != 'msvc': - raise unittest.SkipTest('Test only applies to MSVC-like compilers') - - self.init(testdir) - installed = self.introspect('--installed') - files = [os.path.basename(path) for path in installed.values()] - - self.assertTrue('prog.pdb' in files) - - def _check_ld(self, name: str, lang: str, expected: str) -> None: - if not shutil.which(name): - raise unittest.SkipTest('Could not find {}.'.format(name)) - envvar = mesonbuild.envconfig.BinaryTable.evarMap['{}_ld'.format(lang)] - with mock.patch.dict(os.environ, {envvar: name}): - env = get_fake_env() - try: - comp = getattr(env, 'detect_{}_compiler'.format(lang))(MachineChoice.HOST) - except EnvironmentException: - raise unittest.SkipTest('Could not find a compiler for {}'.format(lang)) - self.assertEqual(comp.linker.id, expected) - - def test_link_environment_variable_lld_link(self): - self._check_ld('lld-link', 'c', 'lld-link') - - def test_link_environment_variable_link(self): - self._check_ld('link', 'c', 'link') - - def test_link_environment_variable_optlink(self): - self._check_ld('optlink', 'c', 'optlink') - - def test_link_environment_variable_rust(self): - self._check_ld('link', 'rust', 'link') - - def test_pefile_checksum(self): - try: - import pefile - except ImportError: - if is_ci(): - raise - raise unittest.SkipTest('pefile module not found') - testdir = os.path.join(self.common_test_dir, '6 linkshared') - self.init(testdir) - self.build() - # Test that binaries have a non-zero checksum - env = get_fake_env() - cc = env.detect_c_compiler(MachineChoice.HOST) - cc_id = cc.get_id() - ld_id = cc.get_linker_id() - dll = glob(os.path.join(self.builddir, '*mycpplib.dll'))[0] - exe = os.path.join(self.builddir, 'cppprog.exe') - for f in (dll, exe): - pe = pefile.PE(f) - msg = 'PE file: {!r}, compiler: {!r}, linker: {!r}'.format(f, cc_id, ld_id) - if cc_id == 'clang-cl': - # Latest clang-cl tested (7.0) does not write checksums out - self.assertFalse(pe.verify_checksum(), msg=msg) - else: - # Verify that a valid checksum was written by all other compilers - self.assertTrue(pe.verify_checksum(), msg=msg) - - -@unittest.skipUnless(is_osx(), "requires Darwin") -class DarwinTests(BasePlatformTests): - ''' - Tests that should run on macOS - ''' - - def setUp(self): - super().setUp() - self.platform_test_dir = os.path.join(self.src_root, 'test cases/osx') - - def test_apple_bitcode(self): - ''' - Test that -fembed-bitcode is correctly added while compiling and - -bitcode_bundle is added while linking when b_bitcode is true and not - when it is false. This can't be an ordinary test case because we need - to inspect the compiler database. - ''' - testdir = os.path.join(self.platform_test_dir, '7 bitcode') - env = get_fake_env(testdir, self.builddir, self.prefix) - cc = env.detect_c_compiler(MachineChoice.HOST) - if cc.id != 'clang': - raise unittest.SkipTest('Not using Clang on OSX') - # Try with bitcode enabled - out = self.init(testdir, extra_args='-Db_bitcode=true') - # Warning was printed - self.assertRegex(out, 'WARNING:.*b_bitcode') - # Compiler options were added - for compdb in self.get_compdb(): - if 'module' in compdb['file']: - self.assertNotIn('-fembed-bitcode', compdb['command']) - else: - self.assertIn('-fembed-bitcode', compdb['command']) - build_ninja = os.path.join(self.builddir, 'build.ninja') - # Linker options were added - with open(build_ninja, 'r', encoding='utf-8') as f: - contents = f.read() - m = re.search('LINK_ARGS =.*-bitcode_bundle', contents) - self.assertIsNotNone(m, msg=contents) - # Try with bitcode disabled - self.setconf('-Db_bitcode=false') - # Regenerate build - self.build() - for compdb in self.get_compdb(): - self.assertNotIn('-fembed-bitcode', compdb['command']) - build_ninja = os.path.join(self.builddir, 'build.ninja') - with open(build_ninja, 'r', encoding='utf-8') as f: - contents = f.read() - m = re.search('LINK_ARGS =.*-bitcode_bundle', contents) - self.assertIsNone(m, msg=contents) - - def test_apple_bitcode_modules(self): - ''' - Same as above, just for shared_module() - ''' - testdir = os.path.join(self.common_test_dir, '152 shared module resolving symbol in executable') - # Ensure that it builds even with bitcode enabled - self.init(testdir, extra_args='-Db_bitcode=true') - self.build() - self.run_tests() - - def _get_darwin_versions(self, fname): - fname = os.path.join(self.builddir, fname) - out = subprocess.check_output(['otool', '-L', fname], universal_newlines=True) - m = re.match(r'.*version (.*), current version (.*)\)', out.split('\n')[1]) - self.assertIsNotNone(m, msg=out) - return m.groups() - - @skipIfNoPkgconfig - def test_library_versioning(self): - ''' - Ensure that compatibility_version and current_version are set correctly - ''' - testdir = os.path.join(self.platform_test_dir, '2 library versions') - self.init(testdir) - self.build() - targets = {} - for t in self.introspect('--targets'): - targets[t['name']] = t['filename'][0] if isinstance(t['filename'], list) else t['filename'] - self.assertEqual(self._get_darwin_versions(targets['some']), ('7.0.0', '7.0.0')) - self.assertEqual(self._get_darwin_versions(targets['noversion']), ('0.0.0', '0.0.0')) - self.assertEqual(self._get_darwin_versions(targets['onlyversion']), ('1.0.0', '1.0.0')) - self.assertEqual(self._get_darwin_versions(targets['onlysoversion']), ('5.0.0', '5.0.0')) - self.assertEqual(self._get_darwin_versions(targets['intver']), ('2.0.0', '2.0.0')) - self.assertEqual(self._get_darwin_versions(targets['stringver']), ('2.3.0', '2.3.0')) - self.assertEqual(self._get_darwin_versions(targets['stringlistver']), ('2.4.0', '2.4.0')) - self.assertEqual(self._get_darwin_versions(targets['intstringver']), ('1111.0.0', '2.5.0')) - self.assertEqual(self._get_darwin_versions(targets['stringlistvers']), ('2.6.0', '2.6.1')) - - def test_duplicate_rpath(self): - testdir = os.path.join(self.unit_test_dir, '10 build_rpath') - # We purposely pass a duplicate rpath to Meson, in order - # to ascertain that Meson does not call install_name_tool - # with duplicate -delete_rpath arguments, which would - # lead to erroring out on installation - env = {"LDFLAGS": "-Wl,-rpath,/foo/bar"} - self.init(testdir, override_envvars=env) - self.build() - self.install() - - def test_removing_unused_linker_args(self): - testdir = os.path.join(self.common_test_dir, '108 has arg') - env = {'CFLAGS': '-L/tmp -L /var/tmp -headerpad_max_install_names -Wl,-export_dynamic'} - self.init(testdir, override_envvars=env) - - -@unittest.skipUnless(not is_windows(), "requires something Unix-like") -class LinuxlikeTests(BasePlatformTests): - ''' - Tests that should run on Linux, macOS, and *BSD - ''' - - def test_basic_soname(self): - ''' - Test that the soname is set correctly for shared libraries. This can't - be an ordinary test case because we need to run `readelf` and actually - check the soname. - https://github.com/mesonbuild/meson/issues/785 - ''' - testdir = os.path.join(self.common_test_dir, '4 shared') - self.init(testdir) - self.build() - lib1 = os.path.join(self.builddir, 'libmylib.so') - soname = get_soname(lib1) - self.assertEqual(soname, 'libmylib.so') - - def test_custom_soname(self): - ''' - Test that the soname is set correctly for shared libraries when - a custom prefix and/or suffix is used. This can't be an ordinary test - case because we need to run `readelf` and actually check the soname. - https://github.com/mesonbuild/meson/issues/785 - ''' - testdir = os.path.join(self.common_test_dir, '25 library versions') - self.init(testdir) - self.build() - lib1 = os.path.join(self.builddir, 'prefixsomelib.suffix') - soname = get_soname(lib1) - self.assertEqual(soname, 'prefixsomelib.suffix') - - def test_pic(self): - ''' - Test that -fPIC is correctly added to static libraries when b_staticpic - is true and not when it is false. This can't be an ordinary test case - because we need to inspect the compiler database. - ''' - if is_windows() or is_cygwin() or is_osx(): - raise unittest.SkipTest('PIC not relevant') - - testdir = os.path.join(self.common_test_dir, '3 static') - self.init(testdir) - compdb = self.get_compdb() - self.assertIn('-fPIC', compdb[0]['command']) - self.setconf('-Db_staticpic=false') - # Regenerate build - self.build() - compdb = self.get_compdb() - self.assertNotIn('-fPIC', compdb[0]['command']) - - def test_pkgconfig_gen(self): - ''' - Test that generated pkg-config files can be found and have the correct - version and link args. This can't be an ordinary test case because we - need to run pkg-config outside of a Meson build file. - https://github.com/mesonbuild/meson/issues/889 - ''' - testdir = os.path.join(self.common_test_dir, '47 pkgconfig-gen') - self.init(testdir) - env = get_fake_env(testdir, self.builddir, self.prefix) - kwargs = {'required': True, 'silent': True} - os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir - foo_dep = PkgConfigDependency('libfoo', env, kwargs) - 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') - - def test_pkgconfig_gen_deps(self): - ''' - Test that generated pkg-config files correctly handle dependencies - ''' - testdir = os.path.join(self.common_test_dir, '47 pkgconfig-gen') - self.init(testdir) - privatedir1 = self.privatedir - - self.new_builddir() - testdir = os.path.join(self.common_test_dir, '47 pkgconfig-gen', 'dependencies') - self.init(testdir, override_envvars={'PKG_CONFIG_LIBDIR': privatedir1}) - privatedir2 = self.privatedir - - os.environ - env = { - 'PKG_CONFIG_LIBDIR': os.pathsep.join([privatedir1, privatedir2]), - 'PKG_CONFIG_SYSTEM_LIBRARY_PATH': '/usr/lib', - } - self._run(['pkg-config', 'dependency-test', '--validate'], override_envvars=env) - - # pkg-config strips some duplicated flags so we have to parse the - # generated file ourself. - expected = { - 'Requires': 'libexposed', - 'Requires.private': 'libfoo >= 1.0', - 'Libs': '-L${libdir} -llibmain -pthread -lcustom', - 'Libs.private': '-lcustom2 -L${libdir} -llibinternal', - 'Cflags': '-I${includedir} -pthread -DCUSTOM', - } - if is_osx() or is_haiku(): - expected['Cflags'] = expected['Cflags'].replace('-pthread ', '') - with open(os.path.join(privatedir2, 'dependency-test.pc')) as f: - matched_lines = 0 - for line in f: - parts = line.split(':', 1) - if parts[0] in expected: - key = parts[0] - val = parts[1].strip() - expected_val = expected[key] - self.assertEqual(expected_val, val) - matched_lines += 1 - self.assertEqual(len(expected), matched_lines) - - cmd = ['pkg-config', 'requires-test'] - out = self._run(cmd + ['--print-requires'], override_envvars=env).strip().split('\n') - if not is_openbsd(): - self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello'])) - else: - self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello'])) - - cmd = ['pkg-config', 'requires-private-test'] - out = self._run(cmd + ['--print-requires-private'], override_envvars=env).strip().split('\n') - if not is_openbsd(): - self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello'])) - else: - self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello'])) - - cmd = ['pkg-config', 'pub-lib-order'] - out = self._run(cmd + ['--libs'], override_envvars=env).strip().split() - self.assertEqual(out, ['-llibmain2', '-llibinternal']) - - def test_pkg_unfound(self): - testdir = os.path.join(self.unit_test_dir, '23 unfound pkgconfig') - self.init(testdir) - with open(os.path.join(self.privatedir, 'somename.pc')) as f: - pcfile = f.read() - self.assertFalse('blub_blob_blib' in pcfile) - - def test_vala_c_warnings(self): - ''' - Test that no warnings are emitted for C code generated by Vala. This - can't be an ordinary test case because we need to inspect the compiler - database. - https://github.com/mesonbuild/meson/issues/864 - ''' - if not shutil.which('valac'): - raise unittest.SkipTest('valac not installed.') - testdir = os.path.join(self.vala_test_dir, '5 target glib') - self.init(testdir) - compdb = self.get_compdb() - vala_command = None - c_command = None - for each in compdb: - if each['file'].endswith('GLib.Thread.c'): - vala_command = each['command'] - elif each['file'].endswith('GLib.Thread.vala'): - continue - elif each['file'].endswith('retcode.c'): - c_command = each['command'] - else: - m = 'Unknown file {!r} in vala_c_warnings test'.format(each['file']) - raise AssertionError(m) - self.assertIsNotNone(vala_command) - self.assertIsNotNone(c_command) - # -w suppresses all warnings, should be there in Vala but not in C - self.assertIn(" -w ", vala_command) - self.assertNotIn(" -w ", c_command) - # -Wall enables all warnings, should be there in C but not in Vala - self.assertNotIn(" -Wall ", vala_command) - self.assertIn(" -Wall ", c_command) - # -Werror converts warnings to errors, should always be there since it's - # injected by an unrelated piece of code and the project has werror=true - self.assertIn(" -Werror ", vala_command) - self.assertIn(" -Werror ", c_command) - - @skipIfNoPkgconfig - def test_qtdependency_pkgconfig_detection(self): - ''' - Test that qt4 and qt5 detection with pkgconfig works. - ''' - # Verify Qt4 or Qt5 can be found with pkg-config - qt4 = subprocess.call(['pkg-config', '--exists', 'QtCore']) - qt5 = subprocess.call(['pkg-config', '--exists', 'Qt5Core']) - testdir = os.path.join(self.framework_test_dir, '4 qt') - self.init(testdir, extra_args=['-Dmethod=pkg-config']) - # Confirm that the dependency was found with pkg-config - mesonlog = self.get_meson_log() - if qt4 == 0: - self.assertRegex('\n'.join(mesonlog), - r'Run-time dependency qt4 \(modules: Core\) found: YES 4.* \(pkg-config\)\n') - if qt5 == 0: - self.assertRegex('\n'.join(mesonlog), - r'Run-time dependency qt5 \(modules: Core\) found: YES 5.* \(pkg-config\)\n') - - @skip_if_not_base_option('b_sanitize') - def test_generate_gir_with_address_sanitizer(self): - if is_cygwin(): - raise unittest.SkipTest('asan not available on Cygwin') - if is_openbsd(): - raise unittest.SkipTest('-fsanitize=address is not supported on OpenBSD') - - testdir = os.path.join(self.framework_test_dir, '7 gnome') - self.init(testdir, extra_args=['-Db_sanitize=address', '-Db_lundef=false']) - self.build() - - def test_qt5dependency_qmake_detection(self): - ''' - Test that qt5 detection with qmake works. This can't be an ordinary - test case because it involves setting the environment. - ''' - # Verify that qmake is for Qt5 - if not shutil.which('qmake-qt5'): - if not shutil.which('qmake'): - raise unittest.SkipTest('QMake not found') - output = subprocess.getoutput('qmake --version') - if 'Qt version 5' not in output: - raise unittest.SkipTest('Qmake found, but it is not for Qt 5.') - # Disable pkg-config codepath and force searching with qmake/qmake-qt5 - testdir = os.path.join(self.framework_test_dir, '4 qt') - self.init(testdir, extra_args=['-Dmethod=qmake']) - # Confirm that the dependency was found with qmake - mesonlog = self.get_meson_log() - self.assertRegex('\n'.join(mesonlog), - r'Run-time dependency qt5 \(modules: Core\) found: YES .* \((qmake|qmake-qt5)\)\n') - - def _test_soname_impl(self, libpath, install): - if is_cygwin() or is_osx(): - raise unittest.SkipTest('Test only applicable to ELF and linuxlike sonames') - - testdir = os.path.join(self.unit_test_dir, '1 soname') - self.init(testdir) - self.build() - if install: - self.install() - - # File without aliases set. - nover = os.path.join(libpath, 'libnover.so') - self.assertPathExists(nover) - self.assertFalse(os.path.islink(nover)) - self.assertEqual(get_soname(nover), 'libnover.so') - self.assertEqual(len(glob(nover[:-3] + '*')), 1) - - # File with version set - verset = os.path.join(libpath, 'libverset.so') - self.assertPathExists(verset + '.4.5.6') - self.assertEqual(os.readlink(verset), 'libverset.so.4') - self.assertEqual(get_soname(verset), 'libverset.so.4') - self.assertEqual(len(glob(verset[:-3] + '*')), 3) - - # File with soversion set - soverset = os.path.join(libpath, 'libsoverset.so') - self.assertPathExists(soverset + '.1.2.3') - self.assertEqual(os.readlink(soverset), 'libsoverset.so.1.2.3') - self.assertEqual(get_soname(soverset), 'libsoverset.so.1.2.3') - self.assertEqual(len(glob(soverset[:-3] + '*')), 2) - - # File with version and soversion set to same values - settosame = os.path.join(libpath, 'libsettosame.so') - self.assertPathExists(settosame + '.7.8.9') - self.assertEqual(os.readlink(settosame), 'libsettosame.so.7.8.9') - self.assertEqual(get_soname(settosame), 'libsettosame.so.7.8.9') - self.assertEqual(len(glob(settosame[:-3] + '*')), 2) - - # File with version and soversion set to different values - bothset = os.path.join(libpath, 'libbothset.so') - self.assertPathExists(bothset + '.1.2.3') - self.assertEqual(os.readlink(bothset), 'libbothset.so.1.2.3') - self.assertEqual(os.readlink(bothset + '.1.2.3'), 'libbothset.so.4.5.6') - self.assertEqual(get_soname(bothset), 'libbothset.so.1.2.3') - self.assertEqual(len(glob(bothset[:-3] + '*')), 3) - - def test_soname(self): - self._test_soname_impl(self.builddir, False) - - def test_installed_soname(self): - libdir = self.installdir + os.path.join(self.prefix, self.libdir) - self._test_soname_impl(libdir, True) - - def test_compiler_check_flags_order(self): - ''' - Test that compiler check flags override all other flags. This can't be - an ordinary test case because it needs the environment to be set. - ''' - testdir = os.path.join(self.common_test_dir, '39 has function') - env = get_fake_env(testdir, self.builddir, self.prefix) - cpp = env.detect_cpp_compiler(MachineChoice.HOST) - Oflag = '-O3' - OflagCPP = Oflag - if cpp.get_id() in ('clang', 'gcc'): - # prevent developers from adding "int main(int argc, char **argv)" - # to small Meson checks unless these parameters are actually used - OflagCPP += ' -Werror=unused-parameter' - env = {'CFLAGS': Oflag, - 'CXXFLAGS': OflagCPP} - self.init(testdir, override_envvars=env) - cmds = self.get_meson_log_compiler_checks() - for cmd in cmds: - if cmd[0] == 'ccache': - cmd = cmd[1:] - # Verify that -I flags from the `args` kwarg are first - # This is set in the '39 has function' test case - self.assertEqual(cmd[1], '-I/tmp') - # Verify that -O3 set via the environment is overridden by -O0 - Oargs = [arg for arg in cmd if arg.startswith('-O')] - self.assertEqual(Oargs, [Oflag, '-O0']) - - def _test_stds_impl(self, testdir, compiler, p: str): - lang_std = p + '_std' - - has_cpp17 = (compiler.get_id() not in {'clang', 'gcc'} or - compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=5.0.0', '>=9.1') or - compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=5.0.0')) - has_cpp2a_c17 = (compiler.get_id() not in {'clang', 'gcc'} or - compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=6.0.0', '>=10.0') or - compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=8.0.0')) - has_c18 = (compiler.get_id() not in {'clang', 'gcc'} or - compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=8.0.0', '>=11.0') or - compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=8.0.0')) - # Check that all the listed -std=xxx options for this compiler work just fine when used - # https://en.wikipedia.org/wiki/Xcode#Latest_versions - # https://www.gnu.org/software/gcc/projects/cxx-status.html - for v in compiler.get_options()[lang_std].choices: - # we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly - # thus, C++ first - if '++17' in v and not has_cpp17: - continue - elif '++2a' in v and not has_cpp2a_c17: # https://en.cppreference.com/w/cpp/compiler_support - continue - # now C - elif '17' in v and not has_cpp2a_c17: - continue - elif '18' in v and not has_c18: - continue - std_opt = '{}={}'.format(lang_std, v) - self.init(testdir, extra_args=['-D' + std_opt]) - cmd = self.get_compdb()[0]['command'] - # c++03 and gnu++03 are not understood by ICC, don't try to look for them - skiplist = frozenset([ - ('intel', 'c++03'), - ('intel', 'gnu++03')]) - if v != 'none' and not (compiler.get_id(), v) in skiplist: - cmd_std = " -std={} ".format(v) - self.assertIn(cmd_std, cmd) - try: - self.build() - except Exception: - print('{} was {!r}'.format(lang_std, v)) - raise - self.wipe() - # Check that an invalid std option in CFLAGS/CPPFLAGS fails - # Needed because by default ICC ignores invalid options - cmd_std = '-std=FAIL' - if p == 'c': - env_flag_name = 'CFLAGS' - elif p == 'cpp': - env_flag_name = 'CXXFLAGS' - else: - raise NotImplementedError('Language {} not defined.'.format(p)) - env = {} - env[env_flag_name] = cmd_std - with self.assertRaises((subprocess.CalledProcessError, mesonbuild.mesonlib.EnvironmentException), - msg='C compiler should have failed with -std=FAIL'): - self.init(testdir, override_envvars = env) - # ICC won't fail in the above because additional flags are needed to - # make unknown -std=... options errors. - self.build() - - def test_compiler_c_stds(self): - ''' - Test that C stds specified for this compiler can all be used. Can't be - an ordinary test because it requires passing options to meson. - ''' - testdir = os.path.join(self.common_test_dir, '1 trivial') - env = get_fake_env(testdir, self.builddir, self.prefix) - cc = env.detect_c_compiler(MachineChoice.HOST) - self._test_stds_impl(testdir, cc, 'c') - - def test_compiler_cpp_stds(self): - ''' - Test that C++ stds specified for this compiler can all be used. Can't - be an ordinary test because it requires passing options to meson. - ''' - testdir = os.path.join(self.common_test_dir, '2 cpp') - env = get_fake_env(testdir, self.builddir, self.prefix) - cpp = env.detect_cpp_compiler(MachineChoice.HOST) - self._test_stds_impl(testdir, cpp, 'cpp') - - def test_unity_subproj(self): - testdir = os.path.join(self.common_test_dir, '45 subproject') - self.init(testdir, extra_args='--unity=subprojects') - simpletest_id = Target.construct_id_from_path('subprojects/sublib', 'simpletest', '@exe') - self.assertPathExists(os.path.join(self.builddir, 'subprojects/sublib', simpletest_id, 'simpletest-unity.c')) - sublib_id = Target.construct_id_from_path('subprojects/sublib', 'sublib', '@sha') - self.assertPathExists(os.path.join(self.builddir, 'subprojects/sublib', sublib_id, 'sublib-unity.c')) - self.assertPathDoesNotExist(os.path.join(self.builddir, 'user@exe/user-unity.c')) - self.build() - - def test_installed_modes(self): - ''' - Test that files installed by these tests have the correct permissions. - Can't be an ordinary test because our installed_files.txt is very basic. - ''' - # Test file modes - testdir = os.path.join(self.common_test_dir, '12 data') - self.init(testdir) - self.install() - - f = os.path.join(self.installdir, 'etc', 'etcfile.dat') - found_mode = stat.filemode(os.stat(f).st_mode) - want_mode = 'rw------T' - self.assertEqual(want_mode, found_mode[1:]) - - f = os.path.join(self.installdir, 'usr', 'bin', 'runscript.sh') - statf = os.stat(f) - found_mode = stat.filemode(statf.st_mode) - want_mode = 'rwxr-sr-x' - self.assertEqual(want_mode, found_mode[1:]) - if os.getuid() == 0: - # The chown failed nonfatally if we're not root - self.assertEqual(0, statf.st_uid) - self.assertEqual(0, statf.st_gid) - - f = os.path.join(self.installdir, 'usr', 'share', 'progname', - 'fileobject_datafile.dat') - orig = os.path.join(testdir, 'fileobject_datafile.dat') - statf = os.stat(f) - statorig = os.stat(orig) - found_mode = stat.filemode(statf.st_mode) - orig_mode = stat.filemode(statorig.st_mode) - self.assertEqual(orig_mode[1:], found_mode[1:]) - self.assertEqual(os.getuid(), statf.st_uid) - if os.getuid() == 0: - # The chown failed nonfatally if we're not root - self.assertEqual(0, statf.st_gid) - - self.wipe() - # Test directory modes - testdir = os.path.join(self.common_test_dir, '62 install subdir') - self.init(testdir) - self.install() - - f = os.path.join(self.installdir, 'usr', 'share', 'sub1', 'second.dat') - statf = os.stat(f) - found_mode = stat.filemode(statf.st_mode) - want_mode = 'rwxr-x--t' - self.assertEqual(want_mode, found_mode[1:]) - if os.getuid() == 0: - # The chown failed nonfatally if we're not root - self.assertEqual(0, statf.st_uid) - - def test_installed_modes_extended(self): - ''' - Test that files are installed with correct permissions using install_mode. - ''' - testdir = os.path.join(self.common_test_dir, '195 install_mode') - self.init(testdir) - self.build() - self.install() - - for fsobj, want_mode in [ - ('bin', 'drwxr-x---'), - ('bin/runscript.sh', '-rwxr-sr-x'), - ('bin/trivialprog', '-rwxr-sr-x'), - ('include', 'drwxr-x---'), - ('include/config.h', '-rw-rwSr--'), - ('include/rootdir.h', '-r--r--r-T'), - ('lib', 'drwxr-x---'), - ('lib/libstat.a', '-rw---Sr--'), - ('share', 'drwxr-x---'), - ('share/man', 'drwxr-x---'), - ('share/man/man1', 'drwxr-x---'), - ('share/man/man1/foo.1', '-r--r--r-T'), - ('share/sub1', 'drwxr-x---'), - ('share/sub1/second.dat', '-rwxr-x--t'), - ('subdir', 'drwxr-x---'), - ('subdir/data.dat', '-rw-rwSr--'), - ]: - f = os.path.join(self.installdir, 'usr', *fsobj.split('/')) - found_mode = stat.filemode(os.stat(f).st_mode) - self.assertEqual(want_mode, found_mode, - msg=('Expected file %s to have mode %s but found %s instead.' % - (fsobj, want_mode, found_mode))) - # Ensure that introspect --installed works on all types of files - # FIXME: also verify the files list - self.introspect('--installed') - - def test_install_umask(self): - ''' - Test that files are installed with correct permissions using default - install umask of 022, regardless of the umask at time the worktree - was checked out or the build was executed. - ''' - # Copy source tree to a temporary directory and change permissions - # there to simulate a checkout with umask 002. - orig_testdir = os.path.join(self.unit_test_dir, '26 install umask') - # Create a new testdir under tmpdir. - tmpdir = os.path.realpath(tempfile.mkdtemp()) - self.addCleanup(windows_proof_rmtree, tmpdir) - testdir = os.path.join(tmpdir, '26 install umask') - # Copy the tree using shutil.copyfile, which will use the current umask - # instead of preserving permissions of the old tree. - save_umask = os.umask(0o002) - self.addCleanup(os.umask, save_umask) - shutil.copytree(orig_testdir, testdir, copy_function=shutil.copyfile) - # Preserve the executable status of subdir/sayhello though. - os.chmod(os.path.join(testdir, 'subdir', 'sayhello'), 0o775) - self.init(testdir) - # Run the build under a 027 umask now. - os.umask(0o027) - self.build() - # And keep umask 027 for the install step too. - self.install() - - for executable in [ - 'bin/prog', - 'share/subdir/sayhello', - ]: - f = os.path.join(self.installdir, 'usr', *executable.split('/')) - found_mode = stat.filemode(os.stat(f).st_mode) - want_mode = '-rwxr-xr-x' - self.assertEqual(want_mode, found_mode, - msg=('Expected file %s to have mode %s but found %s instead.' % - (executable, want_mode, found_mode))) - - for directory in [ - 'usr', - 'usr/bin', - 'usr/include', - 'usr/share', - 'usr/share/man', - 'usr/share/man/man1', - 'usr/share/subdir', - ]: - f = os.path.join(self.installdir, *directory.split('/')) - found_mode = stat.filemode(os.stat(f).st_mode) - want_mode = 'drwxr-xr-x' - self.assertEqual(want_mode, found_mode, - msg=('Expected directory %s to have mode %s but found %s instead.' % - (directory, want_mode, found_mode))) - - for datafile in [ - 'include/sample.h', - 'share/datafile.cat', - 'share/file.dat', - 'share/man/man1/prog.1', - 'share/subdir/datafile.dog', - ]: - f = os.path.join(self.installdir, 'usr', *datafile.split('/')) - found_mode = stat.filemode(os.stat(f).st_mode) - want_mode = '-rw-r--r--' - self.assertEqual(want_mode, found_mode, - msg=('Expected file %s to have mode %s but found %s instead.' % - (datafile, want_mode, found_mode))) - - def test_cpp_std_override(self): - testdir = os.path.join(self.unit_test_dir, '6 std override') - self.init(testdir) - compdb = self.get_compdb() - # Don't try to use -std=c++03 as a check for the - # presence of a compiler flag, as ICC does not - # support it. - for i in compdb: - if 'prog98' in i['file']: - c98_comp = i['command'] - if 'prog11' in i['file']: - c11_comp = i['command'] - if 'progp' in i['file']: - plain_comp = i['command'] - self.assertNotEqual(len(plain_comp), 0) - self.assertIn('-std=c++98', c98_comp) - self.assertNotIn('-std=c++11', c98_comp) - self.assertIn('-std=c++11', c11_comp) - self.assertNotIn('-std=c++98', c11_comp) - self.assertNotIn('-std=c++98', plain_comp) - self.assertNotIn('-std=c++11', plain_comp) - # Now werror - self.assertIn('-Werror', plain_comp) - self.assertNotIn('-Werror', c98_comp) - - def test_run_installed(self): - if is_cygwin() or is_osx(): - raise unittest.SkipTest('LD_LIBRARY_PATH and RPATH not applicable') - - testdir = os.path.join(self.unit_test_dir, '7 run installed') - self.init(testdir) - self.build() - self.install() - installed_exe = os.path.join(self.installdir, 'usr/bin/prog') - installed_libdir = os.path.join(self.installdir, 'usr/foo') - installed_lib = os.path.join(installed_libdir, 'libfoo.so') - self.assertTrue(os.path.isfile(installed_exe)) - self.assertTrue(os.path.isdir(installed_libdir)) - self.assertTrue(os.path.isfile(installed_lib)) - # Must fail when run without LD_LIBRARY_PATH to ensure that - # rpath has been properly stripped rather than pointing to the builddir. - self.assertNotEqual(subprocess.call(installed_exe, stderr=subprocess.DEVNULL), 0) - # When LD_LIBRARY_PATH is set it should start working. - # For some reason setting LD_LIBRARY_PATH in os.environ fails - # when all tests are run (but works when only this test is run), - # but doing this explicitly works. - env = os.environ.copy() - env['LD_LIBRARY_PATH'] = ':'.join([installed_libdir, env.get('LD_LIBRARY_PATH', '')]) - self.assertEqual(subprocess.call(installed_exe, env=env), 0) - # Ensure that introspect --installed works - installed = self.introspect('--installed') - for v in installed.values(): - self.assertTrue('prog' in v or 'foo' in v) - - @skipIfNoPkgconfig - def test_order_of_l_arguments(self): - testdir = os.path.join(self.unit_test_dir, '8 -L -l order') - self.init(testdir, override_envvars={'PKG_CONFIG_PATH': testdir}) - # NOTE: .pc file has -Lfoo -lfoo -Lbar -lbar but pkg-config reorders - # the flags before returning them to -Lfoo -Lbar -lfoo -lbar - # but pkgconf seems to not do that. Sigh. Support both. - expected_order = [('-L/me/first', '-lfoo1'), - ('-L/me/second', '-lfoo2'), - ('-L/me/first', '-L/me/second'), - ('-lfoo1', '-lfoo2'), - ('-L/me/second', '-L/me/third'), - ('-L/me/third', '-L/me/fourth',), - ('-L/me/third', '-lfoo3'), - ('-L/me/fourth', '-lfoo4'), - ('-lfoo3', '-lfoo4'), - ] - with open(os.path.join(self.builddir, 'build.ninja')) as ifile: - for line in ifile: - if expected_order[0][0] in line: - for first, second in expected_order: - self.assertLess(line.index(first), line.index(second)) - return - raise RuntimeError('Linker entries not found in the Ninja file.') - - def test_introspect_dependencies(self): - ''' - Tests that mesonintrospect --dependencies returns expected output. - ''' - testdir = os.path.join(self.framework_test_dir, '7 gnome') - self.init(testdir) - glib_found = False - gobject_found = False - deps = self.introspect('--dependencies') - self.assertIsInstance(deps, list) - for dep in deps: - self.assertIsInstance(dep, dict) - self.assertIn('name', dep) - self.assertIn('compile_args', dep) - self.assertIn('link_args', dep) - if dep['name'] == 'glib-2.0': - glib_found = True - elif dep['name'] == 'gobject-2.0': - gobject_found = True - self.assertTrue(glib_found) - self.assertTrue(gobject_found) - if subprocess.call(['pkg-config', '--exists', 'glib-2.0 >= 2.56.2']) != 0: - raise unittest.SkipTest('glib >= 2.56.2 needed for the rest') - targets = self.introspect('--targets') - docbook_target = None - for t in targets: - if t['name'] == 'generated-gdbus-docbook': - docbook_target = t - break - self.assertIsInstance(docbook_target, dict) - self.assertEqual(os.path.basename(t['filename'][0]), 'generated-gdbus-doc-' + os.path.basename(t['target_sources'][0]['sources'][0])) - - def test_build_rpath(self): - if is_cygwin(): - raise unittest.SkipTest('Windows PE/COFF binaries do not use RPATH') - testdir = os.path.join(self.unit_test_dir, '10 build_rpath') - self.init(testdir) - self.build() - # C program RPATH - build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) - self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') - self.install() - install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog')) - self.assertEqual(install_rpath, '/baz') - # C++ program RPATH - build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx')) - self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') - self.install() - install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx')) - self.assertEqual(install_rpath, 'baz') - - @skip_if_not_base_option('b_sanitize') - def test_pch_with_address_sanitizer(self): - if is_cygwin(): - raise unittest.SkipTest('asan not available on Cygwin') - if is_openbsd(): - raise unittest.SkipTest('-fsanitize=address is not supported on OpenBSD') - - testdir = os.path.join(self.common_test_dir, '13 pch') - self.init(testdir, extra_args=['-Db_sanitize=address', '-Db_lundef=false']) - self.build() - compdb = self.get_compdb() - for i in compdb: - self.assertIn("-fsanitize=address", i["command"]) - - def test_coverage(self): - gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() - if not gcovr_exe: - raise unittest.SkipTest('gcovr not found') - if not shutil.which('genhtml') and not gcovr_new_rootdir: - raise unittest.SkipTest('genhtml not found and gcovr is too old') - if 'clang' in os.environ.get('CC', ''): - # We need to use llvm-cov instead of gcovr with clang - raise unittest.SkipTest('Coverage does not work with clang right now, help wanted!') - testdir = os.path.join(self.common_test_dir, '1 trivial') - self.init(testdir, extra_args=['-Db_coverage=true']) - self.build() - self.run_tests() - self.run_target('coverage-html') - - def test_cross_find_program(self): - testdir = os.path.join(self.unit_test_dir, '11 cross prog') - crossfile = tempfile.NamedTemporaryFile(mode='w') - print(os.path.join(testdir, 'some_cross_tool.py')) - crossfile.write(textwrap.dedent('''\ - [binaries] - c = '/usr/bin/{1}' - ar = '/usr/bin/ar' - strip = '/usr/bin/ar' - sometool.py = ['{0}'] - someothertool.py = '{0}' - - [properties] - - [host_machine] - system = 'linux' - cpu_family = 'arm' - cpu = 'armv7' # Not sure if correct. - endian = 'little' - ''').format(os.path.join(testdir, 'some_cross_tool.py'), - 'gcc' if is_sunos() else 'cc')) - crossfile.flush() - self.meson_cross_file = crossfile.name - self.init(testdir) - - def test_reconfigure(self): - testdir = os.path.join(self.unit_test_dir, '13 reconfigure') - self.init(testdir, extra_args=['-Db_coverage=true'], default_args=False) - self.build('reconfigure') - - def test_vala_generated_source_buildir_inside_source_tree(self): - ''' - Test that valac outputs generated C files in the expected location when - the builddir is a subdir of the source tree. - ''' - if not shutil.which('valac'): - raise unittest.SkipTest('valac not installed.') - - testdir = os.path.join(self.vala_test_dir, '8 generated sources') - newdir = os.path.join(self.builddir, 'srctree') - shutil.copytree(testdir, newdir) - testdir = newdir - # New builddir - builddir = os.path.join(testdir, 'subdir/_build') - os.makedirs(builddir, exist_ok=True) - self.change_builddir(builddir) - self.init(testdir) - self.build() - - def test_old_gnome_module_codepaths(self): - ''' - A lot of code in the GNOME module is conditional on the version of the - glib tools that are installed, and breakages in the old code can slip - by once the CI has a newer glib version. So we force the GNOME module - to pretend that it's running on an ancient glib so the fallback code is - also tested. - ''' - testdir = os.path.join(self.framework_test_dir, '7 gnome') - mesonbuild.modules.gnome.native_glib_version = '2.20' - env = {'MESON_UNIT_TEST_PRETEND_GLIB_OLD': "1"} - try: - self.init(testdir, - inprocess=True, - override_envvars=env) - self.build(override_envvars=env) - finally: - mesonbuild.modules.gnome.native_glib_version = None - - @skipIfNoPkgconfig - def test_pkgconfig_usage(self): - testdir1 = os.path.join(self.unit_test_dir, '27 pkgconfig usage/dependency') - testdir2 = os.path.join(self.unit_test_dir, '27 pkgconfig usage/dependee') - if subprocess.call(['pkg-config', '--cflags', 'glib-2.0'], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) != 0: - raise unittest.SkipTest('Glib 2.0 dependency not available.') - with tempfile.TemporaryDirectory() as tempdirname: - self.init(testdir1, extra_args=['--prefix=' + tempdirname, '--libdir=lib'], default_args=False) - self.install(use_destdir=False) - shutil.rmtree(self.builddir) - os.mkdir(self.builddir) - pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig') - self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'libpkgdep.pc'))) - lib_dir = os.path.join(tempdirname, 'lib') - myenv = os.environ.copy() - myenv['PKG_CONFIG_PATH'] = pkg_dir - # Private internal libraries must not leak out. - pkg_out = subprocess.check_output(['pkg-config', '--static', '--libs', 'libpkgdep'], env=myenv) - self.assertFalse(b'libpkgdep-int' in pkg_out, 'Internal library leaked out.') - # Dependencies must not leak to cflags when building only a shared library. - pkg_out = subprocess.check_output(['pkg-config', '--cflags', 'libpkgdep'], env=myenv) - self.assertFalse(b'glib' in pkg_out, 'Internal dependency leaked to headers.') - # Test that the result is usable. - self.init(testdir2, override_envvars=myenv) - self.build(override_envvars=myenv) - myenv = os.environ.copy() - myenv['LD_LIBRARY_PATH'] = ':'.join([lib_dir, myenv.get('LD_LIBRARY_PATH', '')]) - if is_cygwin(): - bin_dir = os.path.join(tempdirname, 'bin') - myenv['PATH'] = bin_dir + os.pathsep + myenv['PATH'] - self.assertTrue(os.path.isdir(lib_dir)) - test_exe = os.path.join(self.builddir, 'pkguser') - self.assertTrue(os.path.isfile(test_exe)) - subprocess.check_call(test_exe, env=myenv) - - @skipIfNoPkgconfig - def test_pkgconfig_relative_paths(self): - testdir = os.path.join(self.unit_test_dir, '62 pkgconfig relative paths') - pkg_dir = os.path.join(testdir, 'pkgconfig') - self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'librelativepath.pc'))) - - env = get_fake_env(testdir, self.builddir, self.prefix) - env.coredata.set_options({'pkg_config_path': pkg_dir}, subproject='') - kwargs = {'required': True, 'silent': True} - relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs) - self.assertTrue(relative_path_dep.found()) - - # Ensure link_args are properly quoted - libpath = Path(self.builddir) / '../relativepath/lib' - link_args = ['-L' + libpath.as_posix(), '-lrelativepath'] - self.assertEqual(relative_path_dep.get_link_args(), link_args) - - @skipIfNoPkgconfig - def test_pkgconfig_internal_libraries(self): - ''' - ''' - with tempfile.TemporaryDirectory() as tempdirname: - # build library - testdirbase = os.path.join(self.unit_test_dir, '32 pkgconfig use libraries') - testdirlib = os.path.join(testdirbase, 'lib') - self.init(testdirlib, extra_args=['--prefix=' + tempdirname, - '--libdir=lib', - '--default-library=static'], default_args=False) - self.build() - self.install(use_destdir=False) - - # build user of library - pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig') - self.new_builddir() - self.init(os.path.join(testdirbase, 'app'), - override_envvars={'PKG_CONFIG_PATH': pkg_dir}) - self.build() - - @skipIfNoPkgconfig - def test_static_archive_stripping(self): - ''' - Check that Meson produces valid static archives with --strip enabled - ''' - with tempfile.TemporaryDirectory() as tempdirname: - testdirbase = os.path.join(self.unit_test_dir, '68 static archive stripping') - - # build lib - self.new_builddir() - testdirlib = os.path.join(testdirbase, 'lib') - testlibprefix = os.path.join(tempdirname, 'libprefix') - self.init(testdirlib, extra_args=['--prefix=' + testlibprefix, - '--libdir=lib', - '--default-library=static', - '--buildtype=debug', - '--strip'], default_args=False) - self.build() - self.install(use_destdir=False) - - # build executable (uses lib, fails if static archive has been stripped incorrectly) - pkg_dir = os.path.join(testlibprefix, 'lib/pkgconfig') - self.new_builddir() - self.init(os.path.join(testdirbase, 'app'), - override_envvars={'PKG_CONFIG_PATH': pkg_dir}) - self.build() - - @skipIfNoPkgconfig - def test_pkgconfig_formatting(self): - testdir = os.path.join(self.unit_test_dir, '38 pkgconfig format') - self.init(testdir) - myenv = os.environ.copy() - myenv['PKG_CONFIG_PATH'] = self.privatedir - stdo = subprocess.check_output(['pkg-config', '--libs-only-l', 'libsomething'], env=myenv) - deps = [b'-lgobject-2.0', b'-lgio-2.0', b'-lglib-2.0', b'-lsomething'] - if is_windows() or is_cygwin() or is_osx() or is_openbsd(): - # On Windows, libintl is a separate library - deps.append(b'-lintl') - self.assertEqual(set(deps), set(stdo.split())) - - @skipIfNoPkgconfig - @skip_if_not_language('cs') - def test_pkgconfig_csharp_library(self): - testdir = os.path.join(self.unit_test_dir, '50 pkgconfig csharp library') - self.init(testdir) - myenv = os.environ.copy() - myenv['PKG_CONFIG_PATH'] = self.privatedir - stdo = subprocess.check_output(['pkg-config', '--libs', 'libsomething'], env=myenv) - - self.assertEqual("-r/usr/lib/libsomething.dll", str(stdo.decode('ascii')).strip()) - - @skipIfNoPkgconfig - def test_pkgconfig_link_order(self): - ''' - Test that libraries are listed before their dependencies. - ''' - testdir = os.path.join(self.unit_test_dir, '53 pkgconfig static link order') - self.init(testdir) - myenv = os.environ.copy() - myenv['PKG_CONFIG_PATH'] = self.privatedir - stdo = subprocess.check_output(['pkg-config', '--libs', 'libsomething'], env=myenv) - deps = stdo.split() - self.assertTrue(deps.index(b'-lsomething') < deps.index(b'-ldependency')) - - def test_deterministic_dep_order(self): - ''' - Test that the dependencies are always listed in a deterministic order. - ''' - testdir = os.path.join(self.unit_test_dir, '43 dep order') - self.init(testdir) - with open(os.path.join(self.builddir, 'build.ninja')) as bfile: - for line in bfile: - if 'build myexe:' in line or 'build myexe.exe:' in line: - self.assertIn('liblib1.a liblib2.a', line) - return - raise RuntimeError('Could not find the build rule') - - def test_deterministic_rpath_order(self): - ''' - Test that the rpaths are always listed in a deterministic order. - ''' - if is_cygwin(): - raise unittest.SkipTest('rpath are not used on Cygwin') - testdir = os.path.join(self.unit_test_dir, '42 rpath order') - self.init(testdir) - if is_osx(): - rpathre = re.compile(r'-rpath,.*/subprojects/sub1.*-rpath,.*/subprojects/sub2') - else: - rpathre = re.compile(r'-rpath,\$\$ORIGIN/subprojects/sub1:\$\$ORIGIN/subprojects/sub2') - with open(os.path.join(self.builddir, 'build.ninja')) as bfile: - for line in bfile: - if '-rpath' in line: - self.assertRegex(line, rpathre) - return - raise RuntimeError('Could not find the rpath') - - def test_override_with_exe_dep(self): - ''' - Test that we produce the correct dependencies when a program is overridden with an executable. - ''' - testdir = os.path.join(self.common_test_dir, '201 override with exe') - self.init(testdir) - with open(os.path.join(self.builddir, 'build.ninja')) as bfile: - for line in bfile: - if 'main1.c:' in line or 'main2.c:' in line: - self.assertIn('| subprojects/sub/foobar', line) - - @skipIfNoPkgconfig - def test_usage_external_library(self): - ''' - Test that uninstalled usage of an external library (from the system or - PkgConfigDependency) works. On macOS, this workflow works out of the - box. On Linux, BSDs, Windows, etc, you need to set extra arguments such - as LD_LIBRARY_PATH, etc, so this test is skipped. - - The system library is found with cc.find_library() and pkg-config deps. - ''' - oldprefix = self.prefix - # Install external library so we can find it - testdir = os.path.join(self.unit_test_dir, '40 external, internal library rpath', 'external library') - # install into installdir without using DESTDIR - installdir = self.installdir - self.prefix = installdir - self.init(testdir) - self.prefix = oldprefix - self.build() - self.install(use_destdir=False) - ## New builddir for the consumer - 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, '40 external, internal library rpath', 'built library') - # install into installdir without using DESTDIR - self.prefix = self.installdir - self.init(testdir, override_envvars=env) - self.prefix = oldprefix - self.build(override_envvars=env) - # test uninstalled - self.run_tests(override_envvars=env) - if not is_osx(): - # Rest of the workflow only works on macOS - return - # test running after installation - self.install(use_destdir=False) - prog = os.path.join(self.installdir, 'bin', 'prog') - self._run([prog]) - out = self._run(['otool', '-L', prog]) - self.assertNotIn('@rpath', out) - ## New builddir for testing that DESTDIR is not added to install_name - self.new_builddir() - # install into installdir with DESTDIR - self.init(testdir, override_envvars=env) - self.build(override_envvars=env) - # test running after installation - self.install(override_envvars=env) - prog = self.installdir + os.path.join(self.prefix, 'bin', 'prog') - lib = self.installdir + os.path.join(self.prefix, 'lib', 'libbar_built.dylib') - for f in prog, lib: - out = self._run(['otool', '-L', f]) - # Ensure that the otool output does not contain self.installdir - self.assertNotRegex(out, self.installdir + '.*dylib ') - - def install_subdir_invalid_symlinks(self, testdir, subdir_path): - ''' - Test that installation of broken symlinks works fine. - https://github.com/mesonbuild/meson/issues/3914 - ''' - testdir = os.path.join(self.common_test_dir, testdir) - subdir = os.path.join(testdir, subdir_path) - curdir = os.getcwd() - os.chdir(subdir) - # Can't distribute broken symlinks in the source tree because it breaks - # the creation of zipapps. Create it dynamically and run the test by - # hand. - src = '../../nonexistent.txt' - os.symlink(src, 'invalid-symlink.txt') - try: - self.init(testdir) - self.build() - self.install() - install_path = subdir_path.split(os.path.sep)[-1] - link = os.path.join(self.installdir, 'usr', 'share', install_path, 'invalid-symlink.txt') - self.assertTrue(os.path.islink(link), msg=link) - self.assertEqual(src, os.readlink(link)) - self.assertFalse(os.path.isfile(link), msg=link) - finally: - os.remove(os.path.join(subdir, 'invalid-symlink.txt')) - os.chdir(curdir) - - def test_install_subdir_symlinks(self): - self.install_subdir_invalid_symlinks('62 install subdir', os.path.join('sub', 'sub1')) - - def test_install_subdir_symlinks_with_default_umask(self): - self.install_subdir_invalid_symlinks('195 install_mode', 'sub2') - - def test_install_subdir_symlinks_with_default_umask_and_mode(self): - self.install_subdir_invalid_symlinks('195 install_mode', 'sub1') - - @skipIfNoPkgconfigDep('gmodule-2.0') - def test_ldflag_dedup(self): - testdir = os.path.join(self.unit_test_dir, '52 ldflagdedup') - if is_cygwin() or is_osx(): - raise unittest.SkipTest('Not applicable on Cygwin or OSX.') - self.init(testdir) - build_ninja = os.path.join(self.builddir, 'build.ninja') - max_count = 0 - search_term = '-Wl,--export-dynamic' - with open(build_ninja, 'r', encoding='utf-8') as f: - for line in f: - max_count = max(max_count, line.count(search_term)) - self.assertEqual(max_count, 1, 'Export dynamic incorrectly deduplicated.') - - def test_compiler_libs_static_dedup(self): - testdir = os.path.join(self.unit_test_dir, '56 dedup compiler libs') - self.init(testdir) - build_ninja = os.path.join(self.builddir, 'build.ninja') - with open(build_ninja, 'r', encoding='utf-8') as f: - lines = f.readlines() - for lib in ('-ldl', '-lm', '-lc', '-lrt'): - for line in lines: - if lib not in line: - continue - # Assert that - self.assertEqual(len(line.split(lib)), 2, msg=(lib, line)) - - @skipIfNoPkgconfig - def test_noncross_options(self): - # C_std defined in project options must be in effect also when native compiling. - testdir = os.path.join(self.unit_test_dir, '51 noncross options') - self.init(testdir, extra_args=['-Dpkg_config_path=' + testdir]) - compdb = self.get_compdb() - self.assertEqual(len(compdb), 2) - self.assertRegex(compdb[0]['command'], '-std=c99') - self.assertRegex(compdb[1]['command'], '-std=c99') - self.build() - - def test_identity_cross(self): - testdir = os.path.join(self.unit_test_dir, '61 identity cross') - crossfile = tempfile.NamedTemporaryFile(mode='w') - env = {'CC': '"' + os.path.join(testdir, 'build_wrapper.py') + '"'} - crossfile.write('''[binaries] -c = ['{0}'] -'''.format(os.path.join(testdir, 'host_wrapper.py'))) - crossfile.flush() - self.meson_cross_file = crossfile.name - # TODO should someday be explicit about build platform only here - self.init(testdir, override_envvars=env) - - @skipIfNoPkgconfig - def test_static_link(self): - if is_cygwin(): - raise unittest.SkipTest("Cygwin doesn't support LD_LIBRARY_PATH.") - - # Build some libraries and install them - testdir = os.path.join(self.unit_test_dir, '69 static link/lib') - libdir = os.path.join(self.installdir, self.libdir) - oldprefix = self.prefix - self.prefix = self.installdir - self.init(testdir) - self.install(use_destdir=False) - - # Test that installed libraries works - self.new_builddir() - self.prefix = oldprefix - meson_args = ['-Dc_link_args=-L{}'.format(libdir), - '--fatal-meson-warnings'] - testdir = os.path.join(self.unit_test_dir, '69 static link') - env = {'PKG_CONFIG_LIBDIR': os.path.join(libdir, 'pkgconfig')} - self.init(testdir, extra_args=meson_args, override_envvars=env) - self.build() - self.run_tests() - - def _check_ld(self, check: str, name: str, lang: str, expected: str) -> None: - if is_sunos(): - raise unittest.SkipTest('Solaris currently cannot override the linker.') - if not shutil.which(check): - raise unittest.SkipTest('Could not find {}.'.format(check)) - envvar = mesonbuild.envconfig.BinaryTable.evarMap['{}_ld'.format(lang)] - with mock.patch.dict(os.environ, {envvar: name}): - env = get_fake_env() - comp = getattr(env, 'detect_{}_compiler'.format(lang))(MachineChoice.HOST) - if lang != 'rust' and comp.use_linker_args('foo') == []: - raise unittest.SkipTest( - 'Compiler {} does not support using alternative linkers'.format(comp.id)) - self.assertEqual(comp.linker.id, expected) - - def test_ld_environment_variable_bfd(self): - self._check_ld('ld.bfd', 'bfd', 'c', 'ld.bfd') - - def test_ld_environment_variable_gold(self): - self._check_ld('ld.gold', 'gold', 'c', 'ld.gold') - - def test_ld_environment_variable_lld(self): - self._check_ld('ld.lld', 'lld', 'c', 'ld.lld') - - @skipIfNoExecutable('rustc') - def test_ld_environment_variable_rust(self): - self._check_ld('ld.gold', 'gold', 'rust', 'ld.gold') - - def test_ld_environment_variable_cpp(self): - self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold') - - def test_ld_environment_variable_objc(self): - self._check_ld('ld.gold', 'gold', 'objc', 'ld.gold') - - def test_ld_environment_variable_objcpp(self): - self._check_ld('ld.gold', 'gold', 'objcpp', 'ld.gold') - - @skipIfNoExecutable('gfortran') - def test_ld_environment_variable_fortran(self): - self._check_ld('ld.gold', 'gold', 'fortran', 'ld.gold') - - def compute_sha256(self, filename): - with open(filename, 'rb') as f: - return hashlib.sha256(f.read()).hexdigest() - - def test_wrap_with_file_url(self): - testdir = os.path.join(self.unit_test_dir, '73 wrap file url') - source_filename = os.path.join(testdir, 'subprojects', 'foo.tar.xz') - patch_filename = os.path.join(testdir, 'subprojects', 'foo-patch.tar.xz') - wrap_filename = os.path.join(testdir, 'subprojects', 'foo.wrap') - source_hash = self.compute_sha256(source_filename) - patch_hash = self.compute_sha256(patch_filename) - wrap = textwrap.dedent("""\ - [wrap-file] - directory = foo - - source_url = file://{} - source_filename = foo.tar.xz - source_hash = {} - - patch_url = file://{} - patch_filename = foo-patch.tar.xz - patch_hash = {} - """.format(source_filename, source_hash, patch_filename, patch_hash)) - with open(wrap_filename, 'w') as f: - f.write(wrap) - self.init(testdir) - self.build() - self.run_tests() - - windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'packagecache')) - windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'foo')) - os.unlink(wrap_filename) - - -def should_run_cross_arm_tests(): - return shutil.which('arm-linux-gnueabihf-gcc') and not platform.machine().lower().startswith('arm') - -@unittest.skipUnless(not is_windows() and should_run_cross_arm_tests(), "requires ability to cross compile to ARM") -class LinuxCrossArmTests(BasePlatformTests): - ''' - Tests that cross-compilation to Linux/ARM works - ''' - - def setUp(self): - super().setUp() - src_root = os.path.dirname(__file__) - self.meson_cross_file = os.path.join(src_root, 'cross', 'ubuntu-armhf.txt') - - def test_cflags_cross_environment_pollution(self): - ''' - Test that the CFLAGS environment variable does not pollute the cross - environment. This can't be an ordinary test case because we need to - inspect the compiler database. - ''' - testdir = os.path.join(self.common_test_dir, '3 static') - self.init(testdir, override_envvars={'CFLAGS': '-DBUILD_ENVIRONMENT_ONLY'}) - compdb = self.get_compdb() - self.assertNotIn('-DBUILD_ENVIRONMENT_ONLY', compdb[0]['command']) - - def test_cross_file_overrides_always_args(self): - ''' - Test that $lang_args in cross files always override get_always_args(). - Needed for overriding the default -D_FILE_OFFSET_BITS=64 on some - architectures such as some Android versions and Raspbian. - https://github.com/mesonbuild/meson/issues/3049 - https://github.com/mesonbuild/meson/issues/3089 - ''' - testdir = os.path.join(self.unit_test_dir, '33 cross file overrides always args') - self.meson_cross_file = os.path.join(testdir, 'ubuntu-armhf-overrides.txt') - self.init(testdir) - compdb = self.get_compdb() - self.assertRegex(compdb[0]['command'], '-D_FILE_OFFSET_BITS=64.*-U_FILE_OFFSET_BITS') - self.build() - - def test_cross_libdir(self): - # When cross compiling "libdir" should default to "lib" - # rather than "lib/x86_64-linux-gnu" or something like that. - testdir = os.path.join(self.common_test_dir, '1 trivial') - self.init(testdir) - for i in self.introspect('--buildoptions'): - if i['name'] == 'libdir': - self.assertEqual(i['value'], 'lib') - return - self.assertTrue(False, 'Option libdir not in introspect data.') - - def test_std_remains(self): - # C_std defined in project options must be in effect also when cross compiling. - testdir = os.path.join(self.unit_test_dir, '51 noncross options') - self.init(testdir) - compdb = self.get_compdb() - self.assertRegex(compdb[0]['command'], '-std=c99') - self.build() - - @skipIfNoPkgconfig - def test_pkg_config_option(self): - if not shutil.which('arm-linux-gnueabihf-pkg-config'): - raise unittest.SkipTest('Cross-pkgconfig not found.') - testdir = os.path.join(self.unit_test_dir, '58 pkg_config_path option') - self.init(testdir, extra_args=[ - '-Dbuild.pkg_config_path=' + os.path.join(testdir, 'build_extra_path'), - '-Dpkg_config_path=' + os.path.join(testdir, 'host_extra_path'), - ]) - - -def should_run_cross_mingw_tests(): - return shutil.which('x86_64-w64-mingw32-gcc') and not (is_windows() or is_cygwin()) - -@unittest.skipUnless(not is_windows() and should_run_cross_mingw_tests(), "requires ability to cross compile with MinGW") -class LinuxCrossMingwTests(BasePlatformTests): - ''' - Tests that cross-compilation to Windows/MinGW works - ''' - - def setUp(self): - super().setUp() - src_root = os.path.dirname(__file__) - self.meson_cross_file = os.path.join(src_root, 'cross', 'linux-mingw-w64-64bit.txt') - - def test_exe_wrapper_behaviour(self): - ''' - Test that an exe wrapper that isn't found doesn't cause compiler sanity - checks and compiler checks to fail, but causes configure to fail if it - requires running a cross-built executable (custom_target or run_target) - and causes the tests to be skipped if they are run. - ''' - testdir = os.path.join(self.unit_test_dir, '36 exe_wrapper behaviour') - # Configures, builds, and tests fine by default - self.init(testdir) - self.build() - self.run_tests() - self.wipe() - os.mkdir(self.builddir) - # Change cross file to use a non-existing exe_wrapper and it should fail - self.meson_cross_file = os.path.join(testdir, 'broken-cross.txt') - # Force tracebacks so we can detect them properly - env = {'MESON_FORCE_BACKTRACE': '1'} - with self.assertRaisesRegex(MesonException, 'exe_wrapper.*target.*use-exe-wrapper'): - # Must run in-process or we'll get a generic CalledProcessError - self.init(testdir, extra_args='-Drun-target=false', - inprocess=True, - override_envvars=env) - with self.assertRaisesRegex(MesonException, 'exe_wrapper.*run target.*run-prog'): - # Must run in-process or we'll get a generic CalledProcessError - self.init(testdir, extra_args='-Dcustom-target=false', - inprocess=True, - override_envvars=env) - self.init(testdir, extra_args=['-Dcustom-target=false', '-Drun-target=false'], - override_envvars=env) - self.build() - with self.assertRaisesRegex(MesonException, 'exe_wrapper.*PATH'): - # Must run in-process or we'll get a generic CalledProcessError - self.run_tests(inprocess=True, override_envvars=env) - - @skipIfNoPkgconfig - def test_cross_pkg_config_option(self): - testdir = os.path.join(self.unit_test_dir, '58 pkg_config_path option') - self.init(testdir, extra_args=[ - '-Dbuild.pkg_config_path=' + os.path.join(testdir, 'build_extra_path'), - '-Dpkg_config_path=' + os.path.join(testdir, 'host_extra_path'), - ]) - - -class PythonTests(BasePlatformTests): - ''' - Tests that verify compilation of python extension modules - ''' - - def test_versions(self): - if self.backend is not Backend.ninja: - raise unittest.SkipTest('Skipping python tests with {} backend'.format(self.backend.name)) - - testdir = os.path.join(self.src_root, 'test cases', 'unit', '39 python extmodule') - - # No python version specified, this will use meson's python - self.init(testdir) - self.build() - self.run_tests() - self.wipe() - - # When specifying a known name, (python2 / python3) the module - # will also try 'python' as a fallback and use it if the major - # version matches - try: - self.init(testdir, extra_args=['-Dpython=python2']) - self.build() - self.run_tests() - except unittest.SkipTest: - # python2 is not necessarily installed on the test machine, - # if it is not, or the python headers can't be found, the test - # will raise MESON_SKIP_TEST, we could check beforehand what version - # of python is available, but it's a bit of a chicken and egg situation, - # as that is the job of the module, so we just ask for forgiveness rather - # than permission. - pass - - self.wipe() - - for py in ('pypy', 'pypy3'): - try: - self.init(testdir, extra_args=['-Dpython=%s' % py]) - except unittest.SkipTest: - # Same as above, pypy2 and pypy3 are not expected to be present - # on the test system, the test project only raises in these cases - continue - - # We have a pypy, this is expected to work - self.build() - self.run_tests() - self.wipe() - - # The test is configured to error out with MESON_SKIP_TEST - # in case it could not find python - with self.assertRaises(unittest.SkipTest): - self.init(testdir, extra_args=['-Dpython=not-python']) - self.wipe() - - # While dir is an external command on both Windows and Linux, - # it certainly isn't python - with self.assertRaises(unittest.SkipTest): - self.init(testdir, extra_args=['-Dpython=dir']) - self.wipe() - - -class RewriterTests(BasePlatformTests): - def setUp(self): - super().setUp() - self.maxDiff = None - - def prime(self, dirname): - copy_tree(os.path.join(self.rewrite_test_dir, dirname), self.builddir) - - def rewrite_raw(self, directory, args): - 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) - print('STDOUT:') - print(p.stdout) - print('STDERR:') - print(p.stderr) - if p.returncode != 0: - if 'MESON_SKIP_TEST' in p.stdout: - raise unittest.SkipTest('Project requested skipping.') - raise subprocess.CalledProcessError(p.returncode, command, output=p.stdout) - if not p.stderr: - return {} - return json.loads(p.stderr) - - def rewrite(self, directory, args): - if isinstance(args, str): - args = [args] - return self.rewrite_raw(directory, ['command'] + args) - - def test_target_source_list(self): - self.prime('1 basic') - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'target': { - 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp']}, - } - } - self.assertDictEqual(out, expected) - - def test_target_add_sources(self): - self.prime('1 basic') - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) - expected = { - 'target': { - 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}, - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['a7.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['a5.cpp', 'fileA.cpp', 'main.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['a5.cpp', 'main.cpp', 'fileA.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['a3.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp', 'a4.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}, - 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}, - } - } - self.assertDictEqual(out, expected) - - # Check the written file - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - self.assertDictEqual(out, expected) - - def test_target_add_sources_abs(self): - self.prime('1 basic') - abs_src = [os.path.join(self.builddir, x) for x in ['a1.cpp', 'a2.cpp', 'a6.cpp']] - add = json.dumps([{"type": "target", "target": "trivialprog1", "operation": "src_add", "sources": abs_src}]) - inf = json.dumps([{"type": "target", "target": "trivialprog1", "operation": "info"}]) - self.rewrite(self.builddir, add) - out = self.rewrite(self.builddir, inf) - expected = {'target': {'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp']}}} - self.assertDictEqual(out, expected) - - def test_target_remove_sources(self): - self.prime('1 basic') - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'rmSrc.json')) - expected = { - 'target': { - 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileC.cpp']}, - 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp']}, - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileC.cpp', 'main.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp']}, - 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp']}, - } - } - self.assertDictEqual(out, expected) - - # Check the written file - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - self.assertDictEqual(out, expected) - - def test_target_subdir(self): - self.prime('2 subdirs') - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) - expected = {'name': 'something', 'sources': ['first.c', 'second.c', 'third.c']} - self.assertDictEqual(list(out['target'].values())[0], expected) - - # Check the written file - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - self.assertDictEqual(list(out['target'].values())[0], expected) - - def test_target_remove(self): - self.prime('1 basic') - self.rewrite(self.builddir, os.path.join(self.builddir, 'rmTgt.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - - expected = { - 'target': { - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp']}, - } - } - self.assertDictEqual(out, expected) - - def test_tatrget_add(self): - self.prime('1 basic') - self.rewrite(self.builddir, os.path.join(self.builddir, 'addTgt.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - - expected = { - 'target': { - 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp']}, - 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp']}, - 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp']}, - 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp']}, - 'trivialprog10@sha': {'name': 'trivialprog10', 'sources': ['new1.cpp', 'new2.cpp']}, - } - } - self.assertDictEqual(out, expected) - - def test_target_remove_subdir(self): - self.prime('2 subdirs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'rmTgt.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - self.assertDictEqual(out, {}) - - def test_target_add_subdir(self): - self.prime('2 subdirs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'addTgt.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = {'name': 'something', 'sources': ['first.c', 'second.c']} - self.assertDictEqual(out['target']['94b671c@@something@exe'], expected) - - def test_target_source_sorting(self): - self.prime('5 sorting') - add_json = json.dumps([{'type': 'target', 'target': 'exe1', 'operation': 'src_add', 'sources': ['a666.c']}]) - inf_json = json.dumps([{'type': 'target', 'target': 'exe1', 'operation': 'info'}]) - out = self.rewrite(self.builddir, add_json) - out = self.rewrite(self.builddir, inf_json) - expected = { - 'target': { - 'exe1@exe': { - 'name': 'exe1', - 'sources': [ - 'aaa/a/a1.c', - 'aaa/b/b1.c', - 'aaa/b/b2.c', - 'aaa/f1.c', - 'aaa/f2.c', - 'aaa/f3.c', - 'bbb/a/b1.c', - 'bbb/b/b2.c', - 'bbb/c1/b5.c', - 'bbb/c2/b7.c', - 'bbb/c10/b6.c', - 'bbb/a4.c', - 'bbb/b3.c', - 'bbb/b4.c', - 'bbb/b5.c', - 'a1.c', - 'a2.c', - 'a3.c', - 'a10.c', - 'a20.c', - 'a30.c', - 'a100.c', - 'a101.c', - 'a110.c', - 'a210.c', - 'a666.c', - 'b1.c', - 'c2.c' - ] - } - } - } - self.assertDictEqual(out, expected) - - def test_target_same_name_skip(self): - self.prime('4 same name targets') - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = {'name': 'myExe', 'sources': ['main.cpp']} - self.assertEqual(len(out['target']), 2) - for val in out['target'].values(): - self.assertDictEqual(expected, val) - - def test_kwargs_info(self): - self.prime('3 kwargs') - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'kwargs': { - 'project#/': {'version': '0.0.1'}, - 'target#tgt1': {'build_by_default': True}, - 'dependency#dep1': {'required': False} - } - } - self.assertDictEqual(out, expected) - - def test_kwargs_set(self): - self.prime('3 kwargs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'set.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'kwargs': { - 'project#/': {'version': '0.0.2', 'meson_version': '0.50.0', 'license': ['GPL', 'MIT']}, - 'target#tgt1': {'build_by_default': False, 'build_rpath': '/usr/local', 'dependencies': 'dep1'}, - 'dependency#dep1': {'required': True, 'method': 'cmake'} - } - } - self.assertDictEqual(out, expected) - - def test_kwargs_add(self): - self.prime('3 kwargs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'add.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'kwargs': { - 'project#/': {'version': '0.0.1', 'license': ['GPL', 'MIT', 'BSD']}, - 'target#tgt1': {'build_by_default': True}, - 'dependency#dep1': {'required': False} - } - } - self.assertDictEqual(out, expected) - - def test_kwargs_remove(self): - self.prime('3 kwargs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'remove.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'kwargs': { - 'project#/': {'version': '0.0.1', 'license': 'GPL'}, - 'target#tgt1': {'build_by_default': True}, - 'dependency#dep1': {'required': False} - } - } - self.assertDictEqual(out, expected) - - def test_kwargs_remove_regex(self): - self.prime('3 kwargs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'remove_regex.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'kwargs': { - 'project#/': {'version': '0.0.1', 'default_options': ['buildtype=release', 'debug=true']}, - 'target#tgt1': {'build_by_default': True}, - 'dependency#dep1': {'required': False} - } - } - self.assertDictEqual(out, expected) - - def test_kwargs_delete(self): - self.prime('3 kwargs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'delete.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'kwargs': { - 'project#/': {}, - 'target#tgt1': {}, - 'dependency#dep1': {'required': False} - } - } - self.assertDictEqual(out, expected) - - def test_default_options_set(self): - self.prime('3 kwargs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'defopts_set.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'kwargs': { - 'project#/': {'version': '0.0.1', 'default_options': ['buildtype=release', 'debug=True', 'cpp_std=c++11']}, - 'target#tgt1': {'build_by_default': True}, - 'dependency#dep1': {'required': False} - } - } - self.assertDictEqual(out, expected) - - def test_default_options_delete(self): - self.prime('3 kwargs') - self.rewrite(self.builddir, os.path.join(self.builddir, 'defopts_delete.json')) - out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) - expected = { - 'kwargs': { - 'project#/': {'version': '0.0.1', 'default_options': ['cpp_std=c++14', 'debug=true']}, - 'target#tgt1': {'build_by_default': True}, - 'dependency#dep1': {'required': False} - } - } - self.assertDictEqual(out, expected) - -class NativeFileTests(BasePlatformTests): - - def setUp(self): - super().setUp() - self.testcase = os.path.join(self.unit_test_dir, '47 native file binary') - self.current_config = 0 - self.current_wrapper = 0 - - def helper_create_native_file(self, values): - """Create a config file as a temporary file. - - values should be a nested dictionary structure of {section: {key: - value}} - """ - filename = os.path.join(self.builddir, 'generated{}.config'.format(self.current_config)) - self.current_config += 1 - with open(filename, 'wt') as f: - for section, entries in values.items(): - f.write('[{}]\n'.format(section)) - for k, v in entries.items(): - f.write("{}='{}'\n".format(k, v)) - return filename - - def helper_create_binary_wrapper(self, binary, dir_=None, extra_args=None, **kwargs): - """Creates a wrapper around a binary that overrides specific values.""" - filename = os.path.join(dir_ or self.builddir, 'binary_wrapper{}.py'.format(self.current_wrapper)) - extra_args = extra_args or {} - self.current_wrapper += 1 - if is_haiku(): - chbang = '#!/bin/env python3' - else: - chbang = '#!/usr/bin/env python3' - - with open(filename, 'wt') as f: - f.write(textwrap.dedent('''\ - {} - import argparse - import subprocess - import sys - - def main(): - parser = argparse.ArgumentParser() - '''.format(chbang))) - for name in chain(extra_args, kwargs): - f.write(' parser.add_argument("-{0}", "--{0}", action="store_true")\n'.format(name)) - f.write(' args, extra_args = parser.parse_known_args()\n') - for name, value in chain(extra_args.items(), kwargs.items()): - f.write(' if args.{}:\n'.format(name)) - f.write(' print("{}", file=sys.{})\n'.format(value, kwargs.get('outfile', 'stdout'))) - f.write(' sys.exit(0)\n') - f.write(textwrap.dedent(''' - ret = subprocess.run( - ["{}"] + extra_args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - print(ret.stdout.decode('utf-8')) - print(ret.stderr.decode('utf-8'), file=sys.stderr) - sys.exit(ret.returncode) - - if __name__ == '__main__': - main() - '''.format(binary))) - - if not is_windows(): - os.chmod(filename, 0o755) - return filename - - # On windows we need yet another level of indirection, as cmd cannot - # invoke python files itself, so instead we generate a .bat file, which - # invokes our python wrapper - batfile = os.path.join(self.builddir, 'binary_wrapper{}.bat'.format(self.current_wrapper)) - with open(batfile, 'wt') as f: - f.write(r'@{} {} %*'.format(sys.executable, filename)) - return batfile - - def helper_for_compiler(self, lang, cb, for_machine = MachineChoice.HOST): - """Helper for generating tests for overriding compilers for langaugages - with more than one implementation, such as C, C++, ObjC, ObjC++, and D. - """ - env = get_fake_env() - getter = getattr(env, 'detect_{}_compiler'.format(lang)) - getter = functools.partial(getter, for_machine) - cc = getter() - binary, newid = cb(cc) - env.binaries[for_machine].binaries[lang] = binary - compiler = getter() - self.assertEqual(compiler.id, newid) - - def test_multiple_native_files_override(self): - wrapper = self.helper_create_binary_wrapper('bash', version='foo') - config = self.helper_create_native_file({'binaries': {'bash': wrapper}}) - wrapper = self.helper_create_binary_wrapper('bash', version='12345') - config2 = self.helper_create_native_file({'binaries': {'bash': wrapper}}) - self.init(self.testcase, extra_args=[ - '--native-file', config, '--native-file', config2, - '-Dcase=find_program']) - - # This test hangs on cygwin. - @unittest.skipIf(os.name != 'posix' or is_cygwin(), 'Uses fifos, which are not available on non Unix OSes.') - def test_native_file_is_pipe(self): - fifo = os.path.join(self.builddir, 'native.file') - os.mkfifo(fifo) - with tempfile.TemporaryDirectory() as d: - wrapper = self.helper_create_binary_wrapper('bash', d, version='12345') - - def filler(): - with open(fifo, 'w') as f: - f.write('[binaries]\n') - f.write("bash = '{}'\n".format(wrapper)) - - thread = threading.Thread(target=filler) - thread.start() - - self.init(self.testcase, extra_args=['--native-file', fifo, '-Dcase=find_program']) - - thread.join() - os.unlink(fifo) - - self.init(self.testcase, extra_args=['--wipe']) - - def test_multiple_native_files(self): - wrapper = self.helper_create_binary_wrapper('bash', version='12345') - config = self.helper_create_native_file({'binaries': {'bash': wrapper}}) - wrapper = self.helper_create_binary_wrapper('python') - config2 = self.helper_create_native_file({'binaries': {'python': wrapper}}) - self.init(self.testcase, extra_args=[ - '--native-file', config, '--native-file', config2, - '-Dcase=find_program']) - - def _simple_test(self, case, binary): - wrapper = self.helper_create_binary_wrapper(binary, version='12345') - config = self.helper_create_native_file({'binaries': {binary: wrapper}}) - self.init(self.testcase, extra_args=['--native-file', config, '-Dcase={}'.format(case)]) - - def test_find_program(self): - self._simple_test('find_program', 'bash') - - def test_config_tool_dep(self): - # Do the skip at this level to avoid screwing up the cache - if mesonbuild.environment.detect_msys2_arch(): - raise unittest.SkipTest('Skipped due to problems with LLVM on MSYS2') - if not shutil.which('llvm-config'): - raise unittest.SkipTest('No llvm-installed, cannot test') - self._simple_test('config_dep', 'llvm-config') - - def test_python3_module(self): - self._simple_test('python3', 'python3') - - def test_python_module(self): - if is_windows(): - # Bat adds extra crap to stdout, so the version check logic in the - # python module breaks. This is fine on other OSes because they - # don't need the extra indirection. - raise unittest.SkipTest('bat indirection breaks internal sanity checks.') - if os.path.exists('/etc/debian_version'): - rc = subprocess.call(['pkg-config', '--cflags', 'python2'], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) - if rc != 0: - # Python 2 will be removed in Debian Bullseye, thus we must - # remove the build dependency on python2-dev. Keep the tests - # but only run them if dev packages are available. - raise unittest.SkipTest('Not running Python 2 tests because dev packages not installed.') - self._simple_test('python', 'python') - - @unittest.skipIf(is_windows(), 'Setting up multiple compilers on windows is hard') - @skip_if_env_set('CC') - def test_c_compiler(self): - def cb(comp): - if comp.id == 'gcc': - if not shutil.which('clang'): - raise unittest.SkipTest('Only one compiler found, cannot test.') - return 'clang', 'clang' - if not is_real_gnu_compiler(shutil.which('gcc')): - raise unittest.SkipTest('Only one compiler found, cannot test.') - return 'gcc', 'gcc' - self.helper_for_compiler('c', cb) - - @unittest.skipIf(is_windows(), 'Setting up multiple compilers on windows is hard') - @skip_if_env_set('CXX') - def test_cpp_compiler(self): - def cb(comp): - if comp.id == 'gcc': - if not shutil.which('clang++'): - raise unittest.SkipTest('Only one compiler found, cannot test.') - return 'clang++', 'clang' - if not is_real_gnu_compiler(shutil.which('g++')): - raise unittest.SkipTest('Only one compiler found, cannot test.') - return 'g++', 'gcc' - self.helper_for_compiler('cpp', cb) - - @skip_if_not_language('objc') - @skip_if_env_set('OBJC') - def test_objc_compiler(self): - def cb(comp): - if comp.id == 'gcc': - if not shutil.which('clang'): - raise unittest.SkipTest('Only one compiler found, cannot test.') - return 'clang', 'clang' - if not is_real_gnu_compiler(shutil.which('gcc')): - raise unittest.SkipTest('Only one compiler found, cannot test.') - return 'gcc', 'gcc' - self.helper_for_compiler('objc', cb) - - @skip_if_not_language('objcpp') - @skip_if_env_set('OBJCXX') - def test_objcpp_compiler(self): - def cb(comp): - if comp.id == 'gcc': - if not shutil.which('clang++'): - raise unittest.SkipTest('Only one compiler found, cannot test.') - return 'clang++', 'clang' - if not is_real_gnu_compiler(shutil.which('g++')): - raise unittest.SkipTest('Only one compiler found, cannot test.') - return 'g++', 'gcc' - self.helper_for_compiler('objcpp', cb) - - @skip_if_not_language('d') - @skip_if_env_set('DC') - def test_d_compiler(self): - def cb(comp): - if comp.id == 'dmd': - if shutil.which('ldc'): - return 'ldc', 'ldc' - elif shutil.which('gdc'): - return 'gdc', 'gdc' - else: - raise unittest.SkipTest('No alternative dlang compiler found.') - if shutil.which('dmd'): - return 'dmd', 'dmd' - raise unittest.SkipTest('No alternative dlang compiler found.') - self.helper_for_compiler('d', cb) - - @skip_if_not_language('cs') - @skip_if_env_set('CSC') - def test_cs_compiler(self): - def cb(comp): - if comp.id == 'csc': - if not shutil.which('mcs'): - raise unittest.SkipTest('No alternate C# implementation.') - return 'mcs', 'mcs' - if not shutil.which('csc'): - raise unittest.SkipTest('No alternate C# implementation.') - return 'csc', 'csc' - self.helper_for_compiler('cs', cb) - - @skip_if_not_language('fortran') - @skip_if_env_set('FC') - def test_fortran_compiler(self): - def cb(comp): - if comp.id == 'lcc': - if shutil.which('lfortran'): - return 'lfortran', 'lcc' - raise unittest.SkipTest('No alternate Fortran implementation.') - elif comp.id == 'gcc': - if shutil.which('ifort'): - # There is an ICC for windows (windows build, linux host), - # but we don't support that ATM so lets not worry about it. - if is_windows(): - return 'ifort', 'intel-cl' - return 'ifort', 'intel' - elif shutil.which('flang'): - return 'flang', 'flang' - elif shutil.which('pgfortran'): - return 'pgfortran', 'pgi' - # XXX: there are several other fortran compilers meson - # supports, but I don't have any of them to test with - raise unittest.SkipTest('No alternate Fortran implementation.') - if not shutil.which('gfortran'): - raise unittest.SkipTest('No alternate Fortran implementation.') - return 'gfortran', 'gcc' - self.helper_for_compiler('fortran', cb) - - def _single_implementation_compiler(self, lang, binary, version_str, version): - """Helper for languages with a single (supported) implementation. - - Builds a wrapper around the compiler to override the version. - """ - wrapper = self.helper_create_binary_wrapper(binary, version=version_str) - env = get_fake_env() - getter = getattr(env, 'detect_{}_compiler'.format(lang)) - getter = functools.partial(getter, MachineChoice.HOST) - env.binaries.host.binaries[lang] = wrapper - compiler = getter() - self.assertEqual(compiler.version, version) - - @skip_if_not_language('vala') - @skip_if_env_set('VALAC') - def test_vala_compiler(self): - self._single_implementation_compiler( - 'vala', 'valac', 'Vala 1.2345', '1.2345') - - @skip_if_not_language('rust') - @skip_if_env_set('RUSTC') - def test_rust_compiler(self): - self._single_implementation_compiler( - 'rust', 'rustc', 'rustc 1.2345', '1.2345') - - @skip_if_not_language('java') - def test_java_compiler(self): - self._single_implementation_compiler( - 'java', 'javac', 'javac 9.99.77', '9.99.77') - - @skip_if_not_language('swift') - def test_swift_compiler(self): - wrapper = self.helper_create_binary_wrapper( - 'swiftc', version='Swift 1.2345', outfile='stderr', - extra_args={'Xlinker': 'macosx_version. PROJECT:ld - 1.2.3'}) - env = get_fake_env() - env.binaries.host.binaries['swift'] = wrapper - compiler = env.detect_swift_compiler(MachineChoice.HOST) - self.assertEqual(compiler.version, '1.2345') - - def test_native_file_dirs(self): - testcase = os.path.join(self.unit_test_dir, '60 native file override') - self.init(testcase, default_args=False, - extra_args=['--native-file', os.path.join(testcase, 'nativefile')]) - - def test_native_file_dirs_overriden(self): - testcase = os.path.join(self.unit_test_dir, '60 native file override') - self.init(testcase, default_args=False, - extra_args=['--native-file', os.path.join(testcase, 'nativefile'), - '-Ddef_libdir=liblib', '-Dlibdir=liblib']) - - def test_compile_sys_path(self): - """Compiling with a native file stored in a system path works. - - There was a bug which caused the paths to be stored incorrectly and - would result in ninja invoking meson in an infinite loop. This tests - for that by actually invoking ninja. - """ - testcase = os.path.join(self.common_test_dir, '1 trivial') - - # It really doesn't matter what's in the native file, just that it exists - config = self.helper_create_native_file({'binaries': {'bash': 'false'}}) - - self.init(testcase, extra_args=['--native-file', config]) - self.build() - - -class CrossFileTests(BasePlatformTests): - - """Tests for cross file functioality not directly related to - cross compiling. - - This is mainly aimed to testing overrides from cross files. - """ - - def test_cross_file_dirs(self): - testcase = os.path.join(self.unit_test_dir, '60 native file override') - self.init(testcase, default_args=False, - extra_args=['--native-file', os.path.join(testcase, 'nativefile'), - '--cross-file', os.path.join(testcase, 'crossfile'), - '-Ddef_bindir=binbar', - '-Ddef_datadir=databar', - '-Ddef_includedir=includebar', - '-Ddef_infodir=infobar', - '-Ddef_libdir=libbar', - '-Ddef_libexecdir=libexecbar', - '-Ddef_localedir=localebar', - '-Ddef_localstatedir=localstatebar', - '-Ddef_mandir=manbar', - '-Ddef_sbindir=sbinbar', - '-Ddef_sharedstatedir=sharedstatebar', - '-Ddef_sysconfdir=sysconfbar']) - - def test_cross_file_dirs_overriden(self): - testcase = os.path.join(self.unit_test_dir, '60 native file override') - self.init(testcase, default_args=False, - extra_args=['--native-file', os.path.join(testcase, 'nativefile'), - '--cross-file', os.path.join(testcase, 'crossfile'), - '-Ddef_libdir=liblib', '-Dlibdir=liblib', - '-Ddef_bindir=binbar', - '-Ddef_datadir=databar', - '-Ddef_includedir=includebar', - '-Ddef_infodir=infobar', - '-Ddef_libexecdir=libexecbar', - '-Ddef_localedir=localebar', - '-Ddef_localstatedir=localstatebar', - '-Ddef_mandir=manbar', - '-Ddef_sbindir=sbinbar', - '-Ddef_sharedstatedir=sharedstatebar', - '-Ddef_sysconfdir=sysconfbar']) - - def test_cross_file_dirs_chain(self): - # crossfile2 overrides crossfile overrides nativefile - testcase = os.path.join(self.unit_test_dir, '60 native file override') - self.init(testcase, default_args=False, - extra_args=['--native-file', os.path.join(testcase, 'nativefile'), - '--cross-file', os.path.join(testcase, 'crossfile'), - '--cross-file', os.path.join(testcase, 'crossfile2'), - '-Ddef_bindir=binbar2', - '-Ddef_datadir=databar', - '-Ddef_includedir=includebar', - '-Ddef_infodir=infobar', - '-Ddef_libdir=libbar', - '-Ddef_libexecdir=libexecbar', - '-Ddef_localedir=localebar', - '-Ddef_localstatedir=localstatebar', - '-Ddef_mandir=manbar', - '-Ddef_sbindir=sbinbar', - '-Ddef_sharedstatedir=sharedstatebar', - '-Ddef_sysconfdir=sysconfbar']) - -class TAPParserTests(unittest.TestCase): - def assert_test(self, events, **kwargs): - if 'explanation' not in kwargs: - kwargs['explanation'] = None - self.assertEqual(next(events), TAPParser.Test(**kwargs)) - - def assert_plan(self, events, **kwargs): - if 'skipped' not in kwargs: - kwargs['skipped'] = False - if 'explanation' not in kwargs: - kwargs['explanation'] = None - self.assertEqual(next(events), TAPParser.Plan(**kwargs)) - - def assert_version(self, events, **kwargs): - self.assertEqual(next(events), TAPParser.Version(**kwargs)) - - def assert_error(self, events): - self.assertEqual(type(next(events)), TAPParser.Error) - - def assert_bailout(self, events, **kwargs): - self.assertEqual(next(events), TAPParser.Bailout(**kwargs)) - - def assert_last(self, events): - with self.assertRaises(StopIteration): - next(events) - - def parse_tap(self, s): - parser = TAPParser(io.StringIO(s)) - return iter(parser.parse()) - - def parse_tap_v13(self, s): - events = self.parse_tap('TAP version 13\n' + s) - self.assert_version(events, version=13) - return events - - def test_empty(self): - events = self.parse_tap('') - self.assert_last(events) - - def test_empty_plan(self): - events = self.parse_tap('1..0') - self.assert_plan(events, count=0, late=False, skipped=True) - self.assert_last(events) - - def test_plan_directive(self): - events = self.parse_tap('1..0 # skipped for some reason') - self.assert_plan(events, count=0, late=False, skipped=True, - explanation='for some reason') - self.assert_last(events) - - events = self.parse_tap('1..1 # skipped for some reason\nok 1') - self.assert_error(events) - self.assert_plan(events, count=1, late=False, skipped=True, - explanation='for some reason') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - events = self.parse_tap('1..1 # todo not supported here\nok 1') - self.assert_error(events) - self.assert_plan(events, count=1, late=False, skipped=False, - explanation='not supported here') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - def test_one_test_ok(self): - events = self.parse_tap('ok') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - def test_one_test_with_number(self): - events = self.parse_tap('ok 1') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - def test_one_test_with_name(self): - events = self.parse_tap('ok 1 abc') - self.assert_test(events, number=1, name='abc', result=TestResult.OK) - self.assert_last(events) - - def test_one_test_not_ok(self): - events = self.parse_tap('not ok') - self.assert_test(events, number=1, name='', result=TestResult.FAIL) - self.assert_last(events) - - def test_one_test_todo(self): - events = self.parse_tap('not ok 1 abc # TODO') - self.assert_test(events, number=1, name='abc', result=TestResult.EXPECTEDFAIL) - self.assert_last(events) - - events = self.parse_tap('ok 1 abc # TODO') - self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS) - self.assert_last(events) - - def test_one_test_skip(self): - events = self.parse_tap('ok 1 abc # SKIP') - self.assert_test(events, number=1, name='abc', result=TestResult.SKIP) - self.assert_last(events) - - def test_one_test_skip_failure(self): - events = self.parse_tap('not ok 1 abc # SKIP') - self.assert_test(events, number=1, name='abc', result=TestResult.FAIL) - self.assert_last(events) - - def test_many_early_plan(self): - events = self.parse_tap('1..4\nok 1\nnot ok 2\nok 3\nnot ok 4') - self.assert_plan(events, count=4, late=False) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_test(events, number=2, name='', result=TestResult.FAIL) - self.assert_test(events, number=3, name='', result=TestResult.OK) - self.assert_test(events, number=4, name='', result=TestResult.FAIL) - self.assert_last(events) - - def test_many_late_plan(self): - events = self.parse_tap('ok 1\nnot ok 2\nok 3\nnot ok 4\n1..4') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_test(events, number=2, name='', result=TestResult.FAIL) - self.assert_test(events, number=3, name='', result=TestResult.OK) - self.assert_test(events, number=4, name='', result=TestResult.FAIL) - self.assert_plan(events, count=4, late=True) - self.assert_last(events) - - def test_directive_case(self): - events = self.parse_tap('ok 1 abc # skip') - self.assert_test(events, number=1, name='abc', result=TestResult.SKIP) - self.assert_last(events) - - events = self.parse_tap('ok 1 abc # ToDo') - self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS) - self.assert_last(events) - - def test_directive_explanation(self): - events = self.parse_tap('ok 1 abc # skip why') - self.assert_test(events, number=1, name='abc', result=TestResult.SKIP, - explanation='why') - self.assert_last(events) - - events = self.parse_tap('ok 1 abc # ToDo Because') - self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS, - explanation='Because') - self.assert_last(events) - - def test_one_test_early_plan(self): - events = self.parse_tap('1..1\nok') - self.assert_plan(events, count=1, late=False) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - def test_one_test_late_plan(self): - events = self.parse_tap('ok\n1..1') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_plan(events, count=1, late=True) - self.assert_last(events) - - def test_out_of_order(self): - events = self.parse_tap('ok 2') - self.assert_error(events) - self.assert_test(events, number=2, name='', result=TestResult.OK) - self.assert_last(events) - - def test_middle_plan(self): - events = self.parse_tap('ok 1\n1..2\nok 2') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_plan(events, count=2, late=True) - self.assert_error(events) - self.assert_test(events, number=2, name='', result=TestResult.OK) - self.assert_last(events) - - def test_too_many_plans(self): - events = self.parse_tap('1..1\n1..2\nok 1') - self.assert_plan(events, count=1, late=False) - self.assert_error(events) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - def test_too_many(self): - events = self.parse_tap('ok 1\nnot ok 2\n1..1') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_test(events, number=2, name='', result=TestResult.FAIL) - self.assert_plan(events, count=1, late=True) - self.assert_error(events) - self.assert_last(events) - - events = self.parse_tap('1..1\nok 1\nnot ok 2') - self.assert_plan(events, count=1, late=False) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_test(events, number=2, name='', result=TestResult.FAIL) - self.assert_error(events) - self.assert_last(events) - - def test_too_few(self): - events = self.parse_tap('ok 1\nnot ok 2\n1..3') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_test(events, number=2, name='', result=TestResult.FAIL) - self.assert_plan(events, count=3, late=True) - self.assert_error(events) - self.assert_last(events) - - events = self.parse_tap('1..3\nok 1\nnot ok 2') - self.assert_plan(events, count=3, late=False) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_test(events, number=2, name='', result=TestResult.FAIL) - self.assert_error(events) - self.assert_last(events) - - def test_too_few_bailout(self): - events = self.parse_tap('1..3\nok 1\nnot ok 2\nBail out! no third test') - self.assert_plan(events, count=3, late=False) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_test(events, number=2, name='', result=TestResult.FAIL) - self.assert_bailout(events, message='no third test') - self.assert_last(events) - - def test_diagnostics(self): - events = self.parse_tap('1..1\n# ignored\nok 1') - self.assert_plan(events, count=1, late=False) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - events = self.parse_tap('# ignored\n1..1\nok 1\n# ignored too') - self.assert_plan(events, count=1, late=False) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - events = self.parse_tap('# ignored\nok 1\n1..1\n# ignored too') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_plan(events, count=1, late=True) - self.assert_last(events) - - def test_empty_line(self): - events = self.parse_tap('1..1\n\nok 1') - self.assert_plan(events, count=1, late=False) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - def test_unexpected(self): - events = self.parse_tap('1..1\ninvalid\nok 1') - self.assert_plan(events, count=1, late=False) - self.assert_error(events) - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_last(events) - - def test_version(self): - events = self.parse_tap('TAP version 13\n') - self.assert_version(events, version=13) - self.assert_last(events) - - events = self.parse_tap('TAP version 12\n') - self.assert_error(events) - self.assert_last(events) - - events = self.parse_tap('1..0\nTAP version 13\n') - self.assert_plan(events, count=0, late=False, skipped=True) - self.assert_error(events) - self.assert_last(events) - - def test_yaml(self): - events = self.parse_tap_v13('ok\n ---\n foo: abc\n bar: def\n ...\nok 2') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_test(events, number=2, name='', result=TestResult.OK) - self.assert_last(events) - - events = self.parse_tap_v13('ok\n ---\n foo: abc\n bar: def') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_error(events) - self.assert_last(events) - - events = self.parse_tap_v13('ok 1\n ---\n foo: abc\n bar: def\nnot ok 2') - self.assert_test(events, number=1, name='', result=TestResult.OK) - self.assert_error(events) - self.assert_test(events, number=2, name='', result=TestResult.FAIL) - self.assert_last(events) - - -def _clang_at_least(compiler, minver: str, apple_minver: str) -> bool: - """ - check that Clang compiler is at least a specified version, whether AppleClang or regular Clang +# Work around some pathlib bugs... +from mesonbuild import _pathlib +import sys +sys.modules['pathlib'] = _pathlib - Parameters - ---------- - compiler: - Meson compiler object - minver: str - Clang minimum version - apple_minver: str - AppleCLang minimum version +import time +import subprocess +import os +import unittest - Returns - ------- - at_least: bool - Clang is at least the specified version - """ - if isinstance(compiler, (mesonbuild.compilers.AppleClangCCompiler, - mesonbuild.compilers.AppleClangCPPCompiler)): - return version_compare(compiler.version, apple_minver) - return version_compare(compiler.version, minver) +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.compilers +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import python_command, setup_vsenv +import mesonbuild.modules.pkgconfig +from unittests.allplatformstests import AllPlatformTests +from unittests.darwintests import DarwinTests +from unittests.failuretests import FailureTests +from unittests.linuxcrosstests import LinuxCrossArmTests, LinuxCrossMingwTests +from unittests.machinefiletests import NativeFileTests, CrossFileTests +from unittests.rewritetests import RewriterTests +from unittests.taptests import TAPParserTests +from unittests.datatests import DataTests +from unittests.internaltests import InternalTests +from unittests.linuxliketests import LinuxlikeTests +from unittests.pythontests import PythonTests +from unittests.subprojectscommandtests import SubprojectsCommandTests +from unittests.windowstests import WindowsTests +from unittests.platformagnostictests import PlatformAgnosticTests def unset_envs(): # For unit tests we must fully control all command lines # so that there are no unexpected changes coming from the # environment, for example when doing a package build. - varnames = ['CPPFLAGS', 'LDFLAGS'] + list(mesonbuild.compilers.compilers.cflags_mapping.values()) + varnames = ['CPPFLAGS', 'LDFLAGS'] + list(mesonbuild.compilers.compilers.CFLAGS_MAPPING.values()) for v in varnames: if v in os.environ: del os.environ[v] @@ -7237,6 +65,9 @@ test_list = [] for arg in argv: if arg.startswith('-'): + if arg in ('-f', '--failfast'): + arg = '--exitfirst' + pytest_args.append(arg) continue # ClassName.test_name => 'ClassName and test_name' if '.' in arg: @@ -7246,29 +77,84 @@ pytest_args += ['-k', ' or '.join(test_list)] return pytest_args +def running_single_tests(argv, cases): + ''' + Check whether we only got arguments for running individual tests, not + entire testcases, and not all testcases (no test args). + ''' + got_test_arg = False + for arg in argv: + if arg.startswith('-'): + continue + for case in cases: + if not arg.startswith(case): + continue + if '.' not in arg: + # Got a testcase, done + return False + got_test_arg = True + return got_test_arg + +def setup_backend(): + filtered = [] + be = 'ninja' + for a in sys.argv: + if a.startswith('--backend'): + be = a.split('=')[1] + else: + filtered.append(a) + # Since we invoke the tests via unittest or xtest test runner + # we need to pass the backend to use to the spawned process via + # this side channel. Yes it sucks, but at least is is fully + # internal to this file. + os.environ['MESON_UNIT_TEST_BACKEND'] = be + sys.argv = filtered + def main(): unset_envs() - try: - import pytest # noqa: F401 - # Need pytest-xdist for `-n` arg - import xdist # noqa: F401 - if sys.version_info.major <= 3 and sys.version_info.minor <= 5: - raise ImportError('pytest with python <= 3.5 is causing issues on the CI') - pytest_args = ['-n', 'auto', './run_unittests.py'] - pytest_args += convert_args(sys.argv[1:]) - return subprocess.run(python_command + ['-m', 'pytest'] + pytest_args).returncode - except ImportError: - print('pytest-xdist not found, using unittest instead') - pass - # All attempts at locating pytest failed, fall back to plain unittest. + setup_backend() cases = ['InternalTests', 'DataTests', 'AllPlatformTests', 'FailureTests', 'PythonTests', 'NativeFileTests', 'RewriterTests', 'CrossFileTests', - 'TAPParserTests', + 'TAPParserTests', 'SubprojectsCommandTests', 'PlatformAgnosticTests', 'LinuxlikeTests', 'LinuxCrossArmTests', 'LinuxCrossMingwTests', 'WindowsTests', 'DarwinTests'] + try: + import pytest # noqa: F401 + pytest_args = [] + try: + # Need pytest-xdist for `-n` arg + import xdist # noqa: F401 + # Don't use pytest-xdist when running single unit tests since it wastes + # time spawning a lot of processes to distribute tests to in that case. + if not running_single_tests(sys.argv, cases): + pytest_args += ['-n', 'auto'] + except ImportError: + print('pytest-xdist not found, tests will not be distributed across CPU cores') + # Let there be colors! + if 'CI' in os.environ: + pytest_args += ['--color=yes'] + pytest_args += ['./run_unittests.py'] + pytest_args += convert_args(sys.argv[1:]) + # Always disable pytest-cov because we use a custom setup + try: + import pytest_cov # noqa: F401 + print('Disabling pytest-cov') + pytest_args += ['-p' 'no:cov'] + except ImportError: + pass + return subprocess.run(python_command + ['-m', 'pytest'] + pytest_args).returncode + except ImportError: + print('pytest not found, using unittest instead') + # Fallback to plain unittest. return unittest.main(defaultTest=cases, buffer=True) if __name__ == '__main__': - raise SystemExit(main()) + setup_vsenv() + print('Meson build system', mesonbuild.coredata.version, 'Unit Tests') + start = time.monotonic() + try: + raise SystemExit(main()) + finally: + print('Total time: {:.3f} seconds'.format(time.monotonic() - start)) diff -Nru meson-0.53.2/setup.cfg meson-0.61.2/setup.cfg --- meson-0.53.2/setup.cfg 2020-02-25 16:02:10.000000000 +0000 +++ meson-0.61.2/setup.cfg 2022-02-14 19:24:02.893610000 +0000 @@ -1,4 +1,6 @@ [metadata] +name = meson +version = attr: mesonbuild.coredata.version description = A high performance build system author = Jussi Pakkanen author_email = jpakkane@gmail.com @@ -21,22 +23,43 @@ Operating System :: POSIX :: BSD Operating System :: POSIX :: Linux Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 Topic :: Software Development :: Build Tools long_description = Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL. [options] -python_requires = >= 3.5.2 +packages = find: +python_requires = >= 3.6 +setup_requires = + setuptools + +[options.entry_points] +console_scripts = + meson = mesonbuild.mesonmain:main [options.extras_require] +ninja = + ninja>=1.8.2 progress = tqdm +typing = + mypy + typing_extensions; python_version <"3.8" + +[options.package_data] +mesonbuild.scripts = cmd_or_ps.ps1 + +[options.packages.find] +include = mesonbuild, mesonbuild.* +exclude = *.data [tool:pytest] python_classes = +python_files = + run_unittests.py [egg_info] tag_build = diff -Nru meson-0.53.2/setup.py meson-0.61.2/setup.py --- meson-0.53.2/setup.py 2020-02-25 18:00:47.000000000 +0000 +++ meson-0.61.2/setup.py 2022-01-17 10:50:45.000000000 +0000 @@ -16,41 +16,16 @@ import sys -if sys.version_info < (3, 5, 2): +if sys.version_info < (3, 6): raise SystemExit('ERROR: Tried to install Meson with an unsupported Python version: \n{}' - '\nMeson requires Python 3.5.2 or greater'.format(sys.version)) + '\nMeson requires Python 3.6.0 or greater'.format(sys.version)) -from mesonbuild.coredata import version from setuptools import setup -# On windows, will create Scripts/meson.exe and Scripts/meson-script.py -# Other platforms will create bin/meson -entries = {'console_scripts': ['meson=mesonbuild.mesonmain:main']} -packages = ['mesonbuild', - 'mesonbuild.ast', - 'mesonbuild.backend', - 'mesonbuild.cmake', - 'mesonbuild.compilers', - 'mesonbuild.compilers.mixins', - 'mesonbuild.dependencies', - 'mesonbuild.modules', - 'mesonbuild.scripts', - 'mesonbuild.templates', - 'mesonbuild.wrap'] -package_data = { - 'mesonbuild.dependencies': ['data/CMakeLists.txt', 'data/CMakeListsLLVM.txt', 'data/CMakePathInfo.txt'], - 'mesonbuild.cmake': ['data/run_ctgt.py', 'data/preload.cmake'], -} data_files = [] if sys.platform != 'win32': # Only useful on UNIX-like systems data_files = [('share/man/man1', ['man/meson.1']), ('share/polkit-1/actions', ['data/com.mesonbuild.install.policy'])] -if __name__ == '__main__': - setup(name='meson', - version=version, - packages=packages, - package_data=package_data, - entry_points=entries, - data_files=data_files,) +setup(data_files=data_files,) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/10 header only/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/10 header only/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/10 header only/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/10 header only/main.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -3,8 +3,14 @@ using namespace std; +#define EXPECTED "Hello World compDef 42" + int main(void) { cmModClass obj("Hello"); cout << obj.getStr() << endl; + if (obj.getStr() != EXPECTED) { + cerr << "Expected: '" << EXPECTED << "'" << endl; + return 1; + } return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/10 header only/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/10 header only/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/10 header only/subprojects/cmMod/CMakeLists.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/10 header only/subprojects/cmMod/CMakeLists.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -9,3 +9,4 @@ set_target_properties(cmModLib PROPERTIES INTERFACE_COMPILE_OPTIONS "-DCMAKE_FLAG_MUST_BE_PRESENT") target_include_directories(cmModLib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include") target_compile_definitions(cmModLib INTERFACE -DCMAKE_COMPILER_DEFINE_STR="compDef") +target_compile_definitions(cmModLib INTERFACE MESON_MAGIC_FLAG=42) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/10 header only/subprojects/cmMod/include/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/10 header only/subprojects/cmMod/include/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/10 header only/subprojects/cmMod/include/cmMod.hpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/10 header only/subprojects/cmMod/include/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -6,6 +6,9 @@ #error "The flag CMAKE_FLAG_MUST_BE_PRESENT was not set" #endif +#define xstr(s) str(s) +#define str(s) #s + class cmModClass { private: std::string str; @@ -13,6 +16,8 @@ cmModClass(std::string foo) { str = foo + " World "; str += CMAKE_COMPILER_DEFINE_STR; + str += ' '; + str += xstr(MESON_MAGIC_FLAG); } inline std::string getStr() const { return str; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/cmake/FindSomethingLikePython.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/cmake/FindSomethingLikePython.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/cmake/FindSomethingLikePython.cmake" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/cmake/FindSomethingLikePython.cmake" 2021-04-01 21:12:21.000000000 +0000 @@ -1,24 +1,9 @@ cmake_policy(VERSION 3.7) -if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) - find_package(Python COMPONENTS Interpreter) -else() - find_package(PythonInterp) -endif() - +find_package(Python COMPONENTS Interpreter) if(Python_FOUND OR PYTHONINTERP_FOUND) set(SomethingLikePython_FOUND ON) set(SomethingLikePython_EXECUTABLE ${Python_EXECUTABLE}) - - if(NOT DEFINED Python_VERSION) - set(Python_VERSION ${Python_VERSION_STRING}) - endif() - if(NOT TARGET Python::Interpreter) - add_executable(Python::Interpreter IMPORTED) - set_target_properties(Python::Interpreter PROPERTIES - IMPORTED_LOCATION ${Python_EXECUTABLE} - VERSION ${Python_VERSION}) - endif() else() set(SomethingLikePython_FOUND OFF) endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/meson.build" 2020-01-07 21:05:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/meson.build" 2021-10-23 16:47:26.000000000 +0000 @@ -1,7 +1,7 @@ # We use Python3 as it's the only thing guaranteed to be available on any platform Meson can run on (unlike Zlib in linuxlike/13 cmake dependency). -project('user CMake find_package module using cmake_module_path', - meson_version: '>= 0.50.0') +project('user CMake find_package module using cmake_module_path', ['c', 'cpp'], + meson_version: '>= 0.55.0') if not find_program('cmake', required: false).found() error('MESON_SKIP_TEST cmake binary not available.') @@ -15,3 +15,11 @@ dependency('SomethingLikePython', required : true, method : 'cmake', cmake_module_path : 'cmake', modules: 'Python::Interpreter') dependency('SomethingLikePython', method : 'cmake', cmake_module_path : ['doesNotExist', 'cmake'], modules: 'Python::Interpreter') + +# Test a custom target with Python::Interpreter in COMMAND +cm = import('cmake') +op = cm.subproject_options() +op.add_cmake_defines({'CMAKE_MODULE_PATH': meson.source_root() / 'cmake'}) +sp = cm.subproject('cmMod', options: op) +main = sp.target('main') +test('main', main) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/subprojects/cmMod/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/subprojects/cmMod/CMakeLists.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmMod) + +message(STATUS "CMAKE_MODULE_PATH: '${CMAKE_MODULE_PATH}'") + +find_package(SomethingLikePython REQUIRED) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/main.c" + COMMAND Python::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/gen.py" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" +) + +add_executable(main "${CMAKE_CURRENT_BINARY_DIR}/main.c") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/subprojects/cmMod/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/subprojects/cmMod/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/subprojects/cmMod/gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/subprojects/cmMod/gen.py" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,9 @@ +with open('main.c', 'w') as fp: + print(''' +#include + +int main(void) { + printf(\"Hello World\"); + return 0; +} +''', file=fp) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/11 cmake_module_path/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/11 cmake_module_path/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "tools": { + "cmake": ">=3.12" + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/13 system includes/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/13 system includes/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/13 system includes/meson.build" 2020-01-07 21:06:04.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/13 system includes/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -7,7 +7,7 @@ ) if meson.get_compiler('cpp').get_argument_syntax() == 'msvc' - error('MESON_SKIP_TEST: Skipp with msvc due to missing -system support') + error('MESON_SKIP_TEST: Skip with msvc due to missing -system support') endif cm = import('cmake') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/15 object library advanced/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/15 object library advanced/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/15 object library advanced/meson.build" 2020-01-07 21:06:08.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/15 object library advanced/meson.build" 2021-10-23 16:47:24.000000000 +0000 @@ -1,5 +1,9 @@ project('cmake_object_lib_test', 'cpp', default_options: ['cpp_std=c++11']) +if meson.is_cross_build() + error('MESON_SKIP_TEST this test does not cross compile correctly.') +endif + cm = import('cmake') sub_pro = cm.subproject('cmObjLib') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/16 threads/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/16 threads/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/16 threads/subprojects/cmMod/CMakeLists.txt" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/16 threads/subprojects/cmMod/CMakeLists.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5) -project(cmMod CXX) +project(cmMod C CXX) set (CMAKE_CXX_STANDARD 14) if(NOT USE_PTHREAD STREQUAL NOT_SET) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/16 threads/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/16 threads/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/16 threads/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/16 threads/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,11 @@ +{ + "matrix": { + "options": { + "use_pthread": [ + { "val": "ON" }, + { "val": "OFF" }, + { "val": "NOT_SET" } + ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/16 threads/test_matrix.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/16 threads/test_matrix.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/16 threads/test_matrix.json" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/16 threads/test_matrix.json" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -{ - "options": { - "use_pthread": [ - { "val": "ON" }, - { "val": "OFF" }, - { "val": "NOT_SET" } - ] - } -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/main.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include + +using namespace std; + +int main(void) { + cmModClass obj("Hello"); + cout << obj.getStr() << endl; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/meson.build" 2021-10-23 16:47:34.000000000 +0000 @@ -0,0 +1,9 @@ +project('include_path_order', ['c', 'cpp']) + +cm = import('cmake') + +sub_pro = cm.subproject('cmMod') +sub_dep = sub_pro.dependency('cmModLib++') + +exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep]) +test('test1', exe1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/CMakeLists.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmMod) +set (CMAKE_CXX_STANDARD 14) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + + # The one and only correct include dir + ${CMAKE_CURRENT_SOURCE_DIR}/incG + + # All of these are traps + ${CMAKE_CURRENT_SOURCE_DIR}/incL + ${CMAKE_CURRENT_SOURCE_DIR}/incM + ${CMAKE_CURRENT_SOURCE_DIR}/incO + ${CMAKE_CURRENT_SOURCE_DIR}/incF + ${CMAKE_CURRENT_SOURCE_DIR}/incI + ${CMAKE_CURRENT_SOURCE_DIR}/incE + ${CMAKE_CURRENT_SOURCE_DIR}/incD + ${CMAKE_CURRENT_SOURCE_DIR}/incH + ${CMAKE_CURRENT_SOURCE_DIR}/incN + ${CMAKE_CURRENT_SOURCE_DIR}/incA + ${CMAKE_CURRENT_SOURCE_DIR}/incB + ${CMAKE_CURRENT_SOURCE_DIR}/incJ + ${CMAKE_CURRENT_SOURCE_DIR}/incP + ${CMAKE_CURRENT_SOURCE_DIR}/incC + ${CMAKE_CURRENT_SOURCE_DIR}/incK +) + +add_definitions("-DDO_NOTHING_JUST_A_FLAG=1") + +add_library(cmModLib++ SHARED cmMod.cpp) +include(GenerateExportHeader) +generate_export_header(cmModLib++) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/cmMod.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/cmMod.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/cmMod.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/cmMod.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,11 @@ +#include "cmMod.hpp" + +using namespace std; + +cmModClass::cmModClass(string foo) { + str = foo + " World"; +} + +string cmModClass::getStr() const { + return str; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incA/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incA/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incA/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incA/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (A) +#pragma once + +#error "cmMod.hpp in incA must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incB/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incB/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incB/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incB/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (B) +#pragma once + +#error "cmMod.hpp in incB must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incC/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incC/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incC/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incC/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (C) +#pragma once + +#error "cmMod.hpp in incC must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incD/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incD/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incD/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incD/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (D) +#pragma once + +#error "cmMod.hpp in incD must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incE/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incE/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incE/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incE/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (E) +#pragma once + +#error "cmMod.hpp in incE must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incF/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incF/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incF/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incF/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (F) +#pragma once + +#error "cmMod.hpp in incF must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incG/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incG/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incG/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incG/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,14 @@ +#pragma once + +#include "cmmodlib++_export.h" +#include + +class CMMODLIB___EXPORT cmModClass { +private: + std::string str; + +public: + cmModClass(std::string foo); + + std::string getStr() const; +}; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incH/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incH/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incH/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incH/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (H) +#pragma once + +#error "cmMod.hpp in incH must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incI/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incI/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incI/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incI/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (I) +#pragma once + +#error "cmMod.hpp in incI must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incJ/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incJ/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incJ/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incJ/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (J) +#pragma once + +#error "cmMod.hpp in incJ must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incL/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incL/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incL/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incL/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (L) +#pragma once + +#error "cmMod.hpp in incL must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incM/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incM/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incM/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incM/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (M) +#pragma once + +#error "cmMod.hpp in incM must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incN/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incN/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incN/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incN/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (N) +#pragma once + +#error "cmMod.hpp in incN must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incO/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incO/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incO/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incO/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (O) +#pragma once + +#error "cmMod.hpp in incO must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incP/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incP/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/17 include path order/subprojects/cmMod/incP/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/17 include path order/subprojects/cmMod/incP/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,4 @@ +// cmMod.hpp (P) +#pragma once + +#error "cmMod.hpp in incP must not be included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/main.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include + +using namespace std; + +int main(void) { + cmModClass obj("Hello"); + cout << obj.getStr() << endl; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/meson.build" 2021-10-23 16:47:36.000000000 +0000 @@ -0,0 +1,9 @@ +project('cmakeSubTest', ['c', 'cpp']) + +cm = import('cmake') + +sub_pro = cm.subproject('cmMod') +sub_dep = sub_pro.dependency('cmModLib++') + +exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep]) +test('test1', exe1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmMod) +set (CMAKE_CXX_STANDARD 14) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_definitions("-DDO_NOTHING_JUST_A_FLAG=1") + +set(SRCS + ${CMAKE_CURRENT_LIST_DIR}/cmMod.hpp + ${CMAKE_CURRENT_LIST_DIR}/cmMod.cpp +) + +add_subdirectory(fakeInc) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,10 @@ +#include "cmMod.hpp" + +using namespace std; + +#define MESON_INCLUDE_IMPL +#include "fakeInc/cmModInc1.cpp" +#include "fakeInc/cmModInc2.cpp" +#include "fakeInc/cmModInc3.cpp" +#include "fakeInc/cmModInc4.cpp" +#undef MESON_INCLUDE_IMPL diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,16 @@ +#pragma once + +#include "cmmodlib++_export.h" +#include + +class CMMODLIB___EXPORT cmModClass { +private: + std::string str; + + std::string getStr1() const; + std::string getStr2() const; +public: + cmModClass(std::string foo); + + std::string getStr() const; +}; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,30 @@ +list(APPEND SRCS + cmModInc1.cpp + cmModInc2.cpp + cmModInc3.cpp + cmModInc4.cpp +) + +set(SRC_A + cmModInc1.cpp + ${CMAKE_CURRENT_LIST_DIR}/cmModInc2.cpp +) + +set_property( + SOURCE ${SRC_A} + PROPERTY + HEADER_FILE_ONLY ON +) + +set_source_files_properties( + cmModInc3.cpp + ${CMAKE_CURRENT_LIST_DIR}/cmModInc4.cpp + PROPERTIES + LABELS "CMake;Lists;are;fun" + HEADER_FILE_ONLY ON +) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +add_library(cmModLib++ SHARED ${SRCS}) +include(GenerateExportHeader) +generate_export_header(cmModLib++) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +#ifndef MESON_INCLUDE_IMPL +#error "MESON_INCLUDE_IMPL is not defined" +#endif // !MESON_INCLUDE_IMPL + +cmModClass::cmModClass(string foo) { + str = foo + " World"; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +#ifndef MESON_INCLUDE_IMPL +#error "MESON_INCLUDE_IMPL is not defined" +#endif // !MESON_INCLUDE_IMPL + +string cmModClass::getStr() const { + return getStr2(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +#ifndef MESON_INCLUDE_IMPL +#error "MESON_INCLUDE_IMPL is not defined" +#endif // !MESON_INCLUDE_IMPL + +string cmModClass::getStr1() const { + return getStr2(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +#ifndef MESON_INCLUDE_IMPL +#error "MESON_INCLUDE_IMPL is not defined" +#endif // !MESON_INCLUDE_IMPL + +string cmModClass::getStr2() const { + return str; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/main.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,18 @@ +#include +#include +#include + +using namespace std; + +int main(void) { + cmModClass obj("Hello"); + cout << obj.getStr() << endl; + + int v1 = obj.getInt(); + int v2 = getTestInt(); + if (v1 != ((1 + v2) * 2)) { + cerr << "Number test failed" << endl; + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/meson.build" 2021-10-23 16:47:38.000000000 +0000 @@ -0,0 +1,29 @@ +project('cmake_set_opt', ['c', 'cpp']) + +comp = meson.get_compiler('cpp') +if comp.get_argument_syntax() == 'msvc' + error('MESON_SKIP_TEST: MSVC is not supported because it does not support C++11') +endif + +cm = import('cmake') +opts = cm.subproject_options() + +opts.add_cmake_defines({'SOME_CMAKE_VAR': 'something', 'SOME_OTHER_VAR': true}) + +opts.set_override_option('cpp_std', 'c++11') # Global is C++11 +opts.set_override_option('cpp_std', 'c++14', target: 'cmModLib++') # Override it with C++14 for cmModLib++ + +opts.append_compile_args('cpp', '-DMESON_GLOBAL_FLAG=1') +opts.append_compile_args('cpp', ['-DMESON_SPECIAL_FLAG1=1', ['-DMESON_SPECIAL_FLAG2=1']], target: 'cmModLib++') +opts.append_compile_args('cpp', '-DMESON_MAGIC_INT=42', target: 'cmModLib++') +opts.append_compile_args('cpp', [[[['-DMESON_MAGIC_INT=20']]]], target: 'cmTestLib') + +opts.set_install(false) +opts.set_install(true, target: 'testEXE') + +sp = cm.subproject('cmOpts', options: opts) +dep1 = sp.dependency('cmModLib++') +dep2 = sp.dependency('cmTestLib') + +exe1 = executable('main', ['main.cpp'], dependencies: [dep1, dep2]) +test('test1', exe1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/CMakeLists.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.7) + +project(CmOpts) + +set(CMAKE_CXX_STANDARD 98) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if(NOT "${SOME_CMAKE_VAR}" STREQUAL "something") + message(FATAL_ERROR "Setting the CMake var failed") +endif() + +add_library(cmModLib++ STATIC cmMod.cpp) +add_library(cmTestLib STATIC cmTest.cpp) +add_executable(testEXE main.cpp) + +target_link_libraries(testEXE cmModLib++) + +install(TARGETS cmTestLib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,31 @@ +#include "cmMod.hpp" + +using namespace std; + +#if __cplusplus < 201402L +#error "At least C++14 is required" +#endif + +#ifndef MESON_GLOBAL_FLAG +#error "MESON_GLOBAL_FLAG was not set" +#endif + +#ifndef MESON_SPECIAL_FLAG1 +#error "MESON_SPECIAL_FLAG1 was not set" +#endif + +#ifndef MESON_SPECIAL_FLAG2 +#error "MESON_SPECIAL_FLAG2 was not set" +#endif + +cmModClass::cmModClass(string foo) { + str = foo + " World"; +} + +string cmModClass::getStr() const { + return str; +} + +int cmModClass::getInt() const { + return MESON_MAGIC_INT; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,14 @@ +#pragma once + +#include + +class cmModClass { +private: + std::string str; + +public: + cmModClass(std::string foo); + + std::string getStr() const; + int getInt() const; +}; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,25 @@ +#include "cmTest.hpp" + +#if __cplusplus < 201103L +#error "At least C++11 is required" +#endif + +#if __cplusplus >= 201402L +#error "At most C++11 is required" +#endif + +#ifndef MESON_GLOBAL_FLAG +#error "MESON_GLOBAL_FLAG was not set" +#endif + +#ifdef MESON_SPECIAL_FLAG1 +#error "MESON_SPECIAL_FLAG1 *was* set" +#endif + +#ifdef MESON_SPECIAL_FLAG2 +#error "MESON_SPECIAL_FLAG2 *was* set" +#endif + +int getTestInt() { + return MESON_MAGIC_INT; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +int getTestInt(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/subprojects/cmOpts/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/subprojects/cmOpts/main.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include "cmMod.hpp" + +using namespace std; + +int main(void) { + cmModClass obj("Hello (LIB TEST)"); + cout << obj.getStr() << endl; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/19 advanced options/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/19 advanced options/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/testEXE"} + ], + "tools": { + "cmake": ">=3.11" + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/meson.build" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/meson.build" 2021-10-23 16:47:08.000000000 +0000 @@ -3,11 +3,12 @@ cm = import('cmake') sub_pro = cm.subproject('cmMod') -sub_dep = sub_pro.dependency('cmModLib++') +sub_dep = sub_pro.dependency('cmModLib++', include_type: 'system') assert(sub_pro.found(), 'found() method reports not found, but should be found') assert(sub_pro.target_list() == ['cmModLib++'], 'There should be exactly one target') assert(sub_pro.target_type('cmModLib++') == 'shared_library', 'Target type should be shared_library') +assert(sub_dep.include_type() == 'system', 'the include_type kwarg of dependency() works') exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep]) test('test1', exe1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/subprojects/cmMod/CMakeLists.txt" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/subprojects/cmMod/CMakeLists.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -8,5 +8,13 @@ add_definitions("-DDO_NOTHING_JUST_A_FLAG=1") add_library(cmModLib++ SHARED cmMod.cpp) +target_compile_definitions(cmModLib++ PRIVATE MESON_MAGIC_FLAG=21) +target_compile_definitions(cmModLib++ INTERFACE MESON_MAGIC_FLAG=42) + +# Test PCH support +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0") + target_precompile_headers(cmModLib++ PRIVATE "cpp_pch.hpp") +endif() + include(GenerateExportHeader) generate_export_header(cmModLib++) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/subprojects/cmMod/cmMod.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/subprojects/cmMod/cmMod.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/subprojects/cmMod/cmMod.cpp" 2019-06-16 18:54:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/subprojects/cmMod/cmMod.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -2,6 +2,10 @@ using namespace std; +#if MESON_MAGIC_FLAG != 21 +#error "Invalid MESON_MAGIC_FLAG (private)" +#endif + cmModClass::cmModClass(string foo) { str = foo + " World"; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/subprojects/cmMod/cmMod.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/subprojects/cmMod/cmMod.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/subprojects/cmMod/cmMod.hpp" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/subprojects/cmMod/cmMod.hpp" 2020-08-15 16:27:05.000000000 +0000 @@ -3,6 +3,10 @@ #include "cmmodlib++_export.h" #include +#if MESON_MAGIC_FLAG != 42 && MESON_MAGIC_FLAG != 21 +#error "Invalid MESON_MAGIC_FLAG" +#endif + class CMMODLIB___EXPORT cmModClass { private: std::string str; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/subprojects/cmMod/cpp_pch.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/subprojects/cmMod/cpp_pch.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/1 basic/subprojects/cmMod/cpp_pch.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/1 basic/subprojects/cmMod/cpp_pch.hpp" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,2 @@ +#include +#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/20 cmake file/foolib.cmake.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/20 cmake file/foolib.cmake.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/20 cmake file/foolib.cmake.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/20 cmake file/foolib.cmake.in" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1 @@ +@foo@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/20 cmake file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/20 cmake file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/20 cmake file/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/20 cmake file/meson.build" 2021-10-23 16:47:32.000000000 +0000 @@ -0,0 +1,14 @@ +project( + 'cmake config file', +) + +cmake = import('cmake') + +cmake_conf = configuration_data() +cmake_conf.set_quoted('foo', 'bar') +cmake.configure_package_config_file( + name : 'foolib', + input : 'foolib.cmake.in', + install_dir : get_option('libdir') / 'cmake', + configuration : cmake_conf, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/20 cmake file/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/20 cmake file/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/20 cmake file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/20 cmake file/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + {"file": "usr/lib/cmake/foolibConfig.cmake", "type": "file"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/meson.build" 2021-10-23 16:47:40.000000000 +0000 @@ -0,0 +1,13 @@ +project('cmakeSharedModule', ['c', 'cpp']) + +cm = import('cmake') + +sub_pro = cm.subproject('cmMod') +sub_dep = sub_pro.dependency('myMod') + +dl = meson.get_compiler('c').find_library('dl', required: false) + +l = shared_library('runtime', 'runtime.c') +e = executable('prog', ['prog.c'], link_with: l, dependencies: [sub_dep, dl]) +m = sub_pro.target('myMod') +test('test1', e, args : m) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/prog.c" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,108 @@ + +#include +#include "module.h" + +#if SPECIAL_MAGIC_DEFINE != 42 +#error "SPECIAL_MAGIC_DEFINE is not defined" +#endif + +int func_from_language_runtime(void); +typedef int (*fptr) (void); + +#ifdef _WIN32 + +#include + +static wchar_t* +win32_get_last_error (void) +{ + wchar_t *msg = NULL; + + FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_IGNORE_INSERTS + | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError (), 0, + (LPWSTR) &msg, 0, NULL); + return msg; +} + +int main(int argc, char **argv) +{ + HINSTANCE handle; + fptr importedfunc; + int expected, actual; + int ret = 1; + if(argc==0) {}; + + handle = LoadLibraryA (argv[1]); + if (!handle) { + wchar_t *msg = win32_get_last_error (); + printf ("Could not open %s: %S\n", argv[1], msg); + goto nohandle; + } + + importedfunc = (fptr) GetProcAddress (handle, "func"); + if (importedfunc == NULL) { + wchar_t *msg = win32_get_last_error (); + printf ("Could not find 'func': %S\n", msg); + goto out; + } + + actual = importedfunc (); + expected = func_from_language_runtime (); + if (actual != expected) { + printf ("Got %i instead of %i\n", actual, expected); + goto out; + } + + ret = 0; +out: + FreeLibrary (handle); +nohandle: + return ret; +} + +#else + +#include +#include + +int main(int argc, char **argv) { + void *dl; + fptr importedfunc; + int expected, actual; + char *error; + int ret = 1; + if(argc==0) {}; + + dlerror(); + dl = dlopen(argv[1], RTLD_LAZY); + error = dlerror(); + if(error) { + printf("Could not open %s: %s\n", argv[1], error); + goto nodl; + } + + importedfunc = (fptr) dlsym(dl, "func"); + if (importedfunc == NULL) { + printf ("Could not find 'func'\n"); + goto out; + } + + assert(importedfunc != func_from_language_runtime); + + actual = (*importedfunc)(); + expected = func_from_language_runtime (); + if (actual != expected) { + printf ("Got %i instead of %i\n", actual, expected); + goto out; + } + + ret = 0; +out: + dlclose(dl); +nodl: + return ret; +} + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/runtime.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/runtime.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/runtime.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/runtime.c" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,19 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +/* + * This file pretends to be a language runtime that supports extension + * modules. + */ + +int DLL_PUBLIC func_from_language_runtime(void) { + return 86; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmModule) + +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/module") + +add_library(myMod MODULE "${CMAKE_CURRENT_SOURCE_DIR}/module/module.c") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,96 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) + +#include + +typedef int (*fptr) (void); + +#ifdef __CYGWIN__ + +#include + +fptr find_any_f (const char *name) { + return (fptr) dlsym(RTLD_DEFAULT, name); +} +#else /* _WIN32 */ + +#include +#include + +static wchar_t* +win32_get_last_error (void) +{ + wchar_t *msg = NULL; + + FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_IGNORE_INSERTS + | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError (), 0, + (LPWSTR) &msg, 0, NULL); + return msg; +} + +/* Unlike Linux and OS X, when a library is loaded, all the symbols aren't + * loaded into a single namespace. You must fetch the symbol by iterating over + * all loaded modules. Code for finding the function from any of the loaded + * modules is taken from gmodule.c in glib */ +fptr find_any_f (const char *name) { + fptr f; + HANDLE snapshot; + MODULEENTRY32 me32; + + snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0); + if (snapshot == (HANDLE) -1) { + wchar_t *msg = win32_get_last_error(); + printf("Could not get snapshot: %S\n", msg); + return 0; + } + + me32.dwSize = sizeof (me32); + + f = NULL; + if (Module32First (snapshot, &me32)) { + do { + if ((f = (fptr) GetProcAddress (me32.hModule, name)) != NULL) + break; + } while (Module32Next (snapshot, &me32)); + } + + CloseHandle (snapshot); + return f; +} +#endif + +int DLL_PUBLIC func(void) { + fptr f; + + f = find_any_f ("func_from_language_runtime"); + if (f != NULL) + return f(); + printf ("Could not find function\n"); + return 1; +} + +#else +/* + * Shared modules often have references to symbols that are not defined + * at link time, but which will be provided from deps of the executable that + * dlopens it. We need to make sure that this works, i.e. that we do + * not pass -Wl,--no-undefined when linking modules. + */ +int func_from_language_runtime(void); + +int DLL_PUBLIC func(void) { + return func_from_language_runtime(); +} +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +#define SPECIAL_MAGIC_DEFINE 42 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/22 cmake module/cmake_project/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/22 cmake module/cmake_project/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/22 cmake module/cmake_project/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/22 cmake module/cmake_project/CMakeLists.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 2.8) +project(cmakeMeson C) + +find_package(cmakeModule REQUIRED) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/22 cmake module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/22 cmake module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/22 cmake module/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/22 cmake module/meson.build" 2021-10-23 16:47:38.000000000 +0000 @@ -0,0 +1,31 @@ +project('cmakeModule', 'c', version: '1.0.0') + +if build_machine.system() == 'cygwin' + error('MESON_SKIP_TEST CMake is broken on Cygwin.') +endif + +cmake_bin = find_program('cmake', required: false) +if not cmake_bin.found() + error('MESON_SKIP_TEST CMake not installed.') +endif + +cc = meson.get_compiler('c') +if cc.get_id() == 'clang-cl' and meson.backend() == 'ninja' and build_machine.system() == 'windows' + error('MESON_SKIP_TEST CMake installation nor operational for vs2017 clangclx64ninja') +endif + +cmake = import('cmake') + +cmake.write_basic_package_version_file(version: '0.0.1', + name: 'cmakeModule', +) + +conf = configuration_data() +conf.set('MYVAR', 'my variable value') +conf.set_quoted('MYQUOTEDVAR', 'my quoted variable value') + +cmake.configure_package_config_file( + input: 'projectConfig.cmake.in', + name: 'cmakeModule', + configuration: conf, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/22 cmake module/projectConfig.cmake.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/22 cmake module/projectConfig.cmake.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/22 cmake module/projectConfig.cmake.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/22 cmake module/projectConfig.cmake.in" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,4 @@ +@PACKAGE_INIT@ + +set(MYVAR "@MYVAR@") +set(MYQUOTEDVAR @MYQUOTEDVAR@) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/22 cmake module/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/22 cmake module/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/22 cmake module/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/22 cmake module/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/cmake/cmakeModule/cmakeModuleConfig.cmake"}, + {"type": "file", "file": "usr/lib/cmake/cmakeModule/cmakeModuleConfigVersion.cmake"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/CMakeToolchain.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/CMakeToolchain.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/CMakeToolchain.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/CMakeToolchain.cmake" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1 @@ +set(MESON_TEST_VAR2 VAR2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/meson.build" 2021-10-23 16:47:43.000000000 +0000 @@ -0,0 +1,13 @@ +project('cmake toolchain test', ['c']) + +if meson.is_cross_build() + error('MESON_SKIP_TEST: skip this on cross builds') +endif + +cm = import('cmake') + +sub_pro = cm.subproject('cmMod') + +add_languages('cpp') + +sub_pro = cm.subproject('cmModFortran') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/nativefile.ini.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/nativefile.ini.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/nativefile.ini.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/nativefile.ini.in" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ +[properties] + +cmake_toolchain_file = '@MESON_TEST_ROOT@/CMakeToolchain.cmake' +cmake_skip_compiler_test = 'always' + +[cmake] + +MESON_TEST_VAR1 = 'VAR1 space' +MESON_TEST_VAR2 = 'VAR2 error' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/subprojects/cmMod/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/subprojects/cmMod/CMakeLists.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmMod NONE) + +if(NOT "${MESON_TEST_VAR1}" STREQUAL "VAR1 space") + message(FATAL_ERROR "MESON_TEST_VAR1 -- '${MESON_TEST_VAR1}' != 'VAR1 space'") +endif() + +if(NOT "${MESON_TEST_VAR2}" STREQUAL "VAR2") + message(FATAL_ERROR "MESON_TEST_VAR2 -- '${MESON_TEST_VAR2}' != 'VAR2'") +endif() + +if(NOT DEFINED CMAKE_C_COMPILER_VERSION) + message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION was not defined") +endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/subprojects/cmModFortran/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/subprojects/cmModFortran/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/23 cmake toolchain/subprojects/cmModFortran/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/23 cmake toolchain/subprojects/cmModFortran/CMakeLists.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmMod NONE) + +if(NOT "${MESON_TEST_VAR1}" STREQUAL "VAR1 space") + message(FATAL_ERROR "MESON_TEST_VAR1 -- '${MESON_TEST_VAR1}' != 'VAR1 space'") +endif() + +if(NOT "${MESON_TEST_VAR2}" STREQUAL "VAR2") + message(FATAL_ERROR "MESON_TEST_VAR2 -- '${MESON_TEST_VAR2}' != 'VAR2'") +endif() + +if(NOT DEFINED CMAKE_C_COMPILER_VERSION) + message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION was not defined") +endif() + +if(NOT DEFINED CMAKE_CXX_COMPILER_VERSION) + message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION was not defined") +endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/main.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int main(void) { + return doStuff(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/meson.build" 2021-10-23 16:47:47.000000000 +0000 @@ -0,0 +1,13 @@ +project('CMake mix', ['c', 'cpp']) + +if not add_languages('objc', required : false) + error('MESON_SKIP_TEST: No ObjC compiler') +endif + +cm = import('cmake') + +sub_pro = cm.subproject('cmTest') +sub_dep = sub_pro.dependency('cmTest', include_type: 'system') + +exe1 = executable('exe1', ['main.c'], dependencies: [sub_dep]) +test('test1', exe1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmTest) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_library(cmTest STATIC cmTest.c cmTest.m) +target_compile_definitions(cmTest PUBLIC SOME_MAGIC_DEFINE=42) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,13 @@ +#include "cmTest.h" +#include + +#if SOME_MAGIC_DEFINE != 42 +#error "SOME_MAGIC_DEFINE != 42" +#endif + +int foo(int x); + +int doStuff(void) { + printf("Hello World\n"); + return foo(42); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +int doStuff(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,7 @@ +#if SOME_MAGIC_DEFINE != 42 +#error "SOME_MAGIC_DEFINE != 42" +#endif + +int foo(int x) { + return 42 - x; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/main.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,18 @@ +#include +#include + +int32_t cmTestFunc(void); + +int main(void) +{ + if (cmTestFunc() > 4200) + { + printf("Test success.\n"); + return 0; + } + else + { + printf("Test failure.\n"); + return 1; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/meson.build" 2021-10-23 16:47:47.000000000 +0000 @@ -0,0 +1,9 @@ +project('assembler test', ['c', 'cpp']) + +cm = import('cmake') + +sub_pro = cm.subproject('cmTest') +sub_dep = sub_pro.dependency('cmTest') + +exe1 = executable('exe1', ['main.c'], dependencies: [sub_dep]) +test('test1', exe1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/subprojects/cmTest/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/subprojects/cmTest/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/subprojects/cmTest/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/subprojects/cmTest/CMakeLists.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmTest) + +#Detect processor +if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "amd64") + SET(TEST_PROCESSOR "x86_64") +elseif ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86_64") + SET(TEST_PROCESSOR "x86_64") +elseif ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i386") + SET(TEST_PROCESSOR "x86") +elseif ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i686") + SET(TEST_PROCESSOR "x86") +elseif ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm") + SET(TEST_PROCESSOR "arm") +elseif ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "aarch64") + SET(TEST_PROCESSOR "arm") +else () + message(FATAL_ERROR, 'MESON_SKIP_TEST: Unsupported Assembler Platform') +endif () + +#Detect ABI +if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + SET(TEST_ABI "sysv") +elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD") + SET(TEST_ABI "sysv") +elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "NetBSD") + SET(TEST_ABI "sysv") +elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD") + SET(TEST_ABI "sysv") +else () + message(FATAL_ERROR, 'MESON_SKIP_TEST: Unsupported Assembler Platform') +endif () + +SET(TEST_PLATFORM "${TEST_PROCESSOR}-${TEST_ABI}") + +if ( ("${TEST_PLATFORM}" MATCHES "x86_64-sysv") + OR ("${TEST_PLATFORM}" MATCHES "x86-sysv") + OR ("${TEST_PLATFORM}" MATCHES "arm-sysv")) + SET(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) + enable_language(ASM) + SET(TEST_SOURCE "cmTestAsm.s") +endif () + +add_library(cmTest STATIC cmTest.c ${TEST_SOURCE}) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/subprojects/cmTest/cmTestAsm.s" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/subprojects/cmTest/cmTestAsm.s" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/subprojects/cmTest/cmTestAsm.s" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/subprojects/cmTest/cmTestAsm.s" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +.text +.globl cmTestArea +cmTestArea: + .long 4242 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/subprojects/cmTest/cmTest.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/subprojects/cmTest/cmTest.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/25 assembler/subprojects/cmTest/cmTest.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/25 assembler/subprojects/cmTest/cmTest.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +extern const int32_t cmTestArea; + +int32_t cmTestFunc(void) +{ + return cmTestArea; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/installed_files.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -usr/?lib/libcm_cmModLib?so -?cygwin:usr/lib/libcm_cmModLib?implib -?!cygwin:usr/bin/libcm_cmModLib?implib -usr/bin/cm_testEXE?exe diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/meson.build" 2020-01-07 21:05:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/meson.build" 2021-10-23 16:47:10.000000000 +0000 @@ -21,3 +21,7 @@ # Test if we can also extract executables assert(sub_pro.target_type('testEXE') == 'executable', 'The type must be executable for obvious reasons') test('test3', sub_pro.target('testEXE')) + +# Test that we can add a new target with the same name as the CMake subproject +exe4 = executable('testEXE', ['main.cpp'], dependencies: [sub_sta]) +test('test4', exe4) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt" 2021-04-01 21:13:00.000000000 +0000 @@ -20,9 +20,19 @@ add_executable(testEXE main.cpp) target_link_libraries(cmModLib ZLIB::ZLIB) -target_link_libraries(cmModLibStatic ZLIB::ZLIB) +target_link_libraries(cmModLibStatic ;ZLIB::ZLIB;) target_link_libraries(testEXE cmModLib) +if(APPLE) + find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation") + if(NOT COREFOUNDATION_FRAMEWORK) + message(FATAL_ERROR "CoreFoundation framework not found") + endif() + + target_link_libraries(cmModLibStatic "${COREFOUNDATION_FRAMEWORK}") + target_compile_definitions(cmModLibStatic PUBLIC USE_FRAMEWORK) +endif() + target_compile_definitions(cmModLibStatic PUBLIC CMMODLIB_STATIC_DEFINE) -install(TARGETS cmModLib testEXE LIBRARY DESTINATION lib RUNTIME DESTINATION bin) +install(TARGETS testEXE LIBRARY DESTINATION lib RUNTIME DESTINATION bin) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp" 2019-06-16 18:54:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp" 2021-04-01 21:13:00.000000000 +0000 @@ -6,10 +6,19 @@ #error "Invalid value of CONFIG_OPT" #endif +#ifdef USE_FRAMEWORK +#include +#endif + using namespace std; cmModClass::cmModClass(string foo) { str = foo + " World " + zlibVersion(); + +#ifdef USE_FRAMEWORK + CFStringRef ref = CFStringCreateWithCString(NULL, str.c_str(), kCFStringEncodingUTF8); + CFRelease(ref); +#endif } string cmModClass::getStr() const { diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/2 advanced/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/2 advanced/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/testEXE"} + ], + "tools": { + "cmake": ">=3.11" + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/3 advanced no dep/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/3 advanced no dep/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/3 advanced no dep/installed_files.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/3 advanced no dep/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -usr/?lib/libcm_cmModLib?so -?cygwin:usr/lib/libcm_cmModLib?implib -?!cygwin:usr/bin/libcm_cmModLib?implib -?msvc:usr/bin/cm_cmModLib.pdb -?msvc:usr/bin/cm_testEXE.pdb -usr/bin/cm_testEXE?exe \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/3 advanced no dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/3 advanced no dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/3 advanced no dep/meson.build" 2020-01-07 21:05:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/3 advanced no dep/meson.build" 2021-10-23 16:47:09.000000000 +0000 @@ -14,5 +14,6 @@ test('test2', exe2) # Test if we can also extract executables -assert(sub_pro.target_type('testEXE') == 'executable', 'The type must be executable for obvious reasons') -test('test3', sub_pro.target('testEXE')) +assert(sub_pro.target_type('meson-testEXE') == 'executable', 'The type must be executable for obvious reasons') +test('test3', sub_pro.target('meson-testEXE')) +test('test4', sub_pro.target('benchmark')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/3 advanced no dep/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/3 advanced no dep/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/3 advanced no dep/subprojects/cmMod/CMakeLists.txt" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/3 advanced no dep/subprojects/cmMod/CMakeLists.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -15,10 +15,12 @@ set_target_properties(cmModLib PROPERTIES VERSION 1.0.1) -add_executable(testEXE main.cpp) +add_executable(meson-testEXE main.cpp) +add_executable(benchmark main.cpp) -target_link_libraries(testEXE cmModLib) +target_link_libraries(meson-testEXE cmModLib) +target_link_libraries(benchmark cmModLib) target_compile_definitions(cmModLibStatic PUBLIC CMMODLIB_STATIC_DEFINE) -install(TARGETS cmModLib testEXE LIBRARY DESTINATION lib RUNTIME DESTINATION bin) +install(TARGETS meson-testEXE benchmark LIBRARY DESTINATION lib RUNTIME DESTINATION bin) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/3 advanced no dep/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/3 advanced no dep/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/3 advanced no dep/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/3 advanced no dep/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,11 @@ +{ + "installed": [ + {"type": "pdb", "file": "usr/bin/cm_meson_testEXE"}, + {"type": "exe", "file": "usr/bin/cm_meson_testEXE"}, + {"type": "pdb", "file": "usr/bin/cm_benchmark"}, + {"type": "exe", "file": "usr/bin/cm_benchmark"} + ], + "tools": { + "cmake": ">=3.11" + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/4 code gen/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/4 code gen/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/4 code gen/meson.build" 2020-01-07 21:05:17.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/4 code gen/meson.build" 2021-10-23 16:47:07.000000000 +0000 @@ -1,5 +1,9 @@ project('cmake_code_gen', ['c', 'cpp']) +if meson.is_cross_build() + error('MESON_SKIP_TEST this test does not cross compile correctly.') +endif + cm = import('cmake') # Subproject with the "code generator" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/4 code gen/subprojects/cmCodeGen/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/4 code gen/subprojects/cmCodeGen/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/4 code gen/subprojects/cmCodeGen/CMakeLists.txt" 2019-06-16 18:54:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/4 code gen/subprojects/cmCodeGen/CMakeLists.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.7) +project(CMCodeGen) set(CMAKE_CXX_STANDARD 14) add_executable(genA main.cpp) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/7 cmake options/subprojects/cmOpts/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/7 cmake options/subprojects/cmOpts/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/7 cmake options/subprojects/cmOpts/CMakeLists.txt" 2019-06-16 18:54:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/7 cmake options/subprojects/cmOpts/CMakeLists.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -1,5 +1,10 @@ cmake_minimum_required(VERSION 3.7) +project(testPro) if(NOT "${SOME_CMAKE_VAR}" STREQUAL "something") message(FATAL_ERROR "Setting the CMake var failed") endif() + +if(NOT "${CMAKE_PREFIX_PATH}" STREQUAL "val1;val2") + message(FATAL_ERROR "Setting the CMAKE_PREFIX_PATH failed '${CMAKE_PREFIX_PATH}'") +endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/7 cmake options/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/7 cmake options/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/7 cmake options/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/7 cmake options/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,12 @@ +{ + "matrix": { + "options": { + "cmake_prefix_path": [ + { "val": ["val1", "val2"] } + ], + "build.cmake_prefix_path": [ + { "val": ["val1", "val2"] } + ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/meson.build" 2020-01-07 21:05:54.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/meson.build" 2021-10-23 16:47:17.000000000 +0000 @@ -1,5 +1,9 @@ project('cmakeSubTest', ['c', 'cpp']) +if meson.is_cross_build() + error('MESON_SKIP_TEST this test does not cross compile correctly.') +endif + cm = import('cmake') sub_pro = cm.subproject('cmMod') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -7,6 +7,9 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_definitions("-DDO_NOTHING_JUST_A_FLAG=1") +add_executable(genMain genMain.cpp) +add_custom_command(OUTPUT main.cpp COMMAND genMain > main.cpp) + add_executable(gen main.cpp) add_executable(mycpy cp.cpp) @@ -16,9 +19,15 @@ COMMAND gen ARGS genTest ) +set(CMD_PART) +list(APPEND CMD_PART COMMAND mycpy cpyBase.cpp.in cpyBase.cpp.in.gen) +list(APPEND CMD_PART COMMAND mycpy cpyBase.cpp.in.gen cpyBase.cpp.out) +list(APPEND CMD_PART COMMAND mycpy cpyBase.cpp.out cpyBase.cpp.something) + add_custom_command( OUTPUT cpyBase.cpp COMMAND mycpy "${CMAKE_CURRENT_SOURCE_DIR}/cpyBase.cpp.am" cpyBase.cpp.in + ${CMD_PART} COMMAND mycpy cpyBase.cpp.in cpyBase.cpp.something COMMAND mycpy cpyBase.cpp.something cpyBase.cpp.IAmRunningOutOfIdeas COMMAND mycpy cpyBase.cpp.IAmRunningOutOfIdeas cpyBase.cpp @@ -111,7 +120,14 @@ add_subdirectory(cpyTest ccppyyTTeesstt) -add_library(cmModLib SHARED cmMod.cpp genTest.cpp cpyBase.cpp cpyBase.hpp cpyNext.cpp cpyNext.hpp cpyTest.cpp cpyTest.hpp cpyTest2.hpp cpyTest3.hpp) +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cpyTest/some/directory/cpyTest5.hpp" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/cpyTest/cpyTest5.hpp" "${CMAKE_CURRENT_BINARY_DIR}/cpyTest/some/directory/cpyTest5.hpp" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/cpyTest/cpyTest5.hpp" +) +include_directories("${CMAKE_CURRENT_BINARY_DIR}/cpyTest/some") + +add_library(cmModLib SHARED cmMod.cpp genTest.cpp cpyBase.cpp cpyBase.hpp cpyNext.cpp cpyNext.hpp cpyTest.cpp cpyTest.hpp cpyTest2.hpp cpyTest3.hpp cpyTest/some/directory/cpyTest5.hpp) include(GenerateExportHeader) generate_export_header(cmModLib) @@ -125,5 +141,19 @@ ) add_custom_target(macro_name_cmd COMMAND macro_name) +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + message(STATUS "Running the -include test case on macro_name") + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cpyInc.hpp" + COMMAND mycpy "${CMAKE_CURRENT_SOURCE_DIR}/cpyInc.hpp.am" "${CMAKE_CURRENT_BINARY_DIR}/cpyInc.hpp" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/cpyInc.hpp.am" + ) + target_compile_options(macro_name PUBLIC -DTEST_CMD_INCLUDE -include "${CMAKE_CURRENT_BINARY_DIR}/cpyInc.hpp") +endif() + +# Only executable targets are replaced in the command +# all other target names are kept as is +add_custom_target(clang-format COMMAND clang-format -i cmMod.cpp) + add_dependencies(cmModLib args_test_cmd tgtCpyTest4) add_dependencies(args_test_cmd macro_name_cmd;gen;mycpy) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp" 2021-11-02 19:58:07.000000000 +0000 @@ -20,5 +20,5 @@ } string cmModClass::getOther() const { - return "Srings:\n - " + getStrCpy() + "\n - " + getStrNext() + "\n - " + getStrCpyTest(); + return "Strings:\n - " + getStrCpy() + "\n - " + getStrNext() + "\n - " + getStrCpyTest(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyInc.hpp.am" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyInc.hpp.am" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyInc.hpp.am" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyInc.hpp.am" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +#define CPY_INC_WAS_INCLUDED 1 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest5.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest5.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest5.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest5.hpp" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +#define CPY_TEST_STR_5 " test" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp" 2021-04-01 21:12:21.000000000 +0000 @@ -2,7 +2,8 @@ #include "cpyTest2.hpp" #include "cpyTest3.hpp" #include "ccppyyTTeesstt/cpyTest4.hpp" +#include "directory/cpyTest5.hpp" std::string getStrCpyTest() { - return CPY_TEST_STR_2 CPY_TEST_STR_3 CPY_TEST_STR_4; + return CPY_TEST_STR_2 CPY_TEST_STR_3 CPY_TEST_STR_4 CPY_TEST_STR_5; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/genMain.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/genMain.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/genMain.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/genMain.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,40 @@ +#include + +using namespace std; + +int main() { + cout << R"asd( +#include +#include + +using namespace std; + +int main(int argc, const char *argv[]) { + if(argc < 2) { + cerr << argv[0] << " requires an output file!" << endl; + return 1; + } + ofstream out1(string(argv[1]) + ".hpp"); + ofstream out2(string(argv[1]) + ".cpp"); + out1 << R"( +#pragma once + +#include + +std::string getStr(); +)"; + + out2 << R"( +#include ")" << argv[1] << R"(.hpp" + +std::string getStr() { + return "Hello World"; +} +)"; + + return 0; +} +)asd"; + + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/macro_name.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/macro_name.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/macro_name.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/macro_name.cpp" 2021-04-01 21:12:21.000000000 +0000 @@ -5,6 +5,12 @@ using namespace std; +#ifdef TEST_CMD_INCLUDE +#if CPY_INC_WAS_INCLUDED != 1 +#error "cpyInc.hpp was not included" +#endif +#endif + int main() { this_thread::sleep_for(chrono::seconds(1)); ofstream out1("macro_name.txt"); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cmake/8 custom command/subprojects/cmMod/main.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cmake/8 custom command/subprojects/cmMod/main.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -#include -#include - -using namespace std; - -int main(int argc, const char *argv[]) { - if(argc < 2) { - cerr << argv[0] << " requires an output file!" << endl; - return 1; - } - ofstream out1(string(argv[1]) + ".hpp"); - ofstream out2(string(argv[1]) + ".cpp"); - out1 << R"( -#pragma once - -#include - -std::string getStr(); -)"; - - out2 << R"( -#include ")" << argv[1] << R"(.hpp" - -std::string getStr() { - return "Hello World"; -} -)"; - - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 postconf with args/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 postconf with args/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 postconf with args/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 postconf with args/meson.build" 2021-10-23 16:48:57.000000000 +0000 @@ -0,0 +1,10 @@ +project('postconf script', 'c') + +conf = configure_file( + configuration : configuration_data(), + output : 'out' +) + +meson.add_postconf_script(find_program('postconf.py'), '5', '33', conf) + +test('post', executable('prog', 'prog.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 postconf with args/postconf.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 postconf with args/postconf.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 postconf with args/postconf.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 postconf with args/postconf.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +import sys, os + +template = '''#pragma once + +#define THE_NUMBER {} +#define THE_ARG1 {} +#define THE_ARG2 {} +''' + +input_file = os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat') +output_file = os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h') + +with open(input_file) as f: + data = f.readline().strip() +with open(output_file, 'w') as f: + f.write(template.format(data, sys.argv[1], sys.argv[2])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 postconf with args/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 postconf with args/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 postconf with args/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 postconf with args/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"generated.h" + +int main(void) { + return THE_NUMBER != 9 || THE_ARG1 != 5 || THE_ARG2 != 33; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 postconf with args/raw.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 postconf with args/raw.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 postconf with args/raw.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 postconf with args/raw.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +9 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 stringdef/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 stringdef/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 stringdef/meson.build" 2020-01-07 21:07:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 stringdef/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('stringdef', 'c') - -test('stringdef', executable('stringdef', 'stringdef.c', c_args : '-DFOO="bar"')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 stringdef/stringdef.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 stringdef/stringdef.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/100 stringdef/stringdef.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/100 stringdef/stringdef.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include -#include - -int main(void) { - if(strcmp(FOO, "bar")) { - printf("FOO is misquoted: %s\n", FOO); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 find program path/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 find program path/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 find program path/meson.build" 2020-01-07 21:07:49.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 find program path/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -project('find program', 'c') - -python = import('python3').find_python() - -# Source file via string -prog = find_program('program.py') -# Source file via files() -progf = files('program.py') -# Built file -py = configure_file(input : 'program.py', - output : 'builtprogram.py', - configuration : configuration_data()) - -foreach f : [prog, progf, py, find_program(py), find_program(progf)] - ret = run_command(python, f) - assert(ret.returncode() == 0, 'can\'t manually run @0@'.format(prog.path())) - assert(ret.stdout().strip() == 'Found', 'wrong output from manually-run @0@'.format(prog.path())) - - ret = run_command(f) - assert(ret.returncode() == 0, 'can\'t run @0@'.format(prog.path())) - assert(ret.stdout().strip() == 'Found', 'wrong output from @0@'.format(prog.path())) -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 find program path/program.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 find program path/program.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 find program path/program.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 find program path/program.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/usr/bin/env python3 - -print("Found") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 testframework options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 testframework options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 testframework options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 testframework options/meson.build" 2021-10-23 16:48:57.000000000 +0000 @@ -0,0 +1,8 @@ +# normally run only from run_tests.py or run_project_tests.py +# else do like +# meson build '-Dtestoption=A string with spaces' -Dother_one=true -Dcombo_opt=one -Dprefix=/usr -Dlibdir=lib -Dbackend=ninja -Dwerror=True +project('options', 'c') + +assert(get_option('testoption') == 'A string with spaces', 'Incorrect value for testoption option.') +assert(get_option('other_one') == true, 'Incorrect value for other_one option.') +assert(get_option('combo_opt') == 'one', 'Incorrect value for combo_opt option.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 testframework options/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 testframework options/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 testframework options/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 testframework options/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +option('testoption', type : 'string', value : 'optval', description : 'An option to do something') +option('other_one', type : 'boolean', value : false) +option('combo_opt', type : 'combo', choices : ['one', 'two', 'combo'], value : 'combo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 testframework options/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 testframework options/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/101 testframework options/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/101 testframework options/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "matrix": { + "options": { + "testoption": [{ "val": "A string with spaces" }], + "other_one": [{ "val": "true" }], + "combo_opt": [{ "val": "one" }], + "werror": [{ "val": "true" }] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 extract same name/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 extract same name/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 extract same name/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 extract same name/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func1(void) { + return 23; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 extract same name/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 extract same name/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 extract same name/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 extract same name/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func1(void); +int func2(void); + +int main(void) { + return !(func1() == 23 && func2() == 42); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 extract same name/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 extract same name/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 extract same name/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 extract same name/meson.build" 2021-10-23 16:48:58.000000000 +0000 @@ -0,0 +1,19 @@ +project('object extraction', 'c') + +if meson.backend() == 'xcode' + # Xcode gives object files unique names but only if they would clash. For example + # two files named lib.o instead get the following names: + # + # lib-4fbe522d8ba4cb1f1b89cc2df640a2336b92e1a5565f0a4c5a79b5b5e2969eb9.o + # lib-4fbe522d8ba4cb1f1b89cc2df640a2336deeff2bc2297affaadbe20f5cbfee56.o + # + # No-one has reverse engineered the naming scheme so we would access them. + # IF you feel up to the challenge, patches welcome. + error('MESON_SKIP_TEST, Xcode can not extract objs when they would have the same filename.') +endif + +lib = library('somelib', ['lib.c', 'src/lib.c']) +# Also tests that the object list is flattened properly +obj = lib.extract_objects(['lib.c', ['src/lib.c']]) +exe = executable('main', 'main.c', objects: obj) +test('extraction', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 extract same name/src/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 extract same name/src/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 extract same name/src/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 extract same name/src/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func2(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/meson.build" 2020-01-07 21:07:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -project('proj', 'c') -subproject('sub') -libSub = dependency('sub', fallback: ['sub', 'libSub']) - -exe = executable('prog', 'prog.c', dependencies: libSub) -test('subproject subdir', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -int main(void) { - return sub(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/subprojects/sub/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/subprojects/sub/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/subprojects/sub/lib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/subprojects/sub/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -lib = static_library('sub', 'sub.c') -libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/subprojects/sub/lib/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/subprojects/sub/lib/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/subprojects/sub/lib/sub.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/subprojects/sub/lib/sub.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "sub.h" - -int sub(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/subprojects/sub/lib/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/subprojects/sub/lib/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/subprojects/sub/lib/sub.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/subprojects/sub/lib/sub.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef SUB_H -#define SUB_H - -int sub(void); - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/102 subproject subdir/subprojects/sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/102 subproject subdir/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('sub', 'c') -subdir('lib') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 has header symbol/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 has header symbol/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 has header symbol/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 has header symbol/meson.build" 2021-10-23 16:49:08.000000000 +0000 @@ -0,0 +1,40 @@ +project( + 'has header symbol', + 'c', 'cpp', + default_options : ['cpp_std=c++11'], +) + +cc = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') + +foreach comp : [cc, cpp] + assert (comp.has_header_symbol('stdio.h', 'int'), 'base types should always be available') + assert (comp.has_header_symbol('stdio.h', 'printf'), 'printf function not found') + assert (comp.has_header_symbol('stdio.h', 'FILE'), 'FILE structure not found') + assert (comp.has_header_symbol('limits.h', 'INT_MAX'), 'INT_MAX define not found') + assert (not comp.has_header_symbol('limits.h', 'guint64'), 'guint64 is not defined in limits.h') + assert (not comp.has_header_symbol('stdlib.h', 'FILE'), 'FILE structure is defined in stdio.h, not stdlib.h') + assert (not comp.has_header_symbol('stdlol.h', 'printf'), 'stdlol.h shouldn\'t exist') + assert (not comp.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header') +endforeach + +# This is available on Glibc, Solaris & the BSD's, so just test for _GNU_SOURCE +# on Linux +if cc.has_function('ppoll') and host_machine.system() == 'linux' + assert (not cc.has_header_symbol('poll.h', 'ppoll'), 'ppoll should not be accessible without _GNU_SOURCE') + assert (cc.has_header_symbol('poll.h', 'ppoll', prefix : '#define _GNU_SOURCE'), 'ppoll should be accessible with _GNU_SOURCE') +endif + +assert (cpp.has_header_symbol('iostream', 'std::iostream'), 'iostream not found in iostream.h') +assert (cpp.has_header_symbol('vector', 'std::vector'), 'vector not found in vector.h') +assert (not cpp.has_header_symbol('limits.h', 'std::iostream'), 'iostream should not be defined in limits.h') + +# Cross compilation and boost do not mix. +if not meson.is_cross_build() + boost = dependency('boost', required : false) + if boost.found() + assert (cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion not found') + else + assert (not cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion found?!') + endif +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 postconf/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 postconf/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 postconf/meson.build" 2020-01-07 21:07:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 postconf/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('postconf script', 'c') - -meson.add_postconf_script('postconf.py') - -test('post', executable('prog', 'prog.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 postconf/postconf.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 postconf/postconf.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 postconf/postconf.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 postconf/postconf.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 - -import os - -template = '''#pragma once - -#define THE_NUMBER {} -''' - -input_file = os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat') -output_file = os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h') - -with open(input_file) as f: - data = f.readline().strip() -with open(output_file, 'w') as f: - f.write(template.format(data)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 postconf/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 postconf/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 postconf/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 postconf/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"generated.h" - -int main(void) { - return THE_NUMBER != 9; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 postconf/raw.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 postconf/raw.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/103 postconf/raw.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/103 postconf/raw.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -9 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 has arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 has arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 has arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 has arg/meson.build" 2021-10-23 16:49:01.000000000 +0000 @@ -0,0 +1,60 @@ +project('has arg', 'c', 'cpp') + +cc = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') + +if cc.get_id() == 'msvc' + is_arg = '/O2' + useless = '/DFOO' +else + is_arg = '-O2' + useless = '-DFOO' +endif + +isnt_arg = '-fiambroken' + +assert(cc.has_argument(is_arg), 'Arg that should have worked does not work.') +assert(not cc.has_argument(isnt_arg), 'Arg that should be broken is not.') + +assert(cpp.has_argument(is_arg), 'Arg that should have worked does not work.') +assert(not cpp.has_argument(isnt_arg), 'Arg that should be broken is not.') + +assert(cc.get_supported_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') +assert(cpp.get_supported_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') + +# Have useless at the end to ensure that the search goes from front to back. +l1 = cc.first_supported_argument([isnt_arg, is_arg, isnt_arg, useless]) +l2 = cc.first_supported_argument(isnt_arg, isnt_arg, isnt_arg) + +assert(l1.length() == 1, 'First supported returned wrong result.') +assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') +assert(l2.length() == 0, 'First supported did not return empty array.') + +l1 = cpp.first_supported_argument([isnt_arg, is_arg, isnt_arg, useless]) +l2 = cpp.first_supported_argument(isnt_arg, isnt_arg, isnt_arg) + +assert(l1.length() == 1, 'First supported returned wrong result.') +assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') +assert(l2.length() == 0, 'First supported did not return empty array.') + +if cc.get_id() == 'gcc' + pre_arg = '-Wformat' + # NOTE: We have special handling for -Wno-foo args because gcc silently + # ignores unknown -Wno-foo args unless you pass -Werror, so for this test, we + # pass it as two separate arguments. + anti_pre_arg = ['-W', 'no-format'] + arg = '-Werror=format-security' + assert(not cc.has_multi_arguments([anti_pre_arg, arg]), 'Arg that should be broken is not.') + assert(cc.has_multi_arguments(pre_arg), 'Arg that should have worked does not work.') + assert(cc.has_multi_arguments([pre_arg, arg]), 'Arg that should have worked does not work.') + # Test that gcc correctly errors out on unknown -Wno flags + assert(not cc.has_argument('-Wno-lol-meson-test-flags'), 'should error out on unknown -Wno args') + assert(not cc.has_multi_arguments(['-Wno-pragmas', '-Wno-lol-meson-test-flags']), 'should error out even if some -Wno args are valid') +endif + +if cc.get_id() == 'clang' and cc.version().version_compare('<=4.0.0') + # 4.0.0 does not support -fpeel-loops. Newer versions may. + # Please adjust above version number as new versions of clang are released. + notyet_arg = '-fpeel-loops' + assert(not cc.has_argument(notyet_arg), 'Arg that should be broken (unless clang added support recently) is not.') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 postconf with args/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 postconf with args/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 postconf with args/meson.build" 2020-01-07 21:07:51.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 postconf with args/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('postconf script', 'c') - -meson.add_postconf_script('postconf.py', '5', '33') - -test('post', executable('prog', 'prog.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 postconf with args/postconf.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 postconf with args/postconf.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 postconf with args/postconf.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 postconf with args/postconf.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os - -template = '''#pragma once - -#define THE_NUMBER {} -#define THE_ARG1 {} -#define THE_ARG2 {} -''' - -input_file = os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat') -output_file = os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h') - -with open(input_file) as f: - data = f.readline().strip() -with open(output_file, 'w') as f: - f.write(template.format(data, sys.argv[1], sys.argv[2])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 postconf with args/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 postconf with args/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 postconf with args/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 postconf with args/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"generated.h" - -int main(void) { - return THE_NUMBER != 9 || THE_ARG1 != 5 || THE_ARG2 != 33; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 postconf with args/raw.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 postconf with args/raw.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/104 postconf with args/raw.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/104 postconf with args/raw.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -9 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/catter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/catter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/catter.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/catter.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +import sys + +output = sys.argv[-1] +inputs = sys.argv[1:-1] + +with open(output, 'w') as ofile: + ofile.write('#pragma once\n') + for i in inputs: + with open(i) as ifile: + content = ifile.read() + ofile.write(content) + ofile.write('\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/gen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import sys + +ifile = sys.argv[1] +ofile = sys.argv[2] + +with open(ifile) as f: + resname = f.readline().strip() + +templ = 'const char %s[] = "%s";\n' +with open(ofile, 'w') as f: + f.write(templ % (resname, resname)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/gen-resx.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/gen-resx.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/gen-resx.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/gen-resx.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys + +ofile = sys.argv[1] +num = sys.argv[2] + +with open(ofile, 'w') as f: + f.write(f'res{num}\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +#include "alltogether.h" + +int main(void) { + printf("%s - %s - %s - %s\n", res1, res2, res3, res4); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/meson.build" 2021-10-23 16:49:01.000000000 +0000 @@ -0,0 +1,28 @@ +project('generatorcustom', 'c') + +creator = find_program('gen.py') +catter = find_program('catter.py') +gen_resx = find_program('gen-resx.py') + +gen = generator(creator, + output: '@BASENAME@.h', + arguments : ['@INPUT@', '@OUTPUT@']) + +res3 = custom_target('gen-res3', + output : 'res3.txt', + command : [gen_resx, '@OUTPUT@', '3']) + +res4 = custom_target('gen-res4', + output : 'res4.txt', + command : [gen_resx, '@OUTPUT@', '4']) + +hs = gen.process('res1.txt', 'res2.txt', res3, res4[0]) + +allinone = custom_target('alltogether', + input : hs, + output : 'alltogether.h', + command : [catter, '@INPUT@', '@OUTPUT@']) + +proggie = executable('proggie', 'main.c', allinone) + +test('proggie', proggie) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/res1.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/res1.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/res1.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/res1.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +res1 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/res2.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/res2.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 generatorcustom/res2.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 generatorcustom/res2.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +res2 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 testframework options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 testframework options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 testframework options/meson.build" 2020-01-07 21:07:53.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 testframework options/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('options', 'c') - -assert(get_option('testoption') == 'A string with spaces', 'Incorrect value for testoption option.') -assert(get_option('other_one') == true, 'Incorrect value for other_one option.') -assert(get_option('combo_opt') == 'one', 'Incorrect value for combo_opt option.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 testframework options/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 testframework options/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 testframework options/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 testframework options/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -option('testoption', type : 'string', value : 'optval', description : 'An option to do something') -option('other_one', type : 'boolean', value : false) -option('combo_opt', type : 'combo', choices : ['one', 'two', 'combo'], value : 'combo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 testframework options/test_args.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 testframework options/test_args.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/105 testframework options/test_args.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/105 testframework options/test_args.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -# This file is not read by meson itself, but by the test framework. -# It is not possible to pass arguments to meson from a file. -['--werror', '-D', 'testoption=A string with spaces', '-D', 'other_one=true', \ - '-D', 'combo_opt=one'] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 extract same name/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 extract same name/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 extract same name/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 extract same name/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func1(void) { - return 23; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 extract same name/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 extract same name/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 extract same name/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 extract same name/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func1(void); -int func2(void); - -int main(void) { - return !(func1() == 23 && func2() == 42); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 extract same name/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 extract same name/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 extract same name/meson.build" 2020-01-07 21:07:54.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 extract same name/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('object extraction', 'c') - -lib = shared_library('somelib', ['lib.c', 'src/lib.c']) -# Also tests that the object list is flattened properly -obj = lib.extract_objects(['lib.c', ['src/lib.c']]) -exe = executable('main', 'main.c', objects: obj) -test('extraction', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 extract same name/src/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 extract same name/src/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 extract same name/src/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 extract same name/src/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func2(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 multiple dir configure file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 multiple dir configure file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 multiple dir configure file/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 multiple dir configure file/meson.build" 2021-10-23 16:49:02.000000000 +0000 @@ -0,0 +1,11 @@ +project('multiple dir configure file', 'c') + +subdir('subdir') + +configure_file(input : 'subdir/someinput.in', + output : 'outputhere', + copy: true) + +configure_file(input : cfile1, + output : '@BASENAME@', + copy: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 multiple dir configure file/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 multiple dir configure file/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/106 multiple dir configure file/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/106 multiple dir configure file/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +configure_file(input : 'someinput.in', + output : 'outputsubdir', + install : false, + copy: true) + +py3 = import('python3').find_python() + +cfile1 = configure_file(input : 'foo.txt', + output : 'foo.h.in', + capture : true, + command : [py3, '-c', 'print("#mesondefine FOO_BAR")']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 has header symbol/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 has header symbol/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 has header symbol/meson.build" 2020-01-07 21:08:04.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 has header symbol/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -project('has header symbol', 'c', 'cpp') - -cc = meson.get_compiler('c') -cpp = meson.get_compiler('cpp') - -foreach comp : [cc, cpp] - assert (comp.has_header_symbol('stdio.h', 'int'), 'base types should always be available') - assert (comp.has_header_symbol('stdio.h', 'printf'), 'printf function not found') - assert (comp.has_header_symbol('stdio.h', 'FILE'), 'FILE structure not found') - assert (comp.has_header_symbol('limits.h', 'INT_MAX'), 'INT_MAX define not found') - assert (not comp.has_header_symbol('limits.h', 'guint64'), 'guint64 is not defined in limits.h') - assert (not comp.has_header_symbol('stdlib.h', 'FILE'), 'FILE structure is defined in stdio.h, not stdlib.h') - assert (not comp.has_header_symbol('stdlol.h', 'printf'), 'stdlol.h shouldn\'t exist') - assert (not comp.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header') -endforeach - -# This is available on Glibc, Solaris & the BSD's, so just test for _GNU_SOURCE -# on Linux -if cc.has_function('ppoll') and host_machine.system() == 'linux' - assert (not cc.has_header_symbol('poll.h', 'ppoll'), 'ppoll should not be accessible without _GNU_SOURCE') - assert (cc.has_header_symbol('poll.h', 'ppoll', prefix : '#define _GNU_SOURCE'), 'ppoll should be accessible with _GNU_SOURCE') -endif - -assert (cpp.has_header_symbol('iostream', 'std::iostream'), 'iostream not found in iostream.h') -assert (cpp.has_header_symbol('vector', 'std::vector'), 'vector not found in vector.h') -assert (not cpp.has_header_symbol('limits.h', 'std::iostream'), 'iostream should not be defined in limits.h') - -# Cross compilation and boost do not mix. -if not meson.is_cross_build() - boost = dependency('boost', required : false) - if boost.found() - assert (cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion not found') - else - assert (not cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion found?!') - endif -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/asm output/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/asm output/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/asm output/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/asm output/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +configure_file(output : 'blank.txt', configuration : configuration_data()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/comparer.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/comparer.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/comparer.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/comparer.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include "comparer.h" + +#ifndef COMPARER_INCLUDED +#error "comparer.h not included" +#endif + +#define COMPARE_WITH "foo\\bar" /* This is the literal `foo\bar` */ + +int main(void) { + if (strcmp (DEF_WITH_BACKSLASH, COMPARE_WITH)) { + printf ("Arg string is quoted incorrectly: %s instead of %s\n", + DEF_WITH_BACKSLASH, COMPARE_WITH); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/comparer-end.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/comparer-end.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/comparer-end.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/comparer-end.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include "comparer.h" + +#ifndef COMPARER_INCLUDED +#error "comparer.h not included" +#endif + +#define COMPARE_WITH "foo\\bar\\" /* This is `foo\bar\` */ + +int main(void) { + if (strcmp (DEF_WITH_BACKSLASH, COMPARE_WITH)) { + printf ("Arg string is quoted incorrectly: %s vs %s\n", + DEF_WITH_BACKSLASH, COMPARE_WITH); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/comparer-end-notstring.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/comparer-end-notstring.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/comparer-end-notstring.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/comparer-end-notstring.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +#include "comparer.h" + +#ifndef COMPARER_INCLUDED +#error "comparer.h not included" +#endif + +/* This converts foo\\\\bar\\\\ to "foo\\bar\\" (string literal) */ +#define Q(x) #x +#define QUOTE(x) Q(x) + +#define COMPARE_WITH "foo\\bar\\" /* This is the literal `foo\bar\` */ + +int main(void) { + if(strcmp(QUOTE(DEF_WITH_BACKSLASH), COMPARE_WITH)) { + printf("Arg string is quoted incorrectly: %s instead of %s\n", + QUOTE(DEF_WITH_BACKSLASH), COMPARE_WITH); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/include/comparer.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/include/comparer.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/include/comparer.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/include/comparer.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +#include +#include + +#define COMPARER_INCLUDED diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/107 spaces backslash/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/107 spaces backslash/meson.build" 2021-10-23 16:49:02.000000000 +0000 @@ -0,0 +1,28 @@ +project('comparer', 'c') + +# Added manually as a c_arg to test handling of include paths with backslashes +# and spaces. This is especially useful on Windows in vcxproj files since it +# stores include directories in a separate element that has its own +# context-specific escaping/quoting. +include_dir = meson.current_source_dir() + '/include' +default_c_args = ['-I' + include_dir] + +if meson.get_compiler('c').get_argument_syntax() == 'msvc' + default_c_args += ['/Faasm output\\'] + # Hack to create the 'asm output' directory in the builddir + subdir('asm output') +endif + +# Path can contain \. Here we're sending `"foo\bar"`. +test('backslash quoting', + executable('comparer', 'comparer.c', + c_args : default_c_args + ['-DDEF_WITH_BACKSLASH="foo\\bar"'])) +# Path can end in \ without any special quoting. Here we send `"foo\bar\"`. +test('backslash end quoting', + executable('comparer-end', 'comparer-end.c', + c_args : default_c_args + ['-DDEF_WITH_BACKSLASH="foo\\bar\\"'])) +# Path can (really) end in \ if we're not passing a string literal without any +# special quoting. Here we're sending `foo\bar\`. +test('backslash end quoting when not a string literal', + executable('comparer-end-notstring', 'comparer-end-notstring.c', + c_args : default_c_args + ['-DDEF_WITH_BACKSLASH=foo\\bar\\'])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/108 has arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/108 has arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/108 has arg/meson.build" 2020-01-07 21:07:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/108 has arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -project('has arg', 'c', 'cpp') - -cc = meson.get_compiler('c') -cpp = meson.get_compiler('cpp') - -if cc.get_id() == 'msvc' - is_arg = '/O2' - useless = '/DFOO' -else - is_arg = '-O2' - useless = '-DFOO' -endif - -isnt_arg = '-fiambroken' - -assert(cc.has_argument(is_arg), 'Arg that should have worked does not work.') -assert(not cc.has_argument(isnt_arg), 'Arg that should be broken is not.') - -assert(cpp.has_argument(is_arg), 'Arg that should have worked does not work.') -assert(not cpp.has_argument(isnt_arg), 'Arg that should be broken is not.') - -assert(cc.get_supported_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') -assert(cpp.get_supported_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') - -# Have useless at the end to ensure that the search goes from front to back. -l1 = cc.first_supported_argument([isnt_arg, is_arg, isnt_arg, useless]) -l2 = cc.first_supported_argument(isnt_arg, isnt_arg, isnt_arg) - -assert(l1.length() == 1, 'First supported returned wrong result.') -assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') -assert(l2.length() == 0, 'First supported did not return empty array.') - -l1 = cpp.first_supported_argument([isnt_arg, is_arg, isnt_arg, useless]) -l2 = cpp.first_supported_argument(isnt_arg, isnt_arg, isnt_arg) - -assert(l1.length() == 1, 'First supported returned wrong result.') -assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') -assert(l2.length() == 0, 'First supported did not return empty array.') - -if cc.get_id() == 'gcc' - pre_arg = '-Wformat' - # NOTE: We have special handling for -Wno-foo args because gcc silently - # ignores unknown -Wno-foo args unless you pass -Werror, so for this test, we - # pass it as two separate arguments. - anti_pre_arg = ['-W', 'no-format'] - arg = '-Werror=format-security' - assert(not cc.has_multi_arguments([anti_pre_arg, arg]), 'Arg that should be broken is not.') - assert(cc.has_multi_arguments(pre_arg), 'Arg that should have worked does not work.') - assert(cc.has_multi_arguments([pre_arg, arg]), 'Arg that should have worked does not work.') - # Test that gcc correctly errors out on unknown -Wno flags - assert(not cc.has_argument('-Wno-lol-meson-test-flags'), 'should error out on unknown -Wno args') - assert(not cc.has_multi_arguments(['-Wno-pragmas', '-Wno-lol-meson-test-flags']), 'should error out even if some -Wno args are valid') -endif - -if cc.get_id() == 'clang' and cc.version().version_compare('<=4.0.0') - # 4.0.0 does not support -fpeel-loops. Newer versions may. - # Please adjust above version number as new versions of clang are released. - notyet_arg = '-fpeel-loops' - assert(not cc.has_argument(notyet_arg), 'Arg that should be broken (unless clang added support recently) is not.') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/108 ternary/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/108 ternary/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/108 ternary/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/108 ternary/meson.build" 2021-10-23 16:49:02.000000000 +0000 @@ -0,0 +1,12 @@ +project('ternary operator', 'c') + +x = true +one = true ? 1 : error('False branch should not be evaluated') +two = false ? error('True branch should not be evaluated.') : 2 +three = '@0@'.format(x ? 'yes' : 'no') +four = [x ? '0' : '1'] + +assert(one == 1, 'Return value from ternary true is wrong.') +assert(two == 2, 'Return value from ternary false is wrong.') +assert(three == 'yes', 'Return value for ternary inside method call is wrong.') +assert(four == ['0'], 'Return value for ternary inside of list is wrong.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 custom target capture/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 custom target capture/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 custom target capture/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 custom target capture/data_source.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 custom target capture/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 custom target capture/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 custom target capture/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 custom target capture/meson.build" 2021-10-23 16:49:03.000000000 +0000 @@ -0,0 +1,24 @@ +project('custom target', 'c') + +python3 = import('python3').find_python() + +# Note that this will not add a dependency to the compiler executable. +# Code will not be rebuilt if it changes. +comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') + +mytarget = custom_target('bindat', + output : 'data.dat', + input : 'data_source.txt', + capture : true, + command : [python3, comp, '@INPUT@'], + install : true, + install_dir : 'subdir' +) + +ct_output_exists = '''import os, sys +if not os.path.exists(sys.argv[1]): + print("could not find {!r} in {!r}".format(sys.argv[1], os.getcwd())) + sys.exit(1) +''' + +test('capture-wrote', python3, args : ['-c', ct_output_exists, mytarget]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 custom target capture/my_compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 custom target capture/my_compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 custom target capture/my_compiler.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 custom target capture/my_compiler.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +import sys + +if __name__ == '__main__': + if len(sys.argv) != 2: + print(sys.argv[0], 'input_file') + sys.exit(1) + with open(sys.argv[1]) as f: + ifile = f.read() + if ifile != 'This is a text only input file.\n': + print('Malformed input') + sys.exit(1) + print('This is a binary output file.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 custom target capture/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 custom target capture/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 custom target capture/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 custom target capture/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/subdir/data.dat"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/catter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/catter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/catter.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/catter.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -output = sys.argv[-1] -inputs = sys.argv[1:-1] - -with open(output, 'w') as ofile: - ofile.write('#pragma once\n') - for i in inputs: - with open(i, 'r') as ifile: - content = ifile.read() - ofile.write(content) - ofile.write('\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/gen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/gen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -ifile = sys.argv[1] -ofile = sys.argv[2] - -with open(ifile, 'r') as f: - resname = f.readline().strip() - -templ = 'const char %s[] = "%s";\n' -with open(ofile, 'w') as f: - f.write(templ % (resname, resname)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include - -#include"alltogether.h" - -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/meson.build" 2020-01-07 21:07:56.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -project('generatorcustom', 'c') - -creator = find_program('gen.py') -catter = find_program('catter.py') - -gen = generator(creator, - output: '@BASENAME@.h', - arguments : ['@INPUT@', '@OUTPUT@']) - -hs = gen.process('res1.txt', 'res2.txt') - -allinone = custom_target('alltogether', - input : hs, - output : 'alltogether.h', - command : [catter, '@INPUT@', '@OUTPUT@']) - -executable('proggie', 'main.c', allinone) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/res1.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/res1.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/res1.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/res1.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -res1 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/res2.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/res2.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/109 generatorcustom/res2.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/109 generatorcustom/res2.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -res2 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/10 man install/foo.fr.1" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/10 man install/foo.fr.1" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/10 man install/foo.fr.1" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/10 man install/foo.fr.1" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1 @@ +this is a man page of foo.1 its contents are irrelevant diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/10 man install/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/10 man install/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/10 man install/installed_files.txt" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/10 man install/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -usr/share/man/man1/foo.1 -usr/share/man/man2/bar.2 -usr/share/man/man1/vanishing.1 -usr/share/man/man2/vanishing.2 -usr/share/man/man1/baz.1 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/10 man install/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/10 man install/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/10 man install/meson.build" 2020-01-07 21:06:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/10 man install/meson.build" 2021-10-23 16:47:49.000000000 +0000 @@ -1,6 +1,7 @@ project('man install', 'c') m1 = install_man('foo.1') m2 = install_man('bar.2') +m3 = install_man('foo.fr.1', locale: 'fr') install_man('vanishing/vanishing.2') subdir('vanishing') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/10 man install/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/10 man install/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/10 man install/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/10 man install/test.json" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "installed": [ + { "type": "file", "file": "usr/share/man/man1/foo.1" }, + { "type": "file", "file": "usr/share/man/fr/man1/foo.1" }, + { "type": "file", "file": "usr/share/man/man2/bar.2" }, + { "type": "file", "file": "usr/share/man/man1/vanishing.1" }, + { "type": "file", "file": "usr/share/man/man2/vanishing.2" }, + { "type": "file", "file": "usr/share/man/man1/baz.1" } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 allgenerate/converter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 allgenerate/converter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 allgenerate/converter.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 allgenerate/converter.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys + +ifile = sys.argv[1] +ofile = sys.argv[2] + +open(ofile, 'w').write(open(ifile).read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 allgenerate/foobar.cpp.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 allgenerate/foobar.cpp.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 allgenerate/foobar.cpp.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 allgenerate/foobar.cpp.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I am a program.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 allgenerate/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 allgenerate/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 allgenerate/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 allgenerate/meson.build" 2021-10-23 16:49:04.000000000 +0000 @@ -0,0 +1,20 @@ +# Must have two languages here to exercise linker language +# selection bug +project('all sources generated', 'c', 'cpp') + +comp = find_program('converter.py') + +g = generator(comp, + output : '@BASENAME@', + arguments : ['@INPUT@', '@OUTPUT@']) + +c = g.process('foobar.cpp.in') + +prog = executable('genexe', c) + +c2 = custom_target('c2gen', + output : '@BASENAME@', + input : 'foobar.cpp.in', + command : [comp, '@INPUT@', '@OUTPUT@']) + +prog2 = executable('genexe2', c2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 multiple dir configure file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 multiple dir configure file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 multiple dir configure file/meson.build" 2020-01-07 21:07:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 multiple dir configure file/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('multiple dir configure file', 'c') - -subdir('subdir') - -configure_file(input : 'subdir/someinput.in', - output : 'outputhere', - copy: true) - -configure_file(input : cfile1, - output : '@BASENAME@', - copy: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 multiple dir configure file/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 multiple dir configure file/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/110 multiple dir configure file/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/110 multiple dir configure file/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -configure_file(input : 'someinput.in', - output : 'outputsubdir', - install : false, - copy: true) - -py3 = import('python3').find_python() - -cfile1 = configure_file(input : 'foo.txt', - output : 'foo.h.in', - capture : true, - command : [py3, '-c', 'print("#mesondefine FOO_BAR")']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 pathjoin/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 pathjoin/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 pathjoin/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 pathjoin/meson.build" 2021-11-02 19:58:13.000000000 +0000 @@ -0,0 +1,27 @@ +project('pathjoin', 'c') + +# Test string-args form since that is the canonical way +assert(join_paths('foo') == 'foo', 'Single argument join is broken') +assert(join_paths('foo', 'bar') == 'foo/bar', 'Path joining is broken') +assert(join_paths('foo', 'bar', 'baz') == 'foo/bar/baz', 'Path joining is broken') +assert(join_paths('/foo', 'bar') == '/foo/bar', 'Path joining is broken') +assert(join_paths('foo', '/bar') == '/bar', 'Absolute path joining is broken') +assert(join_paths('/foo', '/bar') == '/bar', 'Absolute path joining is broken') +assert(join_paths('/foo', '') == '/foo/', 'Trailing / on path') + +# Test array form since people are using that too +assert(join_paths(['foo']) == 'foo', 'Single argument join is broken') +assert(join_paths(['foo', 'bar']) == 'foo/bar', 'Path joining is broken') +assert(join_paths(['foo', 'bar', 'baz']) == 'foo/bar/baz', 'Path joining is broken') +assert(join_paths(['/foo', 'bar']) == '/foo/bar', 'Path joining is broken') +assert(join_paths(['foo', '/bar']) == '/bar', 'Absolute path joining is broken') +assert(join_paths(['/foo', '/bar']) == '/bar', 'Absolute path joining is broken') +assert(join_paths(['/foo', '']) == '/foo/', 'Trailing / on path') + +# Division operator should do the same as join_paths +assert('foo' / 'bar' == 'foo/bar', 'Path division is broken') +assert('foo' /'bar' /'baz' == 'foo/bar/baz', 'Path division is broken') +assert('/foo' / 'bar' == '/foo/bar', 'Path division is broken') +assert('foo' / '/bar' == '/bar', 'Absolute path division is broken') +assert('/foo' / '/bar' == '/bar', 'Absolute path division is broken') +assert('/foo' / '' == '/foo/', 'Trailing / on path') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/asm output/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/asm output/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/asm output/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/asm output/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -configure_file(output : 'blank.txt', configuration : configuration_data()) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/comparer.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/comparer.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/comparer.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/comparer.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include "comparer.h" - -#ifndef COMPARER_INCLUDED -#error "comparer.h not included" -#endif - -#define COMPARE_WITH "foo\\bar" /* This is the literal `foo\bar` */ - -int main(void) { - if (strcmp (DEF_WITH_BACKSLASH, COMPARE_WITH)) { - printf ("Arg string is quoted incorrectly: %s instead of %s\n", - DEF_WITH_BACKSLASH, COMPARE_WITH); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/comparer-end.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/comparer-end.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/comparer-end.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/comparer-end.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include "comparer.h" - -#ifndef COMPARER_INCLUDED -#error "comparer.h not included" -#endif - -#define COMPARE_WITH "foo\\bar\\" /* This is `foo\bar\` */ - -int main(void) { - if (strcmp (DEF_WITH_BACKSLASH, COMPARE_WITH)) { - printf ("Arg string is quoted incorrectly: %s vs %s\n", - DEF_WITH_BACKSLASH, COMPARE_WITH); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/comparer-end-notstring.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/comparer-end-notstring.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/comparer-end-notstring.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/comparer-end-notstring.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#include "comparer.h" - -#ifndef COMPARER_INCLUDED -#error "comparer.h not included" -#endif - -/* This converts foo\\\\bar\\\\ to "foo\\bar\\" (string literal) */ -#define Q(x) #x -#define QUOTE(x) Q(x) - -#define COMPARE_WITH "foo\\bar\\" /* This is the literal `foo\bar\` */ - -int main(void) { - if(strcmp(QUOTE(DEF_WITH_BACKSLASH), COMPARE_WITH)) { - printf("Arg string is quoted incorrectly: %s instead of %s\n", - QUOTE(DEF_WITH_BACKSLASH), COMPARE_WITH); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/include/comparer.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/include/comparer.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/include/comparer.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/include/comparer.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -#include -#include - -#define COMPARER_INCLUDED diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/111 spaces backslash/meson.build" 2020-01-07 21:07:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/111 spaces backslash/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -project('comparer', 'c') - -# Added manually as a c_arg to test handling of include paths with backslashes -# and spaces. This is especially useful on Windows in vcxproj files since it -# stores include directories in a separate element that has its own -# context-specific escaping/quoting. -include_dir = meson.current_source_dir() + '/include' -default_c_args = ['-I' + include_dir] - -if meson.get_compiler('c').get_argument_syntax() == 'msvc' - default_c_args += ['/Faasm output\\'] - # Hack to create the 'asm output' directory in the builddir - subdir('asm output') -endif - -# Path can contain \. Here we're sending `"foo\bar"`. -test('backslash quoting', - executable('comparer', 'comparer.c', - c_args : default_c_args + ['-DDEF_WITH_BACKSLASH="foo\\bar"'])) -# Path can end in \ without any special quoting. Here we send `"foo\bar\"`. -test('backslash end quoting', - executable('comparer-end', 'comparer-end.c', - c_args : default_c_args + ['-DDEF_WITH_BACKSLASH="foo\\bar\\"'])) -# Path can (really) end in \ if we're not passing a string literal without any -# special quoting. Here we're sending `foo\bar\`. -test('backslash end quoting when not a string literal', - executable('comparer-end-notstring', 'comparer-end-notstring.c', - c_args : default_c_args + ['-DDEF_WITH_BACKSLASH=foo\\bar\\'])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/meson.build" 2021-10-23 16:49:06.000000000 +0000 @@ -0,0 +1,2 @@ +project('proj', 'c') +subdir('prog') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/prog/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/prog/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/prog/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/prog/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +subproject('sub') +libSub = dependency('sub', fallback: ['sub', 'libSub']) + +exe = executable('prog', 'prog.c', dependencies: libSub) +test('subdir subproject', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/prog/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/prog/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/prog/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/prog/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int main(void) { + return sub(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('sub', 'c') +lib = static_library('sub', 'sub.c') +libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/subprojects/sub/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/subprojects/sub/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/subprojects/sub/sub.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/subprojects/sub/sub.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "sub.h" + +int sub(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/subprojects/sub/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/subprojects/sub/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 subdir subproject/subprojects/sub/sub.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 subdir subproject/subprojects/sub/sub.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef SUB_H +#define SUB_H + +int sub(void); + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 ternary/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 ternary/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/112 ternary/meson.build" 2020-01-07 21:07:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/112 ternary/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -project('ternary operator', 'c') - -x = true -one = true ? 1 : error('False branch should not be evaluated') -two = false ? error('True branch should not be evaluated.') : 2 -three = '@0@'.format(x ? 'yes' : 'no') -four = [x ? '0' : '1'] - -assert(one == 1, 'Return value from ternary true is wrong.') -assert(two == 2, 'Return value from ternary false is wrong.') -assert(three == 'yes', 'Return value for ternary inside method call is wrong.') -assert(four == ['0'], 'Return value for ternary inside of list is wrong.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 custom target capture/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 custom target capture/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 custom target capture/data_source.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 custom target capture/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 custom target capture/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 custom target capture/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 custom target capture/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 custom target capture/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/subdir/data.dat diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 custom target capture/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 custom target capture/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 custom target capture/meson.build" 2020-01-07 21:08:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 custom target capture/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -project('custom target', 'c') - -python3 = import('python3').find_python() - -# Note that this will not add a dependency to the compiler executable. -# Code will not be rebuilt if it changes. -comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') - -mytarget = custom_target('bindat', - output : 'data.dat', - input : 'data_source.txt', - capture : true, - command : [python3, comp, '@INPUT@'], - install : true, - install_dir : 'subdir' -) - -ct_output_exists = '''import os, sys -if not os.path.exists(sys.argv[1]): - print("could not find {!r} in {!r}".format(sys.argv[1], os.getcwd())) - sys.exit(1) -''' - -test('capture-wrote', python3, args : ['-c', ct_output_exists, mytarget]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 custom target capture/my_compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 custom target capture/my_compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 custom target capture/my_compiler.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 custom target capture/my_compiler.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -if __name__ == '__main__': - if len(sys.argv) != 2: - print(sys.argv[0], 'input_file') - sys.exit(1) - with open(sys.argv[1]) as f: - ifile = f.read() - if ifile != 'This is a text only input file.\n': - print('Malformed input') - sys.exit(1) - print('This is a binary output file.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 interpreter copy mutable var on assignment/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 interpreter copy mutable var on assignment/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/113 interpreter copy mutable var on assignment/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/113 interpreter copy mutable var on assignment/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,19 @@ +project('foo', 'c') + +a = configuration_data() +a.set('HELLO', 1) + +b = a + +assert(a.has('HELLO'), 'Original config data should be set on a') +assert(b.has('HELLO'), 'Original config data should be set on copy') + +configure_file(output : 'b.h', configuration : b) + +# This should still work, as we didn't use the original above but a copy! +a.set('WORLD', 1) + +assert(a.has('WORLD'), 'New config data should have been set') +assert(not b.has('WORLD'), 'New config data set should not affect var copied earlier') + +configure_file(output : 'a.h', configuration : a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/114 allgenerate/converter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/114 allgenerate/converter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/114 allgenerate/converter.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/114 allgenerate/converter.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -ifile = sys.argv[1] -ofile = sys.argv[2] - -open(ofile, 'w').write(open(ifile).read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/114 allgenerate/foobar.cpp.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/114 allgenerate/foobar.cpp.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/114 allgenerate/foobar.cpp.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/114 allgenerate/foobar.cpp.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I am a program.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/114 allgenerate/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/114 allgenerate/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/114 allgenerate/meson.build" 2020-01-07 21:08:03.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/114 allgenerate/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -# Must have two languages here to exercise linker language -# selection bug -project('all sources generated', 'c', 'cpp') - -comp = find_program('converter.py') - -g = generator(comp, - output : '@BASENAME@', - arguments : ['@INPUT@', '@OUTPUT@']) - -c = g.process('foobar.cpp.in') - -prog = executable('genexe', c) - -c2 = custom_target('c2gen', - output : '@BASENAME@', - input : 'foobar.cpp.in', - command : [comp, '@INPUT@', '@OUTPUT@']) - -prog2 = executable('genexe2', c2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/114 skip/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/114 skip/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/114 skip/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/114 skip/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +project('skip', 'c') + +error('MESON_SKIP_TEST this test is always skipped.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 pathjoin/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 pathjoin/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 pathjoin/meson.build" 2020-01-07 21:08:03.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 pathjoin/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -project('pathjoin', 'c') - -# Test string-args form since that is the canonical way -assert(join_paths('foo') == 'foo', 'Single argument join is broken') -assert(join_paths('foo', 'bar') == 'foo/bar', 'Path joining is broken') -assert(join_paths('foo', 'bar', 'baz') == 'foo/bar/baz', 'Path joining is broken') -assert(join_paths('/foo', 'bar') == '/foo/bar', 'Path joining is broken') -assert(join_paths('foo', '/bar') == '/bar', 'Absolute path joining is broken') -assert(join_paths('/foo', '/bar') == '/bar', 'Absolute path joining is broken') - -# Test array form since people are using that too -assert(join_paths(['foo']) == 'foo', 'Single argument join is broken') -assert(join_paths(['foo', 'bar']) == 'foo/bar', 'Path joining is broken') -assert(join_paths(['foo', 'bar', 'baz']) == 'foo/bar/baz', 'Path joining is broken') -assert(join_paths(['/foo', 'bar']) == '/foo/bar', 'Path joining is broken') -assert(join_paths(['foo', '/bar']) == '/bar', 'Absolute path joining is broken') -assert(join_paths(['/foo', '/bar']) == '/bar', 'Absolute path joining is broken') - -# Division operator should do the same as join_paths -assert('foo' / 'bar' == 'foo/bar', 'Path division is broken') -assert('foo' /'bar' /'baz' == 'foo/bar/baz', 'Path division is broken') -assert('/foo' / 'bar' == '/foo/bar', 'Path division is broken') -assert('foo' / '/bar' == '/bar', 'Absolute path division is broken') -assert('/foo' / '/bar' == '/bar', 'Absolute path division is broken') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/exe.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/exe.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/exe.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/exe.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,27 @@ +#ifndef PROJECT_OPTION +#error +#endif + +#ifndef PROJECT_OPTION_1 +#error +#endif + +#ifndef GLOBAL_ARGUMENT +#error +#endif + +#ifdef SUBPROJECT_OPTION +#error +#endif + +#ifdef OPTION_CPP +#error +#endif + +#ifndef PROJECT_OPTION_C_CPP +#error +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/exe.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/exe.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/exe.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/exe.cpp" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,27 @@ +#ifdef PROJECT_OPTION +#error +#endif + +#ifdef PROJECT_OPTION_1 +#error +#endif + +#ifdef GLOBAL_ARGUMENT +#error +#endif + +#ifdef SUBPROJECT_OPTION +#error +#endif + +#ifndef PROJECT_OPTION_CPP +#error +#endif + +#ifndef PROJECT_OPTION_C_CPP +#error +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/meson.build" 2021-10-23 16:49:08.000000000 +0000 @@ -0,0 +1,17 @@ +project('project options tester', 'c', 'cpp', + version : '2.3.4', + license : 'mylicense') + +add_global_arguments('-DGLOBAL_ARGUMENT', language: 'c') +add_project_arguments('-DPROJECT_OPTION', language: 'c') +add_project_arguments('-DPROJECT_OPTION_CPP', language: 'cpp') +add_project_arguments('-DPROJECT_OPTION_C_CPP', language: ['c', 'cpp']) + +sub = subproject('subexe', version : '1.0.0') + +add_project_arguments('-DPROJECT_OPTION_1', language: 'c') + +e = executable('exe', 'exe.c') +e = executable('execpp', 'exe.cpp') +test('exetest', e) +test('execpptest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/subprojects/subexe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/subprojects/subexe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/subprojects/subexe/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/subprojects/subexe/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +project('subproject', 'c', + version : '1.0.0', + license : ['sublicense1', 'sublicense2']) + +if not meson.is_subproject() + error('Claimed to be master project even though we are a subproject.') +endif + +assert(meson.project_name() == 'subproject', 'Incorrect subproject name') + +add_project_arguments('-DSUBPROJECT_OPTION', language: 'c') +e = executable('subexe', 'subexe.c') +test('subexetest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/subprojects/subexe/subexe.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/subprojects/subexe/subexe.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/115 subproject project arguments/subprojects/subexe/subexe.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/115 subproject project arguments/subprojects/subexe/subexe.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,27 @@ +#ifdef PROJECT_OPTION +#error +#endif + +#ifdef PROJECT_OPTION_1 +#error +#endif + +#ifdef PROJECT_OPTION_C_CPP +#error +#endif + +#ifndef GLOBAL_ARGUMENT +#error +#endif + +#ifndef SUBPROJECT_OPTION +#error +#endif + +#ifdef OPTION_CPP +#error +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/meson.build" 2020-01-07 21:08:06.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('proj', 'c') -subdir('prog') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/prog/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/prog/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/prog/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/prog/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -subproject('sub') -libSub = dependency('sub', fallback: ['sub', 'libSub']) - -exe = executable('prog', 'prog.c', dependencies: libSub) -test('subdir subproject', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/prog/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/prog/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/prog/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/prog/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -int main(void) { - return sub(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/subprojects/sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('sub', 'c') -lib = static_library('sub', 'sub.c') -libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/subprojects/sub/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/subprojects/sub/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/subprojects/sub/sub.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/subprojects/sub/sub.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "sub.h" - -int sub(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/subprojects/sub/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/subprojects/sub/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 subdir subproject/subprojects/sub/sub.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 subdir subproject/subprojects/sub/sub.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef SUB_H -#define SUB_H - -int sub(void); - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 test skip/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 test skip/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 test skip/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 test skip/meson.build" 2021-10-23 16:49:07.000000000 +0000 @@ -0,0 +1,4 @@ +project('test skip', 'c') + +exe_test_skip = executable('test_skip', 'test_skip.c') +test('test_skip', exe_test_skip) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 test skip/test_skip.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 test skip/test_skip.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/116 test skip/test_skip.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/116 test skip/test_skip.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 77; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 interpreter copy mutable var on assignment/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 interpreter copy mutable var on assignment/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 interpreter copy mutable var on assignment/meson.build" 2020-01-07 21:08:06.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 interpreter copy mutable var on assignment/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -project('foo', 'c') - -a = configuration_data() -a.set('HELLO', 1) - -b = a - -assert(a.has('HELLO'), 'Original config data should be set on a') -assert(b.has('HELLO'), 'Original config data should be set on copy') - -configure_file(output : 'b.h', configuration : b) - -# This should still work, as we didn't use the original above but a copy! -a.set('WORLD', 1) - -assert(a.has('WORLD'), 'New config data should have been set') -assert(not b.has('WORLD'), 'New config data set should not affect var copied earlier') - -configure_file(output : 'a.h', configuration : a) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/meson.build" 2021-10-23 16:49:10.000000000 +0000 @@ -0,0 +1,40 @@ +project('shared module', 'c') + +c = meson.get_compiler('c') + +# Windows UWP doesn't support the ToolHelp API we use in this test to emulate +# runtime symbol resolution. +if host_machine.system() == 'windows' + if not c.compiles(''' +#include +#include + +HANDLE func(void) +{ + return CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); +} +''') + error('MESON_SKIP_TEST Windows UWP does not support this test.') + endif +endif + +dl = c.find_library('dl', required : false) +l = shared_library('runtime', 'runtime.c') +# Do NOT link the module with the runtime library. This +# is a common approach for plugins that are only used +# with dlopen. Any symbols are resolved dynamically +# at runtime. This requires extra help on Windows, so +# should be avoided unless really necessary. +m = shared_module('mymodule', 'module.c') +e = executable('prog', 'prog.c', + link_with : l, export_dynamic : true, dependencies : dl) +test('import test', e, args : m) + +# Same as above, but module created with build_target() +m2 = build_target('mymodule2', 'module.c', target_type: 'shared_module') +test('import test 2', e, args : m2) + +# Shared module that does not export any symbols +shared_module('nosyms', 'nosyms.c', + install : true, + install_dir : join_paths(get_option('libdir'), 'modules')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/module.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/module.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,96 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) + +#include + +typedef int (*fptr) (void); + +#ifdef __CYGWIN__ + +#include + +fptr find_any_f (const char *name) { + return (fptr) dlsym(RTLD_DEFAULT, name); +} +#else /* _WIN32 */ + +#include +#include + +static wchar_t* +win32_get_last_error (void) +{ + wchar_t *msg = NULL; + + FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_IGNORE_INSERTS + | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError (), 0, + (LPWSTR) &msg, 0, NULL); + return msg; +} + +/* Unlike Linux and OS X, when a library is loaded, all the symbols aren't + * loaded into a single namespace. You must fetch the symbol by iterating over + * all loaded modules. Code for finding the function from any of the loaded + * modules is taken from gmodule.c in glib */ +fptr find_any_f (const char *name) { + fptr f; + HANDLE snapshot; + MODULEENTRY32 me32; + + snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0); + if (snapshot == (HANDLE) -1) { + wchar_t *msg = win32_get_last_error(); + printf("Could not get snapshot: %S\n", msg); + return 0; + } + + me32.dwSize = sizeof (me32); + + f = NULL; + if (Module32First (snapshot, &me32)) { + do { + if ((f = (fptr) GetProcAddress (me32.hModule, name)) != NULL) + break; + } while (Module32Next (snapshot, &me32)); + } + + CloseHandle (snapshot); + return f; +} +#endif + +int DLL_PUBLIC func(void) { + fptr f; + + f = find_any_f ("func_from_language_runtime"); + if (f != NULL) + return f(); + printf ("Could not find function\n"); + return 1; +} + +#else +/* + * Shared modules often have references to symbols that are not defined + * at link time, but which will be provided from deps of the executable that + * dlopens it. We need to make sure that this works, i.e. that we do + * not pass -Wl,--no-undefined when linking modules. + */ +int func_from_language_runtime(void); + +int DLL_PUBLIC func(void) { + return func_from_language_runtime(); +} +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/nosyms.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/nosyms.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/nosyms.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/nosyms.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +static int +func_not_exported (void) { + return 99; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,103 @@ + +#include + +int func_from_language_runtime(void); +typedef int (*fptr) (void); + +#ifdef _WIN32 + +#include + +static wchar_t* +win32_get_last_error (void) +{ + wchar_t *msg = NULL; + + FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_IGNORE_INSERTS + | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError (), 0, + (LPWSTR) &msg, 0, NULL); + return msg; +} + +int main(int argc, char **argv) +{ + HINSTANCE handle; + fptr importedfunc; + int expected, actual; + int ret = 1; + if(argc==0) {}; + + handle = LoadLibraryA (argv[1]); + if (!handle) { + wchar_t *msg = win32_get_last_error (); + printf ("Could not open %s: %S\n", argv[1], msg); + goto nohandle; + } + + importedfunc = (fptr) GetProcAddress (handle, "func"); + if (importedfunc == NULL) { + wchar_t *msg = win32_get_last_error (); + printf ("Could not find 'func': %S\n", msg); + goto out; + } + + actual = importedfunc (); + expected = func_from_language_runtime (); + if (actual != expected) { + printf ("Got %i instead of %i\n", actual, expected); + goto out; + } + + ret = 0; +out: + FreeLibrary (handle); +nohandle: + return ret; +} + +#else + +#include +#include + +int main(int argc, char **argv) { + void *dl; + fptr importedfunc; + int expected, actual; + char *error; + int ret = 1; + if(argc==0) {}; + + dlerror(); + dl = dlopen(argv[1], RTLD_LAZY); + error = dlerror(); + if(error) { + printf("Could not open %s: %s\n", argv[1], error); + goto nodl; + } + + importedfunc = (fptr) dlsym(dl, "func"); + if (importedfunc == NULL) { + printf ("Could not find 'func'\n"); + goto out; + } + + assert(importedfunc != func_from_language_runtime); + + actual = (*importedfunc)(); + expected = func_from_language_runtime (); + if (actual != expected) { + printf ("Got %i instead of %i\n", actual, expected); + goto out; + } + + ret = 0; +out: + dlclose(dl); +nodl: + return ret; +} + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/runtime.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/runtime.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/runtime.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/runtime.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +/* + * This file pretends to be a language runtime that supports extension + * modules. + */ + +int DLL_PUBLIC func_from_language_runtime(void) { + return 86; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/117 shared module/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/117 shared module/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "expr", "file": "usr/lib/modules/libnosyms?so"}, + {"type": "implibempty", "file": "usr/lib/modules/libnosyms"}, + {"type": "pdb", "file": "usr/lib/modules/nosyms"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include + +unsigned square_unsigned (unsigned a); + +int main(void) +{ + unsigned int ret = square_unsigned (2); + if (ret != 4) { + printf("Got %u instead of 4\n", ret); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#include + +extern "C" { + unsigned square_unsigned (unsigned a); +} + +int main (void) +{ + unsigned int ret = square_unsigned (2); + if (ret != 4) { + printf("Got %u instead of 4\n", ret); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,79 @@ +project('llvm-ir', 'c', 'cpp') + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: asm not supported with the Xcode backend. Patches welcome.') +endif + +cpu = host_machine.cpu_family() +supported_cpus = ['arm', 'aarch64', 'x86', 'x86_64'] + +foreach lang : ['c', 'cpp'] + cc = meson.get_compiler(lang) + cc_id = cc.get_id() + ## Build a trivial executable with mixed LLVM IR source + if cc_id == 'clang' + e = executable('square_ir_' + lang, 'square.ll', 'main.' + lang) + test('test IR square' + lang, e) + endif + ## Build a trivial executable with mixed assembly source + # This also helps test whether cc.symbols_have_underscore_prefix() is working + # properly. This is done by assembling some assembly into an object that will + # provide the unsigned_squared() symbol to main.c/cpp. This requires the + # C symbol mangling to be known in advance. + if cc.symbols_have_underscore_prefix() + uscore_args = ['-DMESON_TEST__UNDERSCORE_SYMBOL'] + message('underscore is prefixed') + else + uscore_args = [] + message('underscore is NOT prefixed') + endif + square_base = 'square-' + cpu + square_impl = square_base + '.S' + # MSVC cannot directly compile assembly files, so we pass it through the + # cl.exe pre-processor first and then assemble it with ml.exe or armasm.exe + # assembler. Then we can link it into the executable. + if cc.get_argument_syntax() == 'msvc' + cl = cc.cmd_array() + if cpu == 'x86' + asmcmd = 'ml' + elif cpu == 'x86_64' + asmcmd = 'ml64' + elif cpu == 'aarch64' + asmcmd = 'armasm64' + elif cpu == 'arm' + asmcmd = 'armasm' + else + error('Unsupported cpu family: "' + cpu + '"') + endif + ml = find_program(asmcmd, required: false) + if not ml.found() + error('MESON_SKIP_TEST: Microsoft assembler (ml/armasm) not found') + endif + # Preprocess file (ml doesn't support pre-processing) + # Force the input to be C (/Tc) because ICL otherwise assumes it's an object (.obj) file + preproc_name = lang + square_base + '.i' + square_preproc = custom_target(lang + square_impl + 'preproc', + input : square_impl, + output : preproc_name, + command : [cl, '/nologo', '/EP', '/P', '/Fi' + preproc_name, '/Tc', '@INPUT@'] + uscore_args) + # Use assembled object file instead of the original .S assembly source + if asmcmd.startswith('armasm') + square_impl = custom_target(lang + square_impl, + input : square_preproc, + output : lang + square_base + '.obj', + command : [ml, '-nologo', '-o', '@OUTPUT@', '@INPUT@']) + else + square_impl = custom_target(lang + square_impl, + input : square_preproc, + output : lang + square_base + '.obj', + command : [ml, '/nologo', '/safeseh', '/Fo', '@OUTPUT@', '/c', '@INPUT@']) + endif + endif + if supported_cpus.contains(cpu) + e = executable('square_asm_' + lang, square_impl, 'main.' + lang, + c_args : uscore_args, cpp_args : uscore_args) + test('test ASM square' + lang, e) + elif cc_id != 'clang' + error('MESON_SKIP_TEST: Unsupported cpu: "' + cpu + '", and LLVM not found') + endif +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square-aarch64.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square-aarch64.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square-aarch64.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square-aarch64.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,29 @@ +#include "symbol-underscore.h" + +#ifdef _MSC_VER + + AREA _TEXT, ARM64, CODE, READONLY + + EXPORT SYMBOL_NAME(square_unsigned) +SYMBOL_NAME(square_unsigned) PROC + mul x1, x0, x0 + mov x0, x1 + ret +SYMBOL_NAME(square_unsigned) ENDP + + END + +#else + +.text +.globl SYMBOL_NAME(square_unsigned) +# ifdef __linux__ +.type square_unsigned, %function +#endif + +SYMBOL_NAME(square_unsigned): + mul x1, x0, x0 + mov x0, x1 + ret + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square-arm.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square-arm.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square-arm.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square-arm.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,29 @@ +#include "symbol-underscore.h" + +#ifdef _MSC_VER + + AREA _TEXT, ARM, CODE, READONLY + + EXPORT SYMBOL_NAME(square_unsigned) +SYMBOL_NAME(square_unsigned) PROC + mul r1, r0, r0 + mov r0, r1 + mov pc, lr +SYMBOL_NAME(square_unsigned) ENDP + + END + +#else + +.text +.globl SYMBOL_NAME(square_unsigned) +# ifdef __linux__ +.type square_unsigned, %function +#endif + +SYMBOL_NAME(square_unsigned): + mul r1, r0, r0 + mov r0, r1 + mov pc, lr + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square.ll" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square.ll" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square.ll" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square.ll" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +define i32 @square_unsigned(i32 %a) { + %1 = mul i32 %a, %a + ret i32 %1 +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square-x86_64.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square-x86_64.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square-x86_64.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square-x86_64.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,37 @@ +#include "symbol-underscore.h" + +#ifdef _MSC_VER /* MSVC on Windows */ + +PUBLIC SYMBOL_NAME(square_unsigned) +_TEXT SEGMENT + +SYMBOL_NAME(square_unsigned) PROC + mov eax, ecx + imul eax, eax + ret +SYMBOL_NAME(square_unsigned) ENDP + +_TEXT ENDS +END + +#else + +.text +.globl SYMBOL_NAME(square_unsigned) +# ifdef __linux__ +.type square_unsigned, %function +#endif + +# if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ +SYMBOL_NAME(square_unsigned): + imull %ecx, %ecx + movl %ecx, %eax + retq +# else /* sysvabi */ +SYMBOL_NAME(square_unsigned): + imull %edi, %edi + movl %edi, %eax + retq +# endif + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square-x86.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square-x86.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/square-x86.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/square-x86.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,36 @@ +#include "symbol-underscore.h" + +/* This sadly doesn't test the symbol underscore stuff. I can't figure out how + * to not use an automatic stdcall mechanism and do everything manually. */ +#ifdef _MSC_VER + +.386 +.MODEL FLAT, C + +PUBLIC square_unsigned +_TEXT SEGMENT + +square_unsigned PROC var1:DWORD + mov eax, var1 + imul eax, eax + ret + +square_unsigned ENDP + +_TEXT ENDS +END + +#else + +.text +.globl SYMBOL_NAME(square_unsigned) +# ifdef __linux__ +.type square_unsigned, %function +#endif + +SYMBOL_NAME(square_unsigned): + movl 4(%esp), %eax + imull %eax, %eax + retl + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/symbol-underscore.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/symbol-underscore.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 llvm ir and assembly/symbol-underscore.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 llvm ir and assembly/symbol-underscore.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#if defined(MESON_TEST__UNDERSCORE_SYMBOL) +# define SYMBOL_NAME(name) _##name +#else +# define SYMBOL_NAME(name) name +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 skip/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 skip/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/118 skip/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/118 skip/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('skip', 'c') - -error('MESON_SKIP_TEST this test is always skipped.') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/meson.build" 2021-10-23 16:49:11.000000000 +0000 @@ -0,0 +1,33 @@ +project('c++ and assembly test') +add_languages('cpp') + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: asm not supported with the Xcode backend. Patches welcome.') +endif + +cpp = meson.get_compiler('cpp') +cpu = host_machine.cpu_family() + +supported_cpus = ['arm', 'x86', 'x86_64'] + +if not supported_cpus.contains(cpu) + error('MESON_SKIP_TEST unsupported cpu:' + cpu) +endif + +if cpp.symbols_have_underscore_prefix() + add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language : 'cpp') +endif + +sources = ['trivial.cc'] +# If the compiler cannot compile assembly, don't use it +if not ['msvc', 'clang-cl', 'intel-cl'].contains(meson.get_compiler('cpp').get_id()) + sources += ['retval-' + cpu + '.S'] + cpp_args = ['-DUSE_ASM'] + message('Using ASM') +else + cpp_args = ['-DNO_USE_ASM'] +endif + +exe = executable('trivialprog', sources, + cpp_args : cpp_args) +test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/retval-arm.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/retval-arm.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/retval-arm.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/retval-arm.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) +# ifdef __linux__ +.type get_retval, %function +#endif + +SYMBOL_NAME(get_retval): + mov r0, #0 + mov pc, lr diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/retval-x86_64.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/retval-x86_64.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/retval-x86_64.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/retval-x86_64.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) +# ifdef __linux__ +.type get_retval, %function +#endif + +SYMBOL_NAME(get_retval): + xorl %eax, %eax + retq diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/retval-x86.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/retval-x86.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/retval-x86.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/retval-x86.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) +# ifdef __linux__ +.type get_retval, %function +#endif + +SYMBOL_NAME(get_retval): + xorl %eax, %eax + retl diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/symbol-underscore.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/symbol-underscore.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/symbol-underscore.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/symbol-underscore.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#if defined(MESON_TEST__UNDERSCORE_SYMBOL) +# define SYMBOL_NAME(name) _##name +#else +# define SYMBOL_NAME(name) name +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/trivial.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/trivial.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 cpp and asm/trivial.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 cpp and asm/trivial.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include + +extern "C" { + int get_retval(void); +} + +int main(void) { + std::cout << "C++ seems to be working." << std::endl; +#if defined(USE_ASM) + return get_retval(); +#elif defined(NO_USE_ASM) + return 0; +#else + #error "Forgot to pass asm define" +#endif +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/exe.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/exe.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/exe.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/exe.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#ifndef PROJECT_OPTION -#error -#endif - -#ifndef PROJECT_OPTION_1 -#error -#endif - -#ifndef GLOBAL_ARGUMENT -#error -#endif - -#ifdef SUBPROJECT_OPTION -#error -#endif - -#ifdef OPTION_CPP -#error -#endif - -#ifndef PROJECT_OPTION_C_CPP -#error -#endif - -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/exe.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/exe.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/exe.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/exe.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -#ifdef PROJECT_OPTION -#error -#endif - -#ifdef PROJECT_OPTION_1 -#error -#endif - -#ifdef GLOBAL_ARGUMENT -#error -#endif - -#ifdef SUBPROJECT_OPTION -#error -#endif - -#ifndef PROJECT_OPTION_CPP -#error -#endif - -#ifndef PROJECT_OPTION_C_CPP -#error -#endif - -int main(void) { - return 0; -} - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/meson.build" 2020-01-07 21:08:08.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -project('project options tester', 'c', 'cpp', - version : '2.3.4', - license : 'mylicense') - -add_global_arguments('-DGLOBAL_ARGUMENT', language: 'c') -add_project_arguments('-DPROJECT_OPTION', language: 'c') -add_project_arguments('-DPROJECT_OPTION_CPP', language: 'cpp') -add_project_arguments('-DPROJECT_OPTION_C_CPP', language: ['c', 'cpp']) - -sub = subproject('subexe', version : '1.0.0') - -add_project_arguments('-DPROJECT_OPTION_1', language: 'c') - -e = executable('exe', 'exe.c') -e = executable('execpp', 'exe.cpp') -test('exetest', e) -test('execpptest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/subprojects/subexe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/subprojects/subexe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/subprojects/subexe/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/subprojects/subexe/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('subproject', 'c', - version : '1.0.0', - license : ['sublicense1', 'sublicense2']) - -if not meson.is_subproject() - error('Claimed to be master project even though we are a subproject.') -endif - -assert(meson.project_name() == 'subproject', 'Incorrect subproject name') - -add_project_arguments('-DSUBPROJECT_OPTION', language: 'c') -e = executable('subexe', 'subexe.c') -test('subexetest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/subprojects/subexe/subexe.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/subprojects/subexe/subexe.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/119 subproject project arguments/subprojects/subexe/subexe.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/119 subproject project arguments/subprojects/subexe/subexe.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#ifdef PROJECT_OPTION -#error -#endif - -#ifdef PROJECT_OPTION_1 -#error -#endif - -#ifdef PROJECT_OPTION_C_CPP -#error -#endif - -#ifndef GLOBAL_ARGUMENT -#error -#endif - -#ifndef SUBPROJECT_OPTION -#error -#endif - -#ifdef OPTION_CPP -#error -#endif - -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/11 subdir/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/11 subdir/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/11 subdir/subdir/meson.build" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/11 subdir/subdir/meson.build" 2021-04-27 06:49:45.000000000 +0000 @@ -1 +1,2 @@ -executable('prog', 'prog.c') +prog = executable('prog', 'prog.c') +test('subdirprog', prog) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/extractor.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/extractor.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/extractor.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/extractor.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#pragma once + +int func1(void); +int func2(void); +int func3(void); +int func4(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/four.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/four.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/four.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/four.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func4(void) { + return 4; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/func1234.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/func1234.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/func1234.def" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/func1234.def" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +EXPORTS + func1 + func2 + func3 + func4 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/meson.build" 2021-10-23 16:49:12.000000000 +0000 @@ -0,0 +1,14 @@ +project('extract all', 'c', 'cpp') + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: Xcode backend does not handle libraries with only objects, not sources.') +endif + +a = static_library('a', 'one.c', 'two.c') +b = static_library('b', 'three.c', 'four.c') +c = shared_library('c', + objects : [a.extract_all_objects(), b.extract_all_objects()], + vs_module_defs : 'func1234.def') + +e = executable('proggie', 'prog.c', link_with : c) +test('extall', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/one.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/one.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/one.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/one.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func1(void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include"extractor.h" +#include + +int main(void) { + if((1+2+3+4) != (func1() + func2() + func3() + func4())) { + printf("Arithmetic is fail.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/three.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/three.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/three.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/three.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func3(void) { + return 3; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/two.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/two.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 extract all shared library/two.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 extract all shared library/two.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func2(void) { + return 2; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 test skip/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 test skip/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 test skip/meson.build" 2020-01-07 21:08:07.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 test skip/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('test skip', 'c') - -exe_test_skip = executable('test_skip', 'test_skip.c') -test('test_skip', exe_test_skip) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 test skip/test_skip.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 test skip/test_skip.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/120 test skip/test_skip.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/120 test skip/test_skip.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 77; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/meson.build" 2021-10-23 16:49:15.000000000 +0000 @@ -0,0 +1,51 @@ +project('object generator', 'c') + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST object-only libraries not supported in Xcode. Patches welcome.') +endif + +# FIXME: Note that this will not add a dependency to the compiler executable. +# Code will not be rebuilt if it changes. +comp = find_program('obj_generator.py') + +if host_machine.system() == 'windows' + ext = '.obj' +else + ext = '.o' +endif + +cc = meson.get_compiler('c').cmd_array().get(-1) + +# Generate an object file with configure_file to mimic prebuilt objects +# provided by the source tree +source1 = configure_file(input : 'source.c', + output : 'source' + ext, + command : [comp, cc, files('source.c'), + join_paths(meson.current_build_dir(), 'source' + ext)]) + +obj = static_library('obj', objects : source1) + +# Generate an object file manually. +gen = generator(comp, + output : '@BASENAME@' + ext, + arguments : [cc, '@INPUT@', '@OUTPUT@']) + +generated = gen.process(['source2.c']) + +shr = shared_library('shr', generated, + vs_module_defs : 'source2.def') + +# Generate an object file with indexed OUTPUT replacement. +gen2 = generator(comp, + output : '@BASENAME@' + ext, + arguments : [cc, '@INPUT@', '@OUTPUT0@']) +generated2 = gen2.process(['source3.c']) + +stc = static_library('stc', generated2) + +subdir('objdir') + +e = executable('prog', 'prog.c', link_with : [obj, shr, stc, subdirfilebuilt_obj, subdirfile_obj, subdirstr_obj], + install : true) + +test('objgen', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/objdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/objdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/objdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/objdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,27 @@ + +#mesonlib.File built +source4 = configure_file(input : 'source4.c', + output : 'source4' + ext, + command : [comp, cc, files('source4.c'), + join_paths(meson.current_build_dir(), 'source4' + ext)]) + +subdirfilebuilt_obj = static_library('subdirfilebuilt_obj', objects : source4) + + +#mesonlib.File not built +configure_file(input : 'source5.c', + output : 'source5' + ext, + command : [comp, cc, files('source5.c'), + join_paths(meson.current_build_dir(), 'source5' + ext)]) + +subdirfile_obj = static_library('subdirfile_obj', objects : files(meson.current_build_dir()/'source5' + ext)) + + +#str +configure_file(input : 'source6.c', + output : 'source6' + ext, + command : [comp, cc, files('source6.c'), + join_paths(meson.current_build_dir(), 'source6' + ext)]) + + +subdirstr_obj = static_library('subdirstr_obj', objects : meson.current_build_dir()/'source6' + ext) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/objdir/source4.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/objdir/source4.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/objdir/source4.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/objdir/source4.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +int func4_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/objdir/source5.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/objdir/source5.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/objdir/source5.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/objdir/source5.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +int func5_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/objdir/source6.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/objdir/source6.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/objdir/source6.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/objdir/source6.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +int func6_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/obj_generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/obj_generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/obj_generator.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/obj_generator.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +# Mimic a binary that generates an object file (e.g. windres). + +import sys, subprocess + +if __name__ == '__main__': + if len(sys.argv) != 4: + print(sys.argv[0], 'compiler input_file output_file') + sys.exit(1) + compiler = sys.argv[1] + ifile = sys.argv[2] + ofile = sys.argv[3] + if compiler.endswith('cl'): + cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] + elif sys.platform == 'sunos5': + cmd = [compiler, '-fpic', '-c', ifile, '-o', ofile] + else: + cmd = [compiler, '-c', ifile, '-o', ofile] + sys.exit(subprocess.call(cmd)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/prog.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,11 @@ +int func1_in_obj(void); +int func2_in_obj(void); +int func3_in_obj(void); +int func4_in_obj(void); +int func5_in_obj(void); +int func6_in_obj(void); + +int main(void) { + return func1_in_obj() + func2_in_obj() + func3_in_obj() + + func4_in_obj() + func5_in_obj() + func6_in_obj(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/source2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/source2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/source2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/source2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func2_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/source2.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/source2.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/source2.def" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/source2.def" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +EXPORTS + func2_in_obj diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/source3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/source3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/source3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/source3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func3_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/source.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func1_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 object only target/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 object only target/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/lib/modules/libnosyms?so -usr/lib/modules/libnosyms?implibempty -?msvc:usr/lib/modules/nosyms.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/meson.build" 2020-01-07 21:08:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -project('shared module', 'c') - -dl = meson.get_compiler('c').find_library('dl', required : false) -l = shared_library('runtime', 'runtime.c') -# Do NOT link the module with the runtime library. This -# is a common approach for plugins that are only used -# with dlopen. Any symbols are resolved dynamically -# at runtime. This requires extra help on Windows, so -# should be avoided unless really necessary. -m = shared_module('mymodule', 'module.c') -e = executable('prog', 'prog.c', - link_with : l, export_dynamic : true, dependencies : dl) -test('import test', e, args : m) - -# Same as above, but module created with build_target() -m2 = build_target('mymodule2', 'module.c', target_type: 'shared_module') -test('import test 2', e, args : m2) - -# Shared module that does not export any symbols -shared_module('nosyms', 'nosyms.c', - install : true, - install_dir : join_paths(get_option('libdir'), 'modules')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/module.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/module.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -#if defined(_WIN32) || defined(__CYGWIN__) - -#include - -typedef int (*fptr) (void); - -#ifdef __CYGWIN__ - -#include - -fptr find_any_f (const char *name) { - return (fptr) dlsym(RTLD_DEFAULT, name); -} -#else /* _WIN32 */ - -#include -#include - -static wchar_t* -win32_get_last_error (void) -{ - wchar_t *msg = NULL; - - FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_IGNORE_INSERTS - | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError (), 0, - (LPWSTR) &msg, 0, NULL); - return msg; -} - -/* Unlike Linux and OS X, when a library is loaded, all the symbols aren't - * loaded into a single namespace. You must fetch the symbol by iterating over - * all loaded modules. Code for finding the function from any of the loaded - * modules is taken from gmodule.c in glib */ -fptr find_any_f (const char *name) { - fptr f; - HANDLE snapshot; - MODULEENTRY32 me32; - - snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0); - if (snapshot == (HANDLE) -1) { - wchar_t *msg = win32_get_last_error(); - printf("Could not get snapshot: %S\n", msg); - return 0; - } - - me32.dwSize = sizeof (me32); - - f = NULL; - if (Module32First (snapshot, &me32)) { - do { - if ((f = (fptr) GetProcAddress (me32.hModule, name)) != NULL) - break; - } while (Module32Next (snapshot, &me32)); - } - - CloseHandle (snapshot); - return f; -} -#endif - -int DLL_PUBLIC func(void) { - fptr f; - - f = find_any_f ("func_from_language_runtime"); - if (f != NULL) - return f(); - printf ("Could not find function\n"); - return 1; -} - -#else -/* - * Shared modules often have references to symbols that are not defined - * at link time, but which will be provided from deps of the executable that - * dlopens it. We need to make sure that this works, i.e. that we do - * not pass -Wl,--no-undefined when linking modules. - */ -int func_from_language_runtime(void); - -int DLL_PUBLIC func(void) { - return func_from_language_runtime(); -} -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/nosyms.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/nosyms.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/nosyms.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/nosyms.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -static int -func_not_exported (void) { - return 99; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ - -#include - -int func_from_language_runtime(void); -typedef int (*fptr) (void); - -#ifdef _WIN32 - -#include - -static wchar_t* -win32_get_last_error (void) -{ - wchar_t *msg = NULL; - - FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_IGNORE_INSERTS - | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError (), 0, - (LPWSTR) &msg, 0, NULL); - return msg; -} - -int main(int argc, char **argv) -{ - HINSTANCE handle; - fptr importedfunc; - int expected, actual; - int ret = 1; - if(argc==0) {}; - - handle = LoadLibraryA (argv[1]); - if (!handle) { - wchar_t *msg = win32_get_last_error (); - printf ("Could not open %s: %S\n", argv[1], msg); - goto nohandle; - } - - importedfunc = (fptr) GetProcAddress (handle, "func"); - if (importedfunc == NULL) { - wchar_t *msg = win32_get_last_error (); - printf ("Could not find 'func': %S\n", msg); - goto out; - } - - actual = importedfunc (); - expected = func_from_language_runtime (); - if (actual != expected) { - printf ("Got %i instead of %i\n", actual, expected); - goto out; - } - - ret = 0; -out: - FreeLibrary (handle); -nohandle: - return ret; -} - -#else - -#include -#include - -int main(int argc, char **argv) { - void *dl; - fptr importedfunc; - int expected, actual; - char *error; - int ret = 1; - if(argc==0) {}; - - dlerror(); - dl = dlopen(argv[1], RTLD_LAZY); - error = dlerror(); - if(error) { - printf("Could not open %s: %s\n", argv[1], error); - goto nodl; - } - - importedfunc = (fptr) dlsym(dl, "func"); - if (importedfunc == NULL) { - printf ("Could not find 'func'\n"); - goto out; - } - - assert(importedfunc != func_from_language_runtime); - - actual = (*importedfunc)(); - expected = func_from_language_runtime (); - if (actual != expected) { - printf ("Got %i instead of %i\n", actual, expected); - goto out; - } - - ret = 0; -out: - dlclose(dl); -nodl: - return ret; -} - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/runtime.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/runtime.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/121 shared module/runtime.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/121 shared module/runtime.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -/* - * This file pretends to be a language runtime that supports extension - * modules. - */ - -int DLL_PUBLIC func_from_language_runtime(void) { - return 86; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include - -unsigned square_unsigned (unsigned a); - -int main(void) -{ - unsigned int ret = square_unsigned (2); - if (ret != 4) { - printf("Got %u instead of 4\n", ret); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/main.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#include - -extern "C" { - unsigned square_unsigned (unsigned a); -} - -int main (void) -{ - unsigned int ret = square_unsigned (2); - if (ret != 4) { - printf("Got %u instead of 4\n", ret); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/meson.build" 2020-01-07 21:08:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -project('llvm-ir', 'c', 'cpp') - -cpu = host_machine.cpu_family() -supported_cpus = ['arm', 'x86', 'x86_64'] - -foreach lang : ['c', 'cpp'] - cc = meson.get_compiler(lang) - cc_id = cc.get_id() - ## Build a trivial executable with mixed LLVM IR source - if cc_id == 'clang' - e = executable('square_ir_' + lang, 'square.ll', 'main.' + lang) - test('test IR square' + lang, e) - endif - ## Build a trivial executable with mixed assembly source - # This also helps test whether cc.symbols_have_underscore_prefix() is working - # properly. This is done by assembling some assembly into an object that will - # provide the unsigned_squared() symbol to main.c/cpp. This requires the - # C symbol mangling to be known in advance. - if cc.symbols_have_underscore_prefix() - uscore_args = ['-DMESON_TEST__UNDERSCORE_SYMBOL'] - message('underscore is prefixed') - else - uscore_args = [] - message('underscore is NOT prefixed') - endif - square_base = 'square-' + cpu - square_impl = square_base + '.S' - # MSVC cannot directly compile assembly files, so we pass it through the - # cl.exe pre-processor first and then assemble it with the ml.exe assembler. - # Then we can link it into the executable. - if cc.get_argument_syntax() == 'msvc' - cl = cc.cmd_array() - if cpu == 'x86' - ml = find_program('ml', required: false) - elif cpu == 'x86_64' - ml = find_program('ml64', required: false) - else - error('Unsupported cpu family: "' + cpu + '"') - endif - if not ml.found() - error('MESON_SKIP_TEST: ML (masm) not found') - endif - # Preprocess file (ml doesn't support pre-processing) - # Force the intput to be C (/Tc) because ICL otherwise assumes it's an object (.obj) file - preproc_name = lang + square_base + '.i' - square_preproc = custom_target(lang + square_impl + 'preproc', - input : square_impl, - output : preproc_name, - command : [cl, '/nologo', '/EP', '/P', '/Fi' + preproc_name, '/Tc', '@INPUT@'] + uscore_args) - # Use assembled object file instead of the original .S assembly source - square_impl = custom_target(lang + square_impl, - input : square_preproc, - output : lang + square_base + '.obj', - command : [ml, '/nologo', '/safeseh', '/Fo', '@OUTPUT@', '/c', '@INPUT@']) - endif - if supported_cpus.contains(cpu) - e = executable('square_asm_' + lang, square_impl, 'main.' + lang, - c_args : uscore_args, cpp_args : uscore_args) - test('test ASM square' + lang, e) - elif cc_id != 'clang' - error('MESON_SKIP_TEST: Unsupported cpu: "' + cpu + '", and LLVM not found') - endif -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/square-arm.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/square-arm.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/square-arm.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/square-arm.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#include "symbol-underscore.h" - -.text -.globl SYMBOL_NAME(square_unsigned) -# ifdef __linux__ -.type square_unsigned, %function -#endif - -SYMBOL_NAME(square_unsigned): - mul r1, r0, r0 - mov r0, r1 - mov pc, lr diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/square.ll" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/square.ll" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/square.ll" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/square.ll" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -define i32 @square_unsigned(i32 %a) { - %1 = mul i32 %a, %a - ret i32 %1 -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/square-x86_64.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/square-x86_64.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/square-x86_64.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/square-x86_64.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -#include "symbol-underscore.h" - -#ifdef _MSC_VER /* MSVC on Windows */ - -PUBLIC SYMBOL_NAME(square_unsigned) -_TEXT SEGMENT - -SYMBOL_NAME(square_unsigned) PROC - mov eax, ecx - imul eax, eax - ret -SYMBOL_NAME(square_unsigned) ENDP - -_TEXT ENDS -END - -#else - -.text -.globl SYMBOL_NAME(square_unsigned) -# ifdef __linux__ -.type square_unsigned, %function -#endif - -# if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ -SYMBOL_NAME(square_unsigned): - imull %ecx, %ecx - movl %ecx, %eax - retq -# else /* sysvabi */ -SYMBOL_NAME(square_unsigned): - imull %edi, %edi - movl %edi, %eax - retq -# endif - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/square-x86.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/square-x86.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/square-x86.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/square-x86.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -#include "symbol-underscore.h" - -/* This sadly doesn't test the symbol underscore stuff. I can't figure out how - * to not use an automatic stdcall mechanism and do everything manually. */ -#ifdef _MSC_VER - -.386 -.MODEL FLAT, C - -PUBLIC square_unsigned -_TEXT SEGMENT - -square_unsigned PROC var1:DWORD - mov eax, var1 - imul eax, eax - ret - -square_unsigned ENDP - -_TEXT ENDS -END - -#else - -.text -.globl SYMBOL_NAME(square_unsigned) -# ifdef __linux__ -.type square_unsigned, %function -#endif - -SYMBOL_NAME(square_unsigned): - movl 4(%esp), %eax - imull %eax, %eax - retl - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/symbol-underscore.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/symbol-underscore.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 llvm ir and assembly/symbol-underscore.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 llvm ir and assembly/symbol-underscore.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#if defined(MESON_TEST__UNDERSCORE_SYMBOL) -# define SYMBOL_NAME(name) _##name -#else -# define SYMBOL_NAME(name) name -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 no buildincdir/include/header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 no buildincdir/include/header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 no buildincdir/include/header.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 no buildincdir/include/header.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +int foobar(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 no buildincdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 no buildincdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 no buildincdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 no buildincdir/meson.build" 2021-10-23 16:49:11.000000000 +0000 @@ -0,0 +1,14 @@ +project('nobuilddir', 'c', + default_options : ['werror=true', 'buildtype=plain']) + +cc = meson.get_compiler('c') + +incwarg = '-Wmissing-include-dirs' + +if cc.has_argument(incwarg) + executable('prog', 'prog.c', + c_args : incwarg, + include_directories : include_directories('include')) +else + error('MESON_SKIP_TEST compiler does not support bad inc dir argument.') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 no buildincdir/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 no buildincdir/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/122 no buildincdir/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/122 no buildincdir/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"header.h" + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/meson.build" 2020-01-07 21:08:12.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -project('c++ and assembly test', 'cpp') - -cpp = meson.get_compiler('cpp') -cpu = host_machine.cpu_family() - -supported_cpus = ['arm', 'x86', 'x86_64'] - -if not supported_cpus.contains(cpu) - error('MESON_SKIP_TEST unsupported cpu:' + cpu) -endif - -if cpp.symbols_have_underscore_prefix() - add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language : 'cpp') -endif - -sources = ['trivial.cc'] -# If the compiler cannot compile assembly, don't use it -if not ['msvc', 'clang-cl', 'intel-cl'].contains(meson.get_compiler('cpp').get_id()) - sources += ['retval-' + cpu + '.S'] - cpp_args = ['-DUSE_ASM'] - message('Using ASM') -else - cpp_args = ['-DNO_USE_ASM'] -endif - -exe = executable('trivialprog', sources, - cpp_args : cpp_args) -test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/retval-arm.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/retval-arm.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/retval-arm.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/retval-arm.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include "symbol-underscore.h" - -.text -.globl SYMBOL_NAME(get_retval) -# ifdef __linux__ -.type get_retval, %function -#endif - -SYMBOL_NAME(get_retval): - mov r0, #0 - mov pc, lr diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/retval-x86_64.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/retval-x86_64.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/retval-x86_64.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/retval-x86_64.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include "symbol-underscore.h" - -.text -.globl SYMBOL_NAME(get_retval) -# ifdef __linux__ -.type get_retval, %function -#endif - -SYMBOL_NAME(get_retval): - xorl %eax, %eax - retq diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/retval-x86.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/retval-x86.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/retval-x86.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/retval-x86.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include "symbol-underscore.h" - -.text -.globl SYMBOL_NAME(get_retval) -# ifdef __linux__ -.type get_retval, %function -#endif - -SYMBOL_NAME(get_retval): - xorl %eax, %eax - retl diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/symbol-underscore.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/symbol-underscore.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/symbol-underscore.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/symbol-underscore.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#if defined(MESON_TEST__UNDERSCORE_SYMBOL) -# define SYMBOL_NAME(name) _##name -#else -# define SYMBOL_NAME(name) name -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/trivial.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/trivial.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 cpp and asm/trivial.cc" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 cpp and asm/trivial.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include - -extern "C" { - int get_retval(void); -} - -int main(void) { - std::cout << "C++ seems to be working." << std::endl; -#if defined(USE_ASM) - return get_retval(); -#elif defined(NO_USE_ASM) - return 0; -#else - #error "Forgot to pass asm define" -#endif -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 custom target directory install/docgen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 custom target directory install/docgen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 custom target directory install/docgen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 custom target directory install/docgen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import os +import sys + +out = sys.argv[1] + +try: + os.mkdir(out) +except FileExistsError: + pass + +for name in ('a', 'b', 'c'): + with open(os.path.join(out, name + '.html'), 'w') as f: + f.write(name) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 custom target directory install/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 custom target directory install/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 custom target directory install/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 custom target directory install/meson.build" 2021-10-23 16:49:13.000000000 +0000 @@ -0,0 +1,9 @@ +project('custom-target-dir-install', 'c') + +docgen = find_program('docgen.py') + +custom_target('docgen', + output : 'html', + command : [docgen, '@OUTPUT@'], + install : true, + install_dir : join_paths(get_option('datadir'), 'doc/testpkgname')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 custom target directory install/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 custom target directory install/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/123 custom target directory install/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/123 custom target directory install/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "file", "file": "usr/share/doc/testpkgname/html/a.html"}, + {"type": "file", "file": "usr/share/doc/testpkgname/html/b.html"}, + {"type": "file", "file": "usr/share/doc/testpkgname/html/c.html"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 dependency file generation/main .c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 dependency file generation/main .c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 dependency file generation/main .c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 dependency file generation/main .c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 dependency file generation/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 dependency file generation/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 dependency file generation/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 dependency file generation/meson.build" 2021-10-23 16:49:13.000000000 +0000 @@ -0,0 +1,14 @@ +project('dep file gen', 'c') + +cc_id = meson.get_compiler('c').get_id() +cc_ver = meson.get_compiler('c').version() + +if cc_id == 'intel' or (cc_id == 'lcc' and cc_ver.version_compare('<=1.23.08')) + # ICC and LCC <= 1.23.08 do not escape spaces in paths in the dependency file, so Ninja + # (correctly) thinks that the rule has multiple outputs and errors out: + # 'depfile has multiple output paths' + error('MESON_SKIP_TEST: Skipping test because your compiler is known to generate broken dependency files') +endif + +e = executable('main file', 'main .c') +test('test it', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/extractor.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/extractor.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/extractor.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/extractor.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#pragma once - -int func1(void); -int func2(void); -int func3(void); -int func4(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/four.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/four.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/four.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/four.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"extractor.h" - -int func4(void) { - return 4; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/func1234.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/func1234.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/func1234.def" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/func1234.def" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -EXPORTS - func1 - func2 - func3 - func4 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/meson.build" 2020-01-07 21:08:12.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('extract all', 'c', 'cpp') - -a = static_library('a', 'one.c', 'two.c') -b = static_library('b', 'three.c', 'four.c') -c = shared_library('c', - objects : [a.extract_all_objects(), b.extract_all_objects()], - vs_module_defs : 'func1234.def') - -e = executable('proggie', 'prog.c', link_with : c) -test('extall', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/one.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/one.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/one.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/one.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"extractor.h" - -int func1(void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include"extractor.h" -#include - -int main(void) { - if((1+2+3+4) != (func1() + func2() + func3() + func4())) { - printf("Arithmetic is fail.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/three.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/three.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/three.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/three.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"extractor.h" - -int func3(void) { - return 3; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/two.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/two.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/124 extract all shared library/two.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/124 extract all shared library/two.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"extractor.h" - -int func2(void) { - return 2; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/inc/confdata.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/inc/confdata.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/inc/confdata.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/inc/confdata.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +@VALUE@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/inc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/inc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/inc/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/inc/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +cdata = configuration_data() +cdata.set('VALUE', '42') + +cfile = configure_file(input : 'confdata.in', +output : 'confdata', +configuration : cdata) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/meson.build" 2021-10-23 16:49:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('conf file in generator', 'c') + +subdir('inc') +subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/src/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/src/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/src/gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/src/gen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import sys + +ifile = sys.argv[1] +ofile = sys.argv[2] + +with open(ifile) as f: + resval = f.readline().strip() + +templ = '#define RESULT (%s)\n' +with open(ofile, 'w') as f: + f.write(templ % (resval, )) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/src/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/src/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/src/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/src/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +#include + +#include"confdata.h" +#if RESULT != 42 +#error Configuration RESULT is not defined correctly +#endif + +#undef RESULT + +#include"source.h" +#if RESULT != 23 +#error Source RESULT is not defined correctly +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +compiler = find_program('gen.py') +gen = generator(compiler, + output: '@BASENAME@.h', + arguments : ['@INPUT@', '@OUTPUT@']) +hs = gen.process(cfile, files('source')) + +executable('proggie', 'main.c', hs) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/src/source" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/src/source" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 configure file in generator/src/source" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 configure file in generator/src/source" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +23 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/meson.build" 2020-01-07 21:08:15.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -project('object generator', 'c') - -# FIXME: Note that this will not add a dependency to the compiler executable. -# Code will not be rebuilt if it changes. -comp = find_program('obj_generator.py') - -if host_machine.system() == 'windows' - ext = '.obj' -else - ext = '.o' -endif - -cc = meson.get_compiler('c').cmd_array().get(-1) - -# Generate an object file with configure_file to mimic prebuilt objects -# provided by the source tree -source1 = configure_file(input : 'source.c', - output : 'source' + ext, - command : [comp, cc, files('source.c'), - join_paths(meson.current_build_dir(), 'source' + ext)]) - -obj = static_library('obj', objects : source1) - -# Generate an object file manually. -gen = generator(comp, - output : '@BASENAME@' + ext, - arguments : [cc, '@INPUT@', '@OUTPUT@']) - -generated = gen.process(['source2.c']) - -shr = shared_library('shr', generated, - vs_module_defs : 'source2.def') - -# Generate an object file with indexed OUTPUT replacement. -gen2 = generator(comp, - output : '@BASENAME@' + ext, - arguments : [cc, '@INPUT@', '@OUTPUT0@']) -generated2 = gen2.process(['source3.c']) - -stc = static_library('stc', generated2) - -e = executable('prog', 'prog.c', link_with : [obj, shr, stc], - install : true) - -test('objgen', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/obj_generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/obj_generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/obj_generator.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/obj_generator.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 - -# Mimic a binary that generates an object file (e.g. windres). - -import sys, subprocess - -if __name__ == '__main__': - if len(sys.argv) != 4: - print(sys.argv[0], 'compiler input_file output_file') - sys.exit(1) - compiler = sys.argv[1] - ifile = sys.argv[2] - ofile = sys.argv[3] - if compiler.endswith('cl'): - cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] - else: - cmd = [compiler, '-c', ifile, '-o', ofile] - sys.exit(subprocess.call(cmd)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -int func1_in_obj(void); -int func2_in_obj(void); -int func3_in_obj(void); - -int main(void) { - return func1_in_obj() + func2_in_obj() + func3_in_obj(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/source2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/source2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/source2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/source2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func2_in_obj(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/source2.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/source2.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/source2.def" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/source2.def" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -EXPORTS - func2_in_obj diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/source3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/source3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/source3.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/source3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func3_in_obj(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/125 object only target/source.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/125 object only target/source.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func1_in_obj(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 generated llvm ir/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 generated llvm ir/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 generated llvm ir/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 generated llvm ir/copyfile.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 generated llvm ir/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 generated llvm ir/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 generated llvm ir/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 generated llvm ir/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include + +unsigned square_unsigned (unsigned a); + +int main(void) +{ + unsigned int ret = square_unsigned (2); + if (ret != 4) { + printf("Got %u instead of 4\n", ret); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 generated llvm ir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 generated llvm ir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 generated llvm ir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 generated llvm ir/meson.build" 2022-01-09 20:49:57.000000000 +0000 @@ -0,0 +1,28 @@ +project('generated llvm ir', 'c') + +if meson.get_compiler('c').get_id() != 'clang' + error('MESON_SKIP_TEST: LLVM IR files can only be built with clang') +endif + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: LLVM ir not supported with the Xcode backend. Patches welcome.') +endif + +copy = find_program('copyfile.py') + +copygen = generator(copy, + arguments : ['@INPUT@', '@OUTPUT@'], + output : '@BASENAME@') + +l = library('square-gen', copygen.process('square.ll.in')) + +test('square-gen-test', executable('square-gen-test', 'main.c', link_with : l)) + +copyct = custom_target('square', + input : 'square.ll.in', + output : 'square.ll', + command : [copy, '@INPUT@', '@OUTPUT@']) + +l = library('square-ct', copyct) + +test('square-ct-test', executable('square-ct-test', 'main.c', link_with : l)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 generated llvm ir/square.ll.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 generated llvm ir/square.ll.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 generated llvm ir/square.ll.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 generated llvm ir/square.ll.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +define i32 @square_unsigned(i32 %a) { + %1 = mul i32 %a, %a + ret i32 %1 +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 no buildincdir/include/header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 no buildincdir/include/header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 no buildincdir/include/header.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 no buildincdir/include/header.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#pragma once - -int foobar(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 no buildincdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 no buildincdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 no buildincdir/meson.build" 2020-01-07 21:08:14.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 no buildincdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('nobuilddir', 'c', - default_options : ['werror=true', 'buildtype=plain']) - -cc = meson.get_compiler('c') - -incwarg = '-Wmissing-include-dirs' - -if cc.has_argument(incwarg) - executable('prog', 'prog.c', - c_args : incwarg, - include_directories : include_directories('include')) -else - error('MESON_SKIP_TEST compiler does not support bad inc dir argument.') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 no buildincdir/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 no buildincdir/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/126 no buildincdir/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/126 no buildincdir/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"header.h" - -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 custom target directory install/docgen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 custom target directory install/docgen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 custom target directory install/docgen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 custom target directory install/docgen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -out = sys.argv[1] - -os.mkdir(out) - -for name in ('a', 'b', 'c'): - with open(os.path.join(out, name + '.html'), 'w') as f: - f.write(name) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 custom target directory install/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 custom target directory install/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 custom target directory install/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 custom target directory install/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/share/doc/testpkgname/html/a.html -usr/share/doc/testpkgname/html/b.html -usr/share/doc/testpkgname/html/c.html diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 custom target directory install/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 custom target directory install/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 custom target directory install/meson.build" 2020-01-07 21:08:14.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 custom target directory install/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('custom-target-dir-install', 'c') - -docgen = find_program('docgen.py') - -custom_target('docgen', - output : 'html', - command : [docgen, '@OUTPUT@'], - install : true, - install_dir : join_paths(get_option('datadir'), 'doc/testpkgname')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/copyfile.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include + +#if defined(_WIN32) || defined(__CYGWIN__) + __declspec(dllimport) +#endif +unsigned square_unsigned (unsigned a); + +int main(void) +{ + unsigned int ret = square_unsigned (2); + if (ret != 4) { + printf("Got %u instead of 4\n", ret); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/meson.build" 2021-10-23 16:49:18.000000000 +0000 @@ -0,0 +1,66 @@ +project('generated assembly', 'c') + +cc = meson.get_compiler('c') + +if ['msvc', 'intel-cl'].contains(cc.get_id()) + error('MESON_SKIP_TEST: assembly files cannot be compiled directly by the compiler') +endif + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: asm not supported with the Xcode backend. Patches welcome.') +endif + + +crt_workaround = [] +if cc.get_linker_id() == 'lld-link' + # It seems that when building without a .c file, lld-link.exe + # misses the fact that it needs to include the c runtime to + # make a working .dll. So here we add an empty .c file to easily + # pull in crt. + crt_workaround += 'empty.c' + if host_machine.cpu_family() == 'x86' + # x86 assembly needs manual annotation to be compatible with + # Safe Exception Handlers (?) This assembly doesn't have such + # annotation, so just disable the feature. + add_project_link_arguments('/SAFESEH:NO', language : 'c') + endif +endif + +cpu = host_machine.cpu_family() +supported_cpus = ['arm', 'x86', 'x86_64'] + +if not supported_cpus.contains(cpu) + error('MESON_SKIP_TEST: unsupported cpu family: ' + cpu) +endif + +if cc.get_id() == 'clang-cl' and cc.version().version_compare('< 12.0.0') and cpu == 'arm' + # https://reviews.llvm.org/D89622 + error('MESON_SKIP_TEST: arm debug symbols not supported in clang-cl < 12.0.0') +endif + +if cc.symbols_have_underscore_prefix() + add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language : 'c') +endif + +copy = find_program('copyfile.py') +output = 'square-@0@.S'.format(cpu) +input = output + '.in' + +copygen = generator(copy, + arguments : ['@INPUT@', '@OUTPUT@'], + output : '@BASENAME@') + +l = library('square-gen', crt_workaround + [copygen.process(input)], + vs_module_defs: 'square.def') + +test('square-gen-test', executable('square-gen-test', 'main.c', link_with : l)) + +copyct = custom_target('square', + input : input, + output : output, + command : [copy, '@INPUT@', '@OUTPUT@']) + +l = library('square-ct', crt_workaround + [copyct], + vs_module_defs: 'square.def') + +test('square-ct-test', executable('square-ct-test', 'main.c', link_with : l)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/square-arm.S.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/square-arm.S.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/square-arm.S.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/square-arm.S.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(square_unsigned) +/* Only supported with GAS */ +# if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) +.type square_unsigned,%function +#endif + +SYMBOL_NAME(square_unsigned): + mul r1, r0, r0 + mov r0, r1 + mov pc, lr diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/square.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/square.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/square.def" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/square.def" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +EXPORTS + square_unsigned diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/square-x86_64.S.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/square-x86_64.S.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/square-x86_64.S.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/square-x86_64.S.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,38 @@ +#include "symbol-underscore.h" + +#if defined(_MSC_VER) && !defined(__clang__) /* MSVC on Windows */ + +PUBLIC SYMBOL_NAME(square_unsigned) +_TEXT SEGMENT + +SYMBOL_NAME(square_unsigned) PROC + mov eax, ecx + imul eax, eax + ret +SYMBOL_NAME(square_unsigned) ENDP + +_TEXT ENDS +END + +#else + +.text +.globl SYMBOL_NAME(square_unsigned) +/* Only supported with GAS */ +# if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__sun) +.type square_unsigned,@function +# endif + +# if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ +SYMBOL_NAME(square_unsigned): + imull %ecx, %ecx + movl %ecx, %eax + retq +# else /* sysvabi */ +SYMBOL_NAME(square_unsigned): + imull %edi, %edi + movl %edi, %eax + retq +# endif + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/square-x86.S.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/square-x86.S.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/square-x86.S.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/square-x86.S.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,34 @@ +#include "symbol-underscore.h" + +#if defined(_MSC_VER) && !defined(__clang__) + +.386 +.MODEL FLAT, C + +PUBLIC square_unsigned +_TEXT SEGMENT + +square_unsigned PROC var1:DWORD + mov eax, var1 + imul eax, eax + ret +square_unsigned ENDP + +_TEXT ENDS +END + +#else + +.text +.globl SYMBOL_NAME(square_unsigned) +/* Only supported with GAS */ +# if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) +.type square_unsigned,@function +# endif + +SYMBOL_NAME(square_unsigned): + movl 4(%esp), %eax + imull %eax, %eax + retl + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/symbol-underscore.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/symbol-underscore.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/127 generated assembly/symbol-underscore.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/127 generated assembly/symbol-underscore.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#if defined(MESON_TEST__UNDERSCORE_SYMBOL) +# define SYMBOL_NAME(name) _##name +#else +# define SYMBOL_NAME(name) name +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 build by default targets in tests/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 build by default targets in tests/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 build by default targets in tests/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 build by default targets in tests/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 build by default targets in tests/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 build by default targets in tests/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 build by default targets in tests/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 build by default targets in tests/meson.build" 2021-10-23 16:49:17.000000000 +0000 @@ -0,0 +1,23 @@ +project('unit-test', 'c', version : '1.0') + +write_file = find_program('write_file.py') + +# A test that consumes and verifies the output generated by a custom target. +# Should work even if target is not built by default. Makes sure that foo.out +# is actually created before the test command that uses foo_out is run. +foo_out = custom_target('foo.out', + output : 'foo.out', + command : [write_file, '@OUTPUT@']) + +# Also verify that a build_by_default : false BuildTarget added to a test is +# built before the test is run. +exe_out = executable('out', 'main.c', build_by_default : false) + +py_file_exists = '''import os, sys +if not os.path.exists(sys.argv[1]) or not os.path.exists(sys.argv[2]): + print("could not find {!r} or {!r} in {!r}" + "".format(sys.argv[1], sys.argv[2], os.getcwd())) + sys.exit(1)''' + +python = import('python3').find_python() +test('output-check', python, args : ['-c', py_file_exists, foo_out, exe_out]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 build by default targets in tests/write_file.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 build by default targets in tests/write_file.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 build by default targets in tests/write_file.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 build by default targets in tests/write_file.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys + +with open(sys.argv[1], 'w') as f: + f.write('Test') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 dependency file generation/main .c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 dependency file generation/main .c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 dependency file generation/main .c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 dependency file generation/main .c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 dependency file generation/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 dependency file generation/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/128 dependency file generation/meson.build" 2020-01-07 21:08:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/128 dependency file generation/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('dep file gen', 'c') - -cc_id = meson.get_compiler('c').get_id() -cc_ver = meson.get_compiler('c').version() - -if cc_id == 'intel' or (cc_id == 'lcc' and cc_ver.version_compare('<=1.23.08')) - # ICC and LCC <= 1.23.08 do not escape spaces in paths in the dependency file, so Ninja - # (correctly) thinks that the rule has multiple outputs and errors out: - # 'depfile has multiple output paths' - error('MESON_SKIP_TEST: Skipping test because your compiler is known to generate broken dependency files') -endif - -e = executable('main file', 'main .c') -test('test it', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/checkexists.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/checkexists.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/checkexists.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/checkexists.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +import os.path, sys + +invert = False +for path in sys.argv[1:]: + if path == '--not': + invert = True + elif not os.path.exists(path) ^ invert: + sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("Existentialism.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,44 @@ +project('build on all', 'c') + +py3_mod = import('python3') +py3 = py3_mod.find_python() + +executable('fooprog', 'foo.c', + build_by_default : false, +) + +executable('barprog', 'foo.c', + build_by_default : false, +) + +comp = files('mygen.py') +checkexists = files('checkexists.py') + +mytarget = custom_target('gendat1', + output : 'generated1.dat', + input : 'source.txt', + command : [py3] + comp + ['@INPUT@', '@OUTPUT@'], + build_by_default : true, +) + +mytarget = custom_target('gendat2', + output : 'generated2.dat', + input : 'source.txt', + command : [py3] + comp + ['@INPUT@', '@OUTPUT@'], + build_by_default : true, + build_always : false, +) + +ct1_output = join_paths(meson.build_root(), 'generated1.dat') +ct2_output = join_paths(meson.build_root(), 'generated2.dat') +exe1_output = join_paths(meson.build_root(), 'fooprog') +exe2_output = join_paths(meson.build_root(), 'barprog') + +if host_machine.system() == 'windows' + exe1_output += '.exe' + exe2_output += '.exe' +endif + +test('check-build-by-default', py3, + args : [checkexists, + ct1_output, ct2_output, '--not', exe1_output, exe2_output]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/mygen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/mygen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/mygen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/mygen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys + +ifile = open(sys.argv[1]) +ofile = open(sys.argv[2], 'w') + +ofile.write(ifile.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 build by default/source.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 build by default/source.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +I am a bunch of text. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/inc/confdata.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/inc/confdata.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/inc/confdata.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/inc/confdata.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -@VALUE@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/inc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/inc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/inc/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/inc/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -cdata = configuration_data() -cdata.set('VALUE', '42') - -cfile = configure_file(input : 'confdata.in', -output : 'confdata', -configuration : cdata) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/meson.build" 2020-01-07 21:08:17.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('conf file in generator', 'c') - -subdir('inc') -subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/src/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/src/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/src/gen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/src/gen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -ifile = sys.argv[1] -ofile = sys.argv[2] - -with open(ifile, 'r') as f: - resval = f.readline().strip() - -templ = '#define RESULT (%s)\n' -with open(ofile, 'w') as f: - f.write(templ % (resval, )) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/src/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/src/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/src/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/src/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -#include - -#include"confdata.h" -#if RESULT != 42 -#error Configuration RESULT is not defined correctly -#endif - -#undef RESULT - -#include"source.h" -#if RESULT != 23 -#error Source RESULT is not defined correctly -#endif - -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/src/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -compiler = find_program('gen.py') -gen = generator(compiler, - output: '@BASENAME@.h', - arguments : ['@INPUT@', '@OUTPUT@']) -hs = gen.process(cfile, files('source')) - -executable('proggie', 'main.c', hs) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/src/source" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/src/source" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/129 configure file in generator/src/source" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/129 configure file in generator/src/source" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -23 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/12 data/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/12 data/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/12 data/installed_files.txt" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/12 data/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -usr/share/progname/datafile.dat -usr/share/progname/fileobject_datafile.dat -usr/share/progname/vanishing.dat -usr/share/progname/vanishing2.dat -usr/share/data install test/renamed file.txt -usr/share/data install test/somefile.txt -usr/share/data install test/some/nested/path.txt -usr/share/renamed/renamed 2.txt -usr/share/renamed/renamed 3.txt -etc/etcfile.dat -usr/bin/runscript.sh diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/12 data/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/12 data/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/12 data/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/12 data/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "installed": [ + {"type": "file", "file": "usr/share/progname/datafile.dat"}, + {"type": "file", "file": "usr/share/progname/fileobject_datafile.dat"}, + {"type": "file", "file": "usr/share/progname/vanishing.dat"}, + {"type": "file", "file": "usr/share/progname/vanishing2.dat"}, + {"type": "file", "file": "usr/share/data install test/renamed file.txt"}, + {"type": "file", "file": "usr/share/data install test/somefile.txt"}, + {"type": "file", "file": "usr/share/data install test/some/nested/path.txt"}, + {"type": "file", "file": "usr/share/renamed/renamed 2.txt"}, + {"type": "file", "file": "usr/share/renamed/renamed 3.txt"}, + {"type": "file", "file": "etc/etcfile.dat"}, + {"type": "file", "file": "usr/bin/runscript.sh"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 generated llvm ir/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 generated llvm ir/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 generated llvm ir/copyfile.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 generated llvm ir/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import shutil - -shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 generated llvm ir/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 generated llvm ir/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 generated llvm ir/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 generated llvm ir/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include - -unsigned square_unsigned (unsigned a); - -int main(void) -{ - unsigned int ret = square_unsigned (2); - if (ret != 4) { - printf("Got %u instead of 4\n", ret); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 generated llvm ir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 generated llvm ir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 generated llvm ir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 generated llvm ir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -project('generated llvm ir', 'c') - -if meson.get_compiler('c').get_id() != 'clang' - error('MESON_SKIP_TEST: LLVM IR files can only be built with clang') -endif - -copy = find_program('copyfile.py') - -copygen = generator(copy, - arguments : ['@INPUT@', '@OUTPUT@'], - output : '@BASENAME@') - -l = shared_library('square-gen', copygen.process('square.ll.in')) - -test('square-gen-test', executable('square-gen-test', 'main.c', link_with : l)) - -copyct = custom_target('square', - input : 'square.ll.in', - output : 'square.ll', - command : [copy, '@INPUT@', '@OUTPUT@']) - -l = shared_library('square-ct', copyct) - -test('square-ct-test', executable('square-ct-test', 'main.c', link_with : l)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 generated llvm ir/square.ll.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 generated llvm ir/square.ll.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 generated llvm ir/square.ll.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 generated llvm ir/square.ll.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -define i32 @square_unsigned(i32 %a) { - %1 = mul i32 %a, %a - ret i32 %1 -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/ctsub/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/ctsub/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/ctsub/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/ctsub/copyfile.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/ctsub/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/ctsub/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/ctsub/main.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/ctsub/main.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#error "ctsub/main.h included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/ctsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/ctsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/ctsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/ctsub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +# https://github.com/mesonbuild/meson/pull/2291 +copy = find_program('copyfile.py') +configure_file(input : 'main.h', + output : 'main.h', + command : [copy, '@INPUT@', '@OUTPUT@']) +ctfile = custom_target('emptyfile', + input : 'emptyfile.c', + output : 'emptyfile.c', + command : [copy, '@INPUT@', '@OUTPUT@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/inc1/hdr.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/inc1/hdr.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/inc1/hdr.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/inc1/hdr.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#define SOME_DEFINE 42 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/inc2/hdr.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/inc2/hdr.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/inc2/hdr.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/inc2/hdr.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#undef SOME_DEFINE diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/meson.build" 2021-10-23 16:49:19.000000000 +0000 @@ -0,0 +1,36 @@ +project('include order', 'c') + +# Test that the order of priority of include paths (from first to last) is: +# +# 1. Target's current build directory +# 2. Target's current source directory +# 3. Include paths added with the `c_args:` kwarg +# 4. Include paths added with the `include_directories`: kwarg +# Within this, the build dir takes precedence over the source dir +# 5. Include paths added via `include_directories:` of internal deps +# Within this, the build dir takes precedence over the source dir + +# Custom target dir with a built header +subdir('ctsub') +# Defines an internal dep +subdir('sub1') +# Defines a per-target include path +subdir('sub2') +# Directory for `c_args:` include path +subdir('sub3') +# The directory where the target resides +subdir('sub4') + +# Test that the order in which internal dependencies are specified is +# preserved. This is needed especially when subprojects get involved and +# multiple build-root config.h files exist, and we must be sure that the +# correct one is found: https://github.com/mesonbuild/meson/issues/1495 +f = executable('somefxe', 'sub4/main.c', + dependencies : [correctinc, dep, wronginc]) + +test('eh', e) +test('oh', f) + +# Test that the order in include_directories() is maintained +incs = include_directories('inc1', 'inc2') +executable('ordertest', 'ordertest.c', include_directories: incs) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/ordertest.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/ordertest.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/ordertest.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/ordertest.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include "hdr.h" + +#if !defined(SOME_DEFINE) || SOME_DEFINE != 42 +#error "Should have picked up hdr.h from inc1/hdr.h" +#endif + +int main(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub1/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub1/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub1/main.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub1/main.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#error "sub1/main.h included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +i = include_directories('.') +l = shared_library('somelib', 'some.c') +dep = declare_dependency(link_with : l, + include_directories : i) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub1/some.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub1/some.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub1/some.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub1/some.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#if defined _WIN32 || defined __CYGWIN__ + __declspec(dllexport) +#endif +int somefunc(void) { + return 1984; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub1/some.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub1/some.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub1/some.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub1/some.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#pragma once + +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllimport) +#else + #define DLL_PUBLIC +#endif + +DLL_PUBLIC +int somefunc(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub2/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub2/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub2/main.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub2/main.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#error "sub2/main.h included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +j = include_directories('.') +wronginc = declare_dependency(include_directories : j) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub3/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub3/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub3/main.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub3/main.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#error "sub3/main.h included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub3/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub3/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +sub3 = meson.current_source_dir() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub4/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub4/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub4/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub4/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +/* Use the <> include notation to force searching in include directories */ +#include + +int main(void) { + if (somefunc() == 1984) + return 0; + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub4/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub4/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub4/main.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub4/main.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +#include "some.h" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub4/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub4/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/130 include order/sub4/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/130 include order/sub4/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +e = executable('someexe', 'main.c', ctfile, + c_args : ['-I' + sub3], + include_directories : j, + dependencies : dep) + +correctinc = declare_dependency(include_directories : include_directories('.')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/copyfile.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import shutil - -shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include - -#if defined(_WIN32) || defined(__CYGWIN__) - __declspec(dllimport) -#endif -unsigned square_unsigned (unsigned a); - -int main(void) -{ - unsigned int ret = square_unsigned (2); - if (ret != 4) { - printf("Got %u instead of 4\n", ret); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/meson.build" 2020-01-07 21:08:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -project('generated assembly', 'c') - -cc = meson.get_compiler('c') - -if ['msvc', 'clang-cl', 'intel-cl'].contains(cc.get_id()) - error('MESON_SKIP_TEST: assembly files cannot be compiled directly by the compiler') -endif - -cpu = host_machine.cpu_family() -supported_cpus = ['arm', 'x86', 'x86_64'] - -if not supported_cpus.contains(cpu) - error('MESON_SKIP_TEST: unsupported cpu family: ' + cpu) -endif - -if cc.symbols_have_underscore_prefix() - add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language : 'c') -endif - -copy = find_program('copyfile.py') -output = 'square-@0@.S'.format(cpu) -input = output + '.in' - -copygen = generator(copy, - arguments : ['@INPUT@', '@OUTPUT@'], - output : '@BASENAME@') - -l = shared_library('square-gen', copygen.process(input)) - -test('square-gen-test', executable('square-gen-test', 'main.c', link_with : l)) - -copyct = custom_target('square', - input : input, - output : output, - command : [copy, '@INPUT@', '@OUTPUT@']) - -l = shared_library('square-ct', copyct) - -test('square-ct-test', executable('square-ct-test', 'main.c', link_with : l)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/square-arm.S.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/square-arm.S.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/square-arm.S.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/square-arm.S.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include "symbol-underscore.h" - -.text -.globl SYMBOL_NAME(square_unsigned) -/* Only supported with GAS */ -# if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) -.type square_unsigned,%function -#endif - -SYMBOL_NAME(square_unsigned): - mul r1, r0, r0 - mov r0, r1 - mov pc, lr diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/square-x86_64.S.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/square-x86_64.S.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/square-x86_64.S.in" 2019-09-16 21:20:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/square-x86_64.S.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -#include "symbol-underscore.h" - -#ifdef _MSC_VER /* MSVC on Windows */ - -PUBLIC SYMBOL_NAME(square_unsigned) -_TEXT SEGMENT - -SYMBOL_NAME(square_unsigned) PROC - mov eax, ecx - imul eax, eax - ret -SYMBOL_NAME(square_unsigned) ENDP - -_TEXT ENDS -END - -#else - -.text -.globl SYMBOL_NAME(square_unsigned) -/* Only supported with GAS */ -# if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__sun) -.type square_unsigned,@function -# endif - -# if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ -SYMBOL_NAME(square_unsigned): - imull %ecx, %ecx - movl %ecx, %eax - retq -# else /* sysvabi */ -SYMBOL_NAME(square_unsigned): - imull %edi, %edi - movl %edi, %eax - retq -# endif - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/square-x86.S.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/square-x86.S.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/square-x86.S.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/square-x86.S.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -#include "symbol-underscore.h" - -#ifdef _MSC_VER - -.386 -.MODEL FLAT, C - -PUBLIC square_unsigned -_TEXT SEGMENT - -square_unsigned PROC var1:DWORD - mov eax, var1 - imul eax, eax - ret -square_unsigned ENDP - -_TEXT ENDS -END - -#else - -.text -.globl SYMBOL_NAME(square_unsigned) -/* Only supported with GAS */ -# if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) -.type square_unsigned,@function -# endif - -SYMBOL_NAME(square_unsigned): - movl 4(%esp), %eax - imull %eax, %eax - retl - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/symbol-underscore.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/symbol-underscore.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 generated assembly/symbol-underscore.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 generated assembly/symbol-underscore.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#if defined(MESON_TEST__UNDERSCORE_SYMBOL) -# define SYMBOL_NAME(name) _##name -#else -# define SYMBOL_NAME(name) name -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/four.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/four.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/four.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/four.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +int func(void); + +static int duplicate_func(void) { + return -4; +} + +int main(void) { + return duplicate_func() + func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/meson.build" 2021-10-23 16:49:18.000000000 +0000 @@ -0,0 +1,6 @@ +project('option override', 'c', + default_options : 'unity=on') + +executable('mustunity', 'one.c', 'two.c') +executable('notunity', 'three.c', 'four.c', + override_options : ['unity=off']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/one.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/one.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/one.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/one.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +static int hidden_func(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/three.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/three.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/three.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/three.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +static int duplicate_func(void) { + return 4; +} + +int func(void) { + return duplicate_func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/two.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/two.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/131 override options/two.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/131 override options/two.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +/* + * Requires a Unity build. Otherwise hidden_func is not specified. + */ +int main(void) { + return hidden_func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 build by default targets in tests/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 build by default targets in tests/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 build by default targets in tests/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 build by default targets in tests/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 build by default targets in tests/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 build by default targets in tests/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 build by default targets in tests/meson.build" 2020-01-07 21:08:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 build by default targets in tests/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -project('unit-test', 'c', version : '1.0') - -write_file = find_program('write_file.py') - -# A test that consumes and verifies the output generated by a custom target. -# Should work even if target is not built by default. Makes sure that foo.out -# is actually created before the test command that uses foo_out is run. -foo_out = custom_target('foo.out', - output : 'foo.out', - command : [write_file, '@OUTPUT@']) - -# Also verify that a build_by_default : false BuildTarget added to a test is -# built before the test is run. -exe_out = executable('out', 'main.c', build_by_default : false) - -py_file_exists = '''import os, sys -if not os.path.exists(sys.argv[1]) or not os.path.exists(sys.argv[2]): - print("could not find {!r} or {!r} in {!r}" - "".format(sys.argv[1], sys.argv[2], os.getcwd())) - sys.exit(1)''' - -python = import('python3').find_python() -test('output-check', python, args : ['-c', py_file_exists, foo_out, exe_out]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 build by default targets in tests/write_file.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 build by default targets in tests/write_file.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 build by default targets in tests/write_file.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 build by default targets in tests/write_file.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -with open(sys.argv[1], 'w') as f: - f.write('Test') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 get define/concat.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 get define/concat.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 get define/concat.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 get define/concat.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,24 @@ +#define __STRINGIFY(x) #x +#define TEST_STRINGIFY(x) __STRINGIFY(x) + +#define TEST_VERSION_MAJOR 6 +#define TEST_VERSION_MINOR 0 +#define TEST_VERSION_BUGFIX 0 + +#define TEST_VERSION_STR \ + TEST_STRINGIFY(TEST_VERSION_MAJOR) \ + "." TEST_STRINGIFY(TEST_VERSION_MINOR) "." TEST_STRINGIFY( \ + TEST_VERSION_BUGFIX) + +#define TEST_CONCAT_1 \ + "ab" \ + "cd" \ + "ef" \ + "" +#define TEST_CONCAT_2 1 +#define TEST_CONCAT_3 1 2 3 +#define TEST_CONCAT_4 "ab" 1 "cd" +#define TEST_CONCAT_5 \ + "ab\"" \ + "cd" +#define TEST_CONCAT_6 "ab\" \"cd" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 get define/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 get define/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 get define/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 get define/meson.build" 2021-10-23 16:49:21.000000000 +0000 @@ -0,0 +1,104 @@ +project('get define', 'c', 'cpp') + +host_system = host_machine.system() + +foreach lang : ['c', 'cpp'] + cc = meson.get_compiler(lang) + if host_system == 'linux' + d = cc.get_define('__linux__') + assert(d == '1', '__linux__ value is @0@ instead of 1'.format(d)) + elif host_system == 'darwin' + d = cc.get_define('__APPLE__') + assert(d == '1', '__APPLE__ value is @0@ instead of 1'.format(d)) + elif host_system == 'windows' + d = cc.get_define('_WIN32') + assert(d == '1', '_WIN32 value is @0@ instead of 1'.format(d)) + elif host_system == 'cygwin' + d = cc.get_define('__CYGWIN__') + assert(d == '1', '__CYGWIN__ value is @0@ instead of 1'.format(d)) + elif host_system == 'haiku' + d = cc.get_define('__HAIKU__') + assert(d == '1', '__HAIKU__ value is @0@ instead of 1'.format(d)) + elif host_system == 'freebsd' + # the __FreeBSD__ define will be equal to the major version of the release + # (ex, in FreeBSD 11.x, __FreeBSD__ == 11). To make the test robust when + # being run on various versions of FreeBSD, just test that the define is + # set. + d = cc.get_define('__FreeBSD__') + assert(d != '', '__FreeBSD__ value is unset') + elif host_system == 'dragonfly' + d = cc.get_define('__DragonFly__') + assert(d == '1', '__DragonFly__ value is @0@ instead of 1'.format(d)) + elif host_system == 'netbsd' + d = cc.get_define('__NetBSD__') + assert(d == '1', '__NetBSD__ value is @0@ instead of 1'.format(d)) + elif host_system == 'openbsd' + d = cc.get_define('__OpenBSD__') + assert(d == '1', '__OpenBSD__ value is @0@ instead of 1'.format(d)) + elif host_system == 'gnu' + d = cc.get_define('__GNU__') + assert(d == '1', '__GNU__ value is @0@ instead of 1'.format(d)) + elif host_system == 'sunos' + d = cc.get_define('__sun__') + assert(d == '1', '__sun__ value is @0@ instead of 1'.format(d)) + else + error('Please report a bug and help us improve support for this platform') + endif + + if cc.find_library('z', required : false).found() + # When a C file containing #include is pre-processed and foo.h is + # found in the compiler's default search path, GCC inserts an extra comment + # between the delimiter and the define which causes a parsing error. + # https://github.com/mesonbuild/meson/issues/1726 + if host_machine.system() == 'netbsd' or host_machine.system() == 'openbsd' + # NetBSD and OpenBSD's zlib don't have a ZLIB_VER_MAJOR, but they do have + # a ZLIB_VERSION (which is a string), so check the first non-quote + # character of that. + ver = cc.get_define('ZLIB_VERSION', prefix : '#include ')[1] + assert(ver == '1', 'ZLIB_VERSION (major) value is "@0@" instead of "1"'.format(ver)) + else + ver = cc.get_define('ZLIB_VER_MAJOR', prefix : '#include ') + assert(ver == '1', 'ZLIB_VER_MAJOR value is "@0@" instead of "1"'.format(ver)) + endif + endif + + # Check that an undefined value is empty. + have = cc.get_define('MESON_FAIL_VALUE') + assert(have == '', 'MESON_FAIL_VALUE value is "@0@" instead of ""'.format(have)) + + # This is used in the test_preprocessor_checks_CPPFLAGS() unit test. + have = cc.get_define('MESON_TEST_DEFINE_VALUE') + expect = get_option('MESON_TEST_DEFINE_VALUE') + assert(have == expect, 'MESON_TEST_DEFINE_VALUE value is "@0@" instead of "@1@"'.format(have, expect)) + + run_1665_test = false + if meson.is_cross_build() + lang_arg = meson.get_cross_property(lang + '_args', '') + if lang_arg == '-DMESON_TEST_ISSUE_1665=1' + run_1665_test = true + endif + endif + + if run_1665_test + have = cc.get_define('MESON_TEST_ISSUE_1665') + assert(have == '1', 'MESON_TEST_ISSUE_1665 value is "@0@" instead of "1"'.format(have)) + endif + + have = cc.get_define('TEST_VERSION_STR', + prefix : '#include ', include_directories: include_directories('.')) + assert(have == '"6.0.0"', 'TEST_VERSION_STR value is "@0@" instead of ""6.0.0""'.format(have)) + + concat_examples = { + 'TEST_CONCAT_1': '"abcdef"', + 'TEST_CONCAT_2': '1', + 'TEST_CONCAT_3': '1 2 3', + 'TEST_CONCAT_4': '"ab" 1 "cd"', + 'TEST_CONCAT_5': '"ab\"cd"', + 'TEST_CONCAT_6': '"ab\" \"cd"', + } + foreach def,expected : concat_examples + have = cc.get_define(def, + prefix : '#include ', include_directories: include_directories('.')) + assert(have == expected, '@0@ value is "@1@" instead of "@2@"'.format(def, have, expected)) + endforeach +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 get define/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 get define/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/132 get define/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/132 get define/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +option('MESON_TEST_DEFINE_VALUE', type : 'string', value : '') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/checkexists.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/checkexists.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/checkexists.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/checkexists.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env python3 - -import os.path, sys - -invert = False -for path in sys.argv[1:]: - if path == '--not': - invert = True - elif not os.path.exists(path) ^ invert: - sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/foo.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("Existentialism.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/meson.build" 2020-01-07 21:08:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -project('build on all', 'c') - -py3_mod = import('python3') -py3 = py3_mod.find_python() - -executable('fooprog', 'foo.c', - build_by_default : false, -) - -executable('barprog', 'foo.c', - build_by_default : false, - build_always : true, -) - -comp = files('mygen.py') -checkexists = files('checkexists.py') - -mytarget = custom_target('gendat1', - output : 'generated1.dat', - input : 'source.txt', - command : [py3] + comp + ['@INPUT@', '@OUTPUT@'], - build_by_default : true, -) - -mytarget = custom_target('gendat2', - output : 'generated2.dat', - input : 'source.txt', - command : [py3] + comp + ['@INPUT@', '@OUTPUT@'], - build_by_default : true, - build_always : false, -) - -ct1_output = join_paths(meson.build_root(), 'generated1.dat') -ct2_output = join_paths(meson.build_root(), 'generated2.dat') -exe1_output = join_paths(meson.build_root(), 'fooprog') -exe2_output = join_paths(meson.build_root(), 'barprog') - -if host_machine.system() == 'windows' - exe1_output += '.exe' - exe2_output += '.exe' -endif - -test('check-build-by-default', py3, - args : [checkexists, - ct1_output, ct2_output, '--not', exe1_output, exe2_output]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/mygen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/mygen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/mygen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/mygen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -ifile = open(sys.argv[1]) -ofile = open(sys.argv[2], 'w') - -ofile.write(ifile.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 build by default/source.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 build by default/source.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -I am a bunch of text. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +int get_retval(void); + +int main(void) { + printf("C seems to be working.\n"); + return get_retval(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include + +extern "C" { + int get_retval(void); + int get_cval(void); +} + +int main(void) { + std::cout << "C++ seems to be working." << std::endl; + return get_retval(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/meson.build" 2021-10-23 16:49:23.000000000 +0000 @@ -0,0 +1,23 @@ +project('c cpp and asm', 'c', 'cpp') + +cpu = host_machine.cpu_family() +cc = meson.get_compiler('c') + +supported_cpus = ['arm', 'x86', 'x86_64'] + +if not supported_cpus.contains(cpu) + error('MESON_SKIP_TEST unsupported cpu:' + cpu) +endif + +if meson.get_compiler('c').get_argument_syntax() == 'msvc' + error('MESON_SKIP_TEST MSVC can\'t compile assembly') +endif + +if cc.symbols_have_underscore_prefix() + add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language: 'c') +endif + +test('test-c-asm', executable('c-asm', ['main.c', 'retval-' + cpu + '.S'])) +test('test-cpp-asm', executable('cpp-asm', ['main.cpp', 'retval-' + cpu + '.S'])) +test('test-c-cpp-asm', executable('c-cpp-asm', ['somelib.c', 'main.cpp', 'retval-' + cpu + '.S'])) +test('test-cpp-c-asm', executable('cpp-c-asm', ['main.cpp', 'somelib.c', 'retval-' + cpu + '.S'])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/retval-arm.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/retval-arm.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/retval-arm.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/retval-arm.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) +# ifdef __linux__ +.type get_retval, %function +#endif + +SYMBOL_NAME(get_retval): + mov r0, #0 + mov pc, lr diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/retval-x86_64.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/retval-x86_64.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/retval-x86_64.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/retval-x86_64.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) +# ifdef __linux__ +.type get_retval, %function +#endif + +SYMBOL_NAME(get_retval): + xorl %eax, %eax + retq diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/retval-x86.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/retval-x86.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/retval-x86.S" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/retval-x86.S" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) +/* Only supported on Linux with GAS */ +# ifdef __linux__ +.type get_retval, %function +#endif + +SYMBOL_NAME(get_retval): + xorl %eax, %eax + retl diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/somelib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/somelib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/somelib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/somelib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int get_cval (void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/symbol-underscore.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/symbol-underscore.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/133 c cpp and asm/symbol-underscore.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/133 c cpp and asm/symbol-underscore.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#if defined(MESON_TEST__UNDERSCORE_SYMBOL) +# define SYMBOL_NAME(name) _##name +#else +# define SYMBOL_NAME(name) name +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 compute int/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 compute int/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 compute int/config.h.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 compute int/config.h.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +#define INTSIZE @INTSIZE@ +#define FOOBAR_IN_CONFIG_H @FOOBAR@ +#define MAXINT @MAXINT@ +#define MININT @MININT@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 compute int/foobar.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 compute int/foobar.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 compute int/foobar.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 compute int/foobar.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef __FOOBAR_H__ +#define __FOOBAR_H__ + +#define FOOBAR_IN_FOOBAR_H 10 + +#endif /*__FOOBAR_H__*/ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 compute int/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 compute int/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 compute int/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 compute int/meson.build" 2021-10-23 16:49:26.000000000 +0000 @@ -0,0 +1,46 @@ +project('compute int', 'c', 'cpp') + +inc = include_directories('.') + +# Test with C +cc = meson.get_compiler('c') + +intsize = cc.compute_int('sizeof(int)', low : 1, high : 16, guess : 4) +foobar = cc.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc) +maxint = cc.compute_int('INT_MAX', prefix: '#include ') +minint = cc.compute_int('INT_MIN', prefix: '#include ') + +# Regression test for the special case -1 that used to fail when cross compiling +assert(cc.compute_int('-1') == -1, 'compute_int(-1) failed') + +cd = configuration_data() +cd.set('INTSIZE', intsize) +cd.set('FOOBAR', foobar) +cd.set('CONFIG', 'config.h') +cd.set('MAXINT', maxint) +cd.set('MININT', minint) +configure_file(input : 'config.h.in', output : 'config.h', configuration : cd) +s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd) + +e = executable('prog', s) +test('compute int test', e) + +# Test with C++ +cpp = meson.get_compiler('cpp') + +intsize = cpp.compute_int('sizeof(int)') +foobar = cpp.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc) +maxint = cpp.compute_int('INT_MAX', prefix: '#include ') +minint = cpp.compute_int('INT_MIN', prefix: '#include ') + +cdpp = configuration_data() +cdpp.set('INTSIZE', intsize) +cdpp.set('FOOBAR', foobar) +cdpp.set('CONFIG', 'config.hpp') +cdpp.set('MAXINT', maxint) +cdpp.set('MININT', minint) +configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp) +spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp) + +epp = executable('progpp', spp) +test('compute int test c++', epp) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 compute int/prog.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 compute int/prog.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 compute int/prog.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 compute int/prog.c.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,25 @@ +#include "@CONFIG@" +#include +#include +#include +#include "foobar.h" + +int main(void) { + if(INTSIZE != sizeof(int)) { + fprintf(stderr, "Mismatch: computed int size %d, actual size %d.\n", INTSIZE, (int)sizeof(int)); + return 1; + } + if(FOOBAR_IN_CONFIG_H != FOOBAR_IN_FOOBAR_H) { + fprintf(stderr, "Mismatch: computed int %d, should be %d.\n", FOOBAR_IN_CONFIG_H, FOOBAR_IN_FOOBAR_H); + return 1; + } + if(MAXINT != INT_MAX) { + fprintf(stderr, "Mismatch: computed max int %d, should be %d.\n", MAXINT, INT_MAX); + return 1; + } + if(MININT != INT_MIN) { + fprintf(stderr, "Mismatch: computed min int %d, should be %d.\n", MININT, INT_MIN); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/ctsub/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/ctsub/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/ctsub/copyfile.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/ctsub/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import shutil - -shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/ctsub/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/ctsub/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/ctsub/main.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/ctsub/main.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#error "ctsub/main.h included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/ctsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/ctsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/ctsub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/ctsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -# https://github.com/mesonbuild/meson/pull/2291 -copy = find_program('copyfile.py') -configure_file(input : 'main.h', - output : 'main.h', - command : [copy, '@INPUT@', '@OUTPUT@']) -ctfile = custom_target('emptyfile', - input : 'emptyfile.c', - output : 'emptyfile.c', - command : [copy, '@INPUT@', '@OUTPUT@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/inc1/hdr.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/inc1/hdr.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/inc1/hdr.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/inc1/hdr.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#define SOME_DEFINE 42 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/inc2/hdr.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/inc2/hdr.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/inc2/hdr.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/inc2/hdr.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#undef SOME_DEFINE diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/meson.build" 2020-01-07 21:08:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -project('include order', 'c') - -# Test that the order of priority of include paths (from first to last) is: -# -# 1. Target's current build directory -# 2. Target's current source directory -# 3. Include paths added with the `c_args:` kwarg -# 4. Include paths added with the `include_directories`: kwarg -# Within this, the build dir takes precedence over the source dir -# 5. Include paths added via `include_directories:` of internal deps -# Within this, the build dir takes precedence over the source dir - -# Custom target dir with a built header -subdir('ctsub') -# Defines an internal dep -subdir('sub1') -# Defines a per-target include path -subdir('sub2') -# Directory for `c_args:` include path -subdir('sub3') -# The directory where the target resides -subdir('sub4') - -# Test that the order in which internal dependencies are specified is -# preserved. This is needed especially when subprojects get involved and -# multiple build-root config.h files exist, and we must be sure that the -# correct one is found: https://github.com/mesonbuild/meson/issues/1495 -f = executable('somefxe', 'sub4/main.c', - dependencies : [correctinc, dep, wronginc]) - -test('eh', e) -test('oh', f) - -# Test that the order in include_directories() is maintained -incs = include_directories('inc1', 'inc2') -executable('ordertest', 'ordertest.c', include_directories: incs) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/ordertest.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/ordertest.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/ordertest.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/ordertest.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include "hdr.h" - -#if !defined(SOME_DEFINE) || SOME_DEFINE != 42 -#error "Should have picked up hdr.h from inc1/hdr.h" -#endif - -int main(void) -{ - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub1/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub1/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub1/main.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub1/main.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#error "sub1/main.h included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -i = include_directories('.') -l = shared_library('somelib', 'some.c') -dep = declare_dependency(link_with : l, - include_directories : i) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub1/some.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub1/some.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub1/some.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub1/some.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - __declspec(dllexport) -#endif -int somefunc(void) { - return 1984; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub1/some.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub1/some.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub1/some.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub1/some.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#pragma once - -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllimport) -#else - #define DLL_PUBLIC -#endif - -DLL_PUBLIC -int somefunc(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub2/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub2/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub2/main.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub2/main.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#error "sub2/main.h included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub2/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -j = include_directories('.') -wronginc = declare_dependency(include_directories : j) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub3/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub3/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub3/main.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub3/main.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#error "sub3/main.h included" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub3/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub3/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -sub3 = meson.current_source_dir() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub4/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub4/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub4/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub4/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -/* Use the <> include notation to force searching in include directories */ -#include - -int main(void) { - if (somefunc() == 1984) - return 0; - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub4/main.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub4/main.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub4/main.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub4/main.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#pragma once - -#include "some.h" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub4/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub4/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/134 include order/sub4/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/134 include order/sub4/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -e = executable('someexe', 'main.c', ctfile, - c_args : ['-I' + sub3], - include_directories : j, - dependencies : dep) - -correctinc = declare_dependency(include_directories : include_directories('.')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/meson.build" 2021-10-23 16:49:23.000000000 +0000 @@ -0,0 +1,16 @@ +project('custom target object output', 'c') + +comp = find_program('obj_generator.py') + +if host_machine.system() == 'windows' + outputname = '@BASENAME@.obj' +else + outputname = '@BASENAME@.o' +endif + +cc = meson.get_compiler('c').cmd_array().get(-1) + +subdir('objdir') +subdir('progdir') + +test('objgen', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/objdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/objdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/objdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/objdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +# Generate an object file manually. +object = custom_target('object', + input : 'source.c', + output : outputname, + command : [comp, cc, '@INPUT@', '@OUTPUT@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/objdir/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/objdir/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/objdir/source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/objdir/source.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func1_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/obj_generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/obj_generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/obj_generator.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/obj_generator.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# Mimic a binary that generates an object file (e.g. windres). + +import sys, subprocess + +if __name__ == '__main__': + if len(sys.argv) != 4: + print(sys.argv[0], 'compiler input_file output_file') + sys.exit(1) + compiler = sys.argv[1] + ifile = sys.argv[2] + ofile = sys.argv[3] + if compiler.endswith('cl'): + cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] + else: + cmd = [compiler, '-c', ifile, '-o', ofile] + sys.exit(subprocess.call(cmd)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/progdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/progdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/progdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/progdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +e = executable('prog', 'prog.c', object) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/progdir/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/progdir/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 custom target object output/progdir/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 custom target object output/progdir/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int func1_in_obj(void); + +int main(void) { + return func1_in_obj(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/four.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/four.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/four.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/four.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -int func(void); - -static int duplicate_func(void) { - return -4; -} - -int main(void) { - return duplicate_func() + func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/meson.build" 2020-01-07 21:08:23.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -project('option override', 'c', - default_options : 'unity=on') - -executable('mustunity', 'one.c', 'two.c') -executable('notunity', 'three.c', 'four.c', - override_options : ['unity=off']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/one.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/one.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/one.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/one.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -static int hidden_func(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/three.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/three.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/three.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/three.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -static int duplicate_func(void) { - return 4; -} - -int func(void) { - return duplicate_func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/two.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/two.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/135 override options/two.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/135 override options/two.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -/* - * Requires a Unity build. Otherwise hidden_func is not specified. - */ -int main(void) { - return hidden_func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/136 empty build file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/136 empty build file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/136 empty build file/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/136 empty build file/meson.build" 2021-10-23 16:49:23.000000000 +0000 @@ -0,0 +1,2 @@ +project('subdir with empty meson.build test', 'c') +subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/136 get define/concat.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/136 get define/concat.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/136 get define/concat.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/136 get define/concat.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#define __STRINGIFY(x) #x -#define TEST_STRINGIFY(x) __STRINGIFY(x) - -#define TEST_VERSION_MAJOR 6 -#define TEST_VERSION_MINOR 0 -#define TEST_VERSION_BUGFIX 0 - -#define TEST_VERSION_STR \ - TEST_STRINGIFY(TEST_VERSION_MAJOR) \ - "." TEST_STRINGIFY(TEST_VERSION_MINOR) "." TEST_STRINGIFY( \ - TEST_VERSION_BUGFIX) - -#define TEST_CONCAT_1 \ - "ab" \ - "cd" \ - "ef" \ - "" -#define TEST_CONCAT_2 1 -#define TEST_CONCAT_3 1 2 3 -#define TEST_CONCAT_4 "ab" 1 "cd" -#define TEST_CONCAT_5 \ - "ab\"" \ - "cd" -#define TEST_CONCAT_6 "ab\" \"cd" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/136 get define/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/136 get define/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/136 get define/meson.build" 2020-01-07 21:08:25.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/136 get define/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -project('get define', 'c', 'cpp') - -host_system = host_machine.system() - -foreach lang : ['c', 'cpp'] - cc = meson.get_compiler(lang) - if host_system == 'linux' - d = cc.get_define('__linux__') - assert(d == '1', '__linux__ value is @0@ instead of 1'.format(d)) - elif host_system == 'darwin' - d = cc.get_define('__APPLE__') - assert(d == '1', '__APPLE__ value is @0@ instead of 1'.format(d)) - elif host_system == 'windows' - d = cc.get_define('_WIN32') - assert(d == '1', '_WIN32 value is @0@ instead of 1'.format(d)) - elif host_system == 'cygwin' - d = cc.get_define('__CYGWIN__') - assert(d == '1', '__CYGWIN__ value is @0@ instead of 1'.format(d)) - elif host_system == 'haiku' - d = cc.get_define('__HAIKU__') - assert(d == '1', '__HAIKU__ value is @0@ instead of 1'.format(d)) - elif host_system == 'freebsd' - # the __FreeBSD__ define will be equal to the major version of the release - # (ex, in FreeBSD 11.x, __FreeBSD__ == 11). To make the test robust when - # being run on various versions of FreeBSD, just test that the define is - # set. - d = cc.get_define('__FreeBSD__') - assert(d != '', '__FreeBSD__ value is unset') - elif host_system == 'dragonfly' - d = cc.get_define('__DragonFly__') - assert(d == '1', '__DragonFly__ value is @0@ instead of 1'.format(d)) - elif host_system == 'netbsd' - d = cc.get_define('__NetBSD__') - assert(d == '1', '__NetBSD__ value is @0@ instead of 1'.format(d)) - elif host_system == 'openbsd' - d = cc.get_define('__OpenBSD__') - assert(d == '1', '__OpenBSD__ value is @0@ instead of 1'.format(d)) - elif host_system == 'gnu' - d = cc.get_define('__GNU__') - assert(d == '1', '__GNU__ value is @0@ instead of 1'.format(d)) - elif host_system == 'sunos' - d = cc.get_define('__sun__') - assert(d == '1', '__sun__ value is @0@ instead of 1'.format(d)) - else - error('Please report a bug and help us improve support for this platform') - endif - - if cc.find_library('z', required : false).found() - # When a C file containing #include is pre-processed and foo.h is - # found in the compiler's default search path, GCC inserts an extra comment - # between the delimiter and the define which causes a parsing error. - # https://github.com/mesonbuild/meson/issues/1726 - if host_machine.system() == 'netbsd' or host_machine.system() == 'openbsd' - # NetBSD and OpenBSD's zlib don't have a ZLIB_VER_MAJOR, but they do have - # a ZLIB_VERSION (which is a string), so check the first non-quote - # character of that. - ver = cc.get_define('ZLIB_VERSION', prefix : '#include ')[1] - assert(ver == '1', 'ZLIB_VERSION (major) value is "@0@" instead of "1"'.format(ver)) - else - ver = cc.get_define('ZLIB_VER_MAJOR', prefix : '#include ') - assert(ver == '1', 'ZLIB_VER_MAJOR value is "@0@" instead of "1"'.format(ver)) - endif - endif - - # Check that an undefined value is empty. - have = cc.get_define('MESON_FAIL_VALUE') - assert(have == '', 'MESON_FAIL_VALUE value is "@0@" instead of ""'.format(have)) - - # This is used in the test_preprocessor_checks_CPPFLAGS() unit test. - have = cc.get_define('MESON_TEST_DEFINE_VALUE') - expect = get_option('MESON_TEST_DEFINE_VALUE') - assert(have == expect, 'MESON_TEST_DEFINE_VALUE value is "@0@" instead of "@1@"'.format(have, expect)) - - run_1665_test = false - if meson.is_cross_build() - lang_arg = meson.get_cross_property(lang + '_args', '') - if lang_arg == '-DMESON_TEST_ISSUE_1665=1' - run_1665_test = true - endif - endif - - if run_1665_test - have = cc.get_define('MESON_TEST_ISSUE_1665') - assert(have == '1', 'MESON_TEST_ISSUE_1665 value is "@0@" instead of "1"'.format(have)) - endif - - have = cc.get_define('TEST_VERSION_STR', - prefix : '#include ', include_directories: include_directories('.')) - assert(have == '"6.0.0"', 'TEST_VERSION_STR value is "@0@" instead of ""6.0.0""'.format(have)) - - concat_examples = { - 'TEST_CONCAT_1': '"abcdef"', - 'TEST_CONCAT_2': '1', - 'TEST_CONCAT_3': '1 2 3', - 'TEST_CONCAT_4': '"ab" 1 "cd"', - 'TEST_CONCAT_5': '"ab\"cd"', - 'TEST_CONCAT_6': '"ab\" \"cd"', - } - foreach def,expected : concat_examples - have = cc.get_define(def, - prefix : '#include ', include_directories: include_directories('.')) - assert(have == expected, '@0@ value is "@1@" instead of "@2@"'.format(def, have, expected)) - endforeach -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/136 get define/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/136 get define/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/136 get define/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/136 get define/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -option('MESON_TEST_DEFINE_VALUE', type : 'string', value : '') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include - -int get_retval(void); - -int main(void) { - printf("C seems to be working.\n"); - return get_retval(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/main.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include - -extern "C" { - int get_retval(void); - int get_cval(void); -} - -int main(void) { - std::cout << "C++ seems to be working." << std::endl; - return get_retval(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/meson.build" 2020-01-07 21:08:26.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -project('c cpp and asm', 'c', 'cpp') - -cpu = host_machine.cpu_family() -cc = meson.get_compiler('c') - -supported_cpus = ['arm', 'x86', 'x86_64'] - -if not supported_cpus.contains(cpu) - error('MESON_SKIP_TEST unsupported cpu:' + cpu) -endif - -if meson.get_compiler('c').get_argument_syntax() == 'msvc' - error('MESON_SKIP_TEST MSVC can\'t compile assembly') -endif - -if cc.symbols_have_underscore_prefix() - add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language: 'c') -endif - -test('test-c-asm', executable('c-asm', ['main.c', 'retval-' + cpu + '.S'])) -test('test-cpp-asm', executable('cpp-asm', ['main.cpp', 'retval-' + cpu + '.S'])) -test('test-c-cpp-asm', executable('c-cpp-asm', ['somelib.c', 'main.cpp', 'retval-' + cpu + '.S'])) -test('test-cpp-c-asm', executable('cpp-c-asm', ['main.cpp', 'somelib.c', 'retval-' + cpu + '.S'])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/retval-arm.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/retval-arm.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/retval-arm.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/retval-arm.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include "symbol-underscore.h" - -.text -.globl SYMBOL_NAME(get_retval) -# ifdef __linux__ -.type get_retval, %function -#endif - -SYMBOL_NAME(get_retval): - mov r0, #0 - mov pc, lr diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/retval-x86_64.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/retval-x86_64.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/retval-x86_64.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/retval-x86_64.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include "symbol-underscore.h" - -.text -.globl SYMBOL_NAME(get_retval) -# ifdef __linux__ -.type get_retval, %function -#endif - -SYMBOL_NAME(get_retval): - xorl %eax, %eax - retq diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/retval-x86.S" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/retval-x86.S" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/retval-x86.S" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/retval-x86.S" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#include "symbol-underscore.h" - -.text -.globl SYMBOL_NAME(get_retval) -/* Only supported on Linux with GAS */ -# ifdef __linux__ -.type get_retval, %function -#endif - -SYMBOL_NAME(get_retval): - xorl %eax, %eax - retl diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/somelib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/somelib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/somelib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/somelib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int get_cval (void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/symbol-underscore.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/symbol-underscore.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 c cpp and asm/symbol-underscore.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 c cpp and asm/symbol-underscore.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#if defined(MESON_TEST__UNDERSCORE_SYMBOL) -# define SYMBOL_NAME(name) _##name -#else -# define SYMBOL_NAME(name) name -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/exe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/exe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/exe/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/exe/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +exe = executable('prog', '../prog.c', link_with : sh_func2_linked_func1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/exe2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/exe2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/exe2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/exe2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +exe2 = executable('prog2', '../prog.c', link_with : sh_only_link_whole) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/exe3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/exe3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/exe3/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/exe3/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +exe3 = executable('prog3', '../prog.c', link_with : sh_func2_dep_func1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/exe4/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/exe4/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/exe4/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/exe4/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +exe4 = executable('prog4', '../prog.c', link_with : sh_func2_transdep_func1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/func1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/func1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/func1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/func1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#define BUILDING_DLL + +#include + +int func1(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/func2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/func2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/func2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/func2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#define BUILDING_DLL + +#include + +int func2(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/meson.build" 2021-10-23 16:49:25.000000000 +0000 @@ -0,0 +1,49 @@ +project('whole archive', 'c') + +if meson.backend() == 'xcode' or \ + meson.backend() == 'vs2010' or \ + meson.backend() == 'vs2012' or \ + meson.backend() == 'vs2013' + error('MESON_SKIP_TEST: whole-archive not supported in Xcode nor pre-VS2015 IDE. Patches welcome.') +endif + +add_project_arguments('-I' + meson.source_root(), language : 'c') + +# Test 1: link_whole keeps all symbols +# Make static func1 +subdir('st_func1') +# Make shared func2 linking whole func1 archive +subdir('sh_func2_linked_func1') +# Link exe with shared library only +subdir('exe') +# Test that both func1 and func2 are accessible from shared library +test('prog', exe) + +# Test 2: link_whole can be used instead of source list, see #2180 +# Make static func2 +subdir('st_func2') +# Link both func1 and func2 into same shared library +# which does not have any sources other than 2 static libraries +subdir('sh_only_link_whole') +# Link exe2 with shared library only +subdir('exe2') +# Test that both func1 and func2 are accessible from shared library +test('prog2', exe2) + +# Test 3: link_whole can be used in declare_dependency() +func1_dep = declare_dependency(link_whole : [st_func1]) +# Use dependency to link func1 into shared library +subdir('sh_func2_dep_func1') +# Link exe3 with shared library +subdir('exe3') +# Test that both func1 and func2 are accessible from shared library +test('prog3', exe3) + +# Test 4: link_whole can be used in transitive declare_dependency() +func1_trans_dep = declare_dependency(dependencies : func1_dep) +# Use transitive dependency to link func1 into shared library +subdir('sh_func2_transdep_func1') +# Link exe4 with shared library +subdir('exe4') +# Test that both func1 and func2 are accessible from shared library +test('prog4', exe4) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/mylib.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/mylib.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/mylib.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/mylib.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,21 @@ +#pragma once + +/* Both funcs here for simplicity. */ + +#if defined _WIN32 || defined __CYGWIN__ +#if defined BUILDING_DLL + #define DLL_PUBLIC __declspec(dllexport) +#else + #define DLL_PUBLIC __declspec(dllimport) +#endif +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC func1(void); +int DLL_PUBLIC func2(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int main(void) { + return func1() - func2(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/sh_func2_dep_func1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/sh_func2_dep_func1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/sh_func2_dep_func1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/sh_func2_dep_func1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +# Same as sh_func2_linked_func1, # func2.c does not depend on func1(), +# so without link_whole compiler would throw func1() away. +# This is the same version of the test with a dependency object instead. +sh_func2_dep_func1 = shared_library('sh_func2_dep_func1', '../func2.c', dependencies : func1_dep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/sh_func2_linked_func1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/sh_func2_linked_func1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/sh_func2_linked_func1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/sh_func2_linked_func1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +# Nothing in func2.c uses func1, so the linker would throw it +# away and thus linking the exe would fail. +sh_func2_linked_func1 = shared_library('sh_func2_linked_func1', '../func2.c', link_whole : st_func1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/sh_func2_transdep_func1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/sh_func2_transdep_func1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/sh_func2_transdep_func1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/sh_func2_transdep_func1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +# Same as sh_func2_dep_func1 but dependency is transitive. +# func2.c does not have any reference to func1() so without link_whole compiler +# should throw func1() out. +sh_func2_transdep_func1 = shared_library( + 'sh_func2_transdep_func1', '../func2.c', + dependencies : func1_trans_dep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/sh_only_link_whole/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/sh_only_link_whole/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/sh_only_link_whole/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/sh_only_link_whole/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +sh_only_link_whole = shared_library('sh_only_link_whole', link_whole : [st_func1, st_func2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/st_func1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/st_func1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/st_func1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/st_func1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +st_func1 = static_library('st_func1', '../func1.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/st_func2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/st_func2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/137 whole archive/st_func2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/137 whole archive/st_func2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +st_func2 = static_library('st_func2', '../func2.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foobar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foobar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foobar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foobar.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,27 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ + +#include "foo.h" +#include "foo.hpp" +#include "foobar.h" + +int get_number_index (void) { + return 1; +} + +void mynumbers(int nums[]) { + nums[0] = forty_two(); + nums[1] = six_one(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foobar.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foobar.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foobar.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foobar.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ + +void mynumbers(int nums[]); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ +#include "foo.h" + +int forty_two(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foo.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foo.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foo.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foo.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,34 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ +#include + +const int cnums[] = {0, 61}; + +/* Provided by foobar.c */ +extern "C" int get_number_index (void); + +template +std::vector makeVector(const T (&data)[N]) +{ + return std::vector(data, data+N); +} + +namespace { + std::vector numbers = makeVector(cnums); +} + +extern "C" int six_one(void) { + return numbers[get_number_index ()]; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foo.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foo.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ + +int forty_two(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foo.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foo.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/foo.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/foo.hpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,24 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +int six_one(void); + +#ifdef __cplusplus +} +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/meson.build" 2021-10-23 16:49:28.000000000 +0000 @@ -0,0 +1,133 @@ +# Copyright © 2017 Dylan Baker +# +# 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. + +project('C and C++ static link test', ['c', 'cpp']) + +if meson.backend() == 'xcode' + error('''MESON_SKIP_TEST: overriding link language is not supported in Xcode. + +If you really need this, then patches are welcome. The only known way is +to create a dummy C++ file in the meson-private directory and adding +that to the target's source list when needed. The primitives exist +but may need some tweaking. Grep for language_stdlib_only_link_flags to find +where this is handled in other backends.''') +endif + +# Verify that adding link arguments works. +add_global_link_arguments('', language : 'c') +add_project_link_arguments('', language : 'c') + +libc = static_library('cfoo', ['foo.c', 'foo.h']) + +# Test that linking C libs to external static C++ libs uses the C++ linker +# Since we can't depend on the test system to provide this, we create one +# ourselves at configure time and then 'find' it with cxx.find_library(). +cxx = meson.get_compiler('cpp') + +if cxx.get_argument_syntax() == 'msvc' + if cxx.get_id() == 'msvc' + static_linker = find_program('lib') + elif cxx.get_id() == 'clang-cl' + static_linker = find_program('llvm-lib') + elif cxx.get_id() == 'intel-cl' + static_linker = find_program('xilib') + else + error('unable to determine static linker to use with this compiler') + endif + compile_cmd = ['/c', '@INPUT@', '/Fo@OUTPUT@'] + stlib_cmd = [static_linker, '/OUT:@OUTPUT@', '@INPUT@'] +else + picflag = [] + if not ['darwin', 'windows'].contains(host_machine.system()) + picflag = ['-fPIC'] + endif + compile_cmd = ['-c', picflag, '@INPUT@', '-o', '@OUTPUT@'] + stlib_cmd = ['ar', 'csr', '@OUTPUT@', '@INPUT@'] +endif + +foo_cpp_o = configure_file( + input : 'foo.cpp', + output : 'foo.cpp.o', + command : cxx.cmd_array() + compile_cmd) + +configure_file( + input : foo_cpp_o, + output : 'libstcppext.a', + command : stlib_cmd) + +libstcppext = cxx.find_library('stcppext', dirs : meson.current_build_dir()) +lib_type_name = libstcppext.type_name() +assert(lib_type_name == 'library', 'type name is ' + lib_type_name) + +libfooext = shared_library( + 'fooext', + ['foobar.c', 'foobar.h'], + link_with : libc, + dependencies : libstcppext, +) + +# Test that linking C libs to internal static C++ libs uses the C++ linker +libcpp = static_library('cppfoo', ['foo.cpp', 'foo.hpp']) + +libfoo = shared_library( + 'foo', + ['foobar.c', 'foobar.h'], + link_with : [libc, libcpp], +) + +# Test that link_whole is also honored +# +# VS2010 lacks the /WHOLEARCHIVE option that later versions of MSVC support, so +# don't run this tests on that backend. +if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19')) + libfoowhole = shared_library( + 'foowhole', + ['foobar.c', 'foobar.h'], + link_whole : [libc, libcpp], + ) +endif + +# Test sublinking (linking C and C++, then linking that to C) +libfoo_static = static_library( + 'foo_static', + ['foobar.c', 'foobar.h'], + link_with : [libc, libcpp], +) + +libsub = shared_library( + 'sub', + ['sub.c', 'sub.h'], + link_with : libfoo_static, +) + +if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19')) + libsubwhole = shared_library( + 'subwhole', + ['sub.c', 'sub.h'], + link_whole : libfoo_static, + ) +endif + +# Test that it really is recursive +libsub_static = static_library( + 'sub_static', + ['sub.c', 'sub.h'], + link_with : libfoo_static, +) + +libsubsub = shared_library( + 'subsub', + ['dummy.c'], + link_with : libsub_static, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/sub.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/sub.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ +#include "sub.h" + +float a_half(void) { + return .5; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 C and CPP link/sub.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 C and CPP link/sub.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ + +float a_half(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 compute int/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 compute int/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 compute int/config.h.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 compute int/config.h.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -#define INTSIZE @INTSIZE@ -#define FOOBAR_IN_CONFIG_H @FOOBAR@ -#define MAXINT @MAXINT@ -#define MININT @MININT@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 compute int/foobar.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 compute int/foobar.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 compute int/foobar.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 compute int/foobar.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef __FOOBAR_H__ -#define __FOOBAR_H__ - -#define FOOBAR_IN_FOOBAR_H 10 - -#endif /*__FOOBAR_H__*/ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 compute int/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 compute int/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 compute int/meson.build" 2020-01-07 21:08:30.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 compute int/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -project('compute int', 'c', 'cpp') - -inc = include_directories('.') - -# Test with C -cc = meson.get_compiler('c') - -intsize = cc.compute_int('sizeof(int)', low : 1, high : 16, guess : 4) -foobar = cc.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc) -maxint = cc.compute_int('INT_MAX', prefix: '#include ') -minint = cc.compute_int('INT_MIN', prefix: '#include ') - -# Regression test for the special case -1 that used to fail when cross compiling -assert(cc.compute_int('-1') == -1, 'compute_int(-1) failed') - -cd = configuration_data() -cd.set('INTSIZE', intsize) -cd.set('FOOBAR', foobar) -cd.set('CONFIG', 'config.h') -cd.set('MAXINT', maxint) -cd.set('MININT', minint) -configure_file(input : 'config.h.in', output : 'config.h', configuration : cd) -s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd) - -e = executable('prog', s) -test('compute int test', e) - -# Test with C++ -cpp = meson.get_compiler('cpp') - -intsize = cpp.compute_int('sizeof(int)') -foobar = cpp.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc) -maxint = cpp.compute_int('INT_MAX', prefix: '#include ') -minint = cpp.compute_int('INT_MIN', prefix: '#include ') - -cdpp = configuration_data() -cdpp.set('INTSIZE', intsize) -cdpp.set('FOOBAR', foobar) -cdpp.set('CONFIG', 'config.hpp') -cdpp.set('MAXINT', maxint) -cdpp.set('MININT', minint) -configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp) -spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp) - -epp = executable('progpp', spp) -test('compute int test c++', epp) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 compute int/prog.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 compute int/prog.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/138 compute int/prog.c.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/138 compute int/prog.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -#include "@CONFIG@" -#include -#include -#include -#include "foobar.h" - -int main(void) { - if(INTSIZE != sizeof(int)) { - fprintf(stderr, "Mismatch: computed int size %d, actual size %d.\n", INTSIZE, (int)sizeof(int)); - return 1; - } - if(FOOBAR_IN_CONFIG_H != FOOBAR_IN_FOOBAR_H) { - fprintf(stderr, "Mismatch: computed int %d, should be %d.\n", FOOBAR_IN_CONFIG_H, FOOBAR_IN_FOOBAR_H); - return 1; - } - if(MAXINT != INT_MAX) { - fprintf(stderr, "Mismatch: computed max int %d, should be %d.\n", MAXINT, INT_MAX); - return 1; - } - if(MININT != INT_MIN) { - fprintf(stderr, "Mismatch: computed min int %d, should be %d.\n", MININT, INT_MIN); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/meson.build" 2020-01-07 21:08:26.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -project('custom target object output', 'c') - -comp = find_program('obj_generator.py') - -if host_machine.system() == 'windows' - outputname = '@BASENAME@.obj' -else - outputname = '@BASENAME@.o' -endif - -cc = meson.get_compiler('c').cmd_array().get(-1) - -subdir('objdir') -subdir('progdir') - -test('objgen', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/objdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/objdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/objdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/objdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -# Generate an object file manually. -object = custom_target('object', - input : 'source.c', - output : outputname, - command : [comp, cc, '@INPUT@', '@OUTPUT@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/objdir/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/objdir/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/objdir/source.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/objdir/source.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func1_in_obj(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/obj_generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/obj_generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/obj_generator.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/obj_generator.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 - -# Mimic a binary that generates an object file (e.g. windres). - -import sys, subprocess - -if __name__ == '__main__': - if len(sys.argv) != 4: - print(sys.argv[0], 'compiler input_file output_file') - sys.exit(1) - compiler = sys.argv[1] - ifile = sys.argv[2] - ofile = sys.argv[3] - if compiler.endswith('cl'): - cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] - else: - cmd = [compiler, '-c', ifile, '-o', ofile] - sys.exit(subprocess.call(cmd)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/progdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/progdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/progdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/progdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -e = executable('prog', 'prog.c', object) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/progdir/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/progdir/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 custom target object output/progdir/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 custom target object output/progdir/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int func1_in_obj(void); - -int main(void) { - return func1_in_obj(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 mesonintrospect from scripts/check_env.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 mesonintrospect from scripts/check_env.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 mesonintrospect from scripts/check_env.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 mesonintrospect from scripts/check_env.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import os +import sys +import shlex + +do_print = False + +if len(sys.argv) > 1: + do_print = bool(sys.argv[1]) + +if 'MESONINTROSPECT' not in os.environ: + raise RuntimeError('MESONINTROSPECT not found') + +mesonintrospect = os.environ['MESONINTROSPECT'] + +introspect_arr = shlex.split(mesonintrospect) + +# print(mesonintrospect) +# print(introspect_arr) + +some_executable = introspect_arr[0] + +if not os.path.isfile(some_executable): + raise RuntimeError(f'{mesonintrospect!r} does not exist') + +if do_print: + print(some_executable, end='') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 mesonintrospect from scripts/check_introspection.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 mesonintrospect from scripts/check_introspection.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 mesonintrospect from scripts/check_introspection.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 mesonintrospect from scripts/check_introspection.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +import os +import shlex +import subprocess + + +if 'MESONINTROSPECT' not in os.environ: + raise RuntimeError('MESONINTROSPECT not found') +if 'MESON_BUILD_ROOT' not in os.environ: + raise RuntimeError('MESON_BUILD_ROOT not found') + +mesonintrospect = os.environ['MESONINTROSPECT'] +introspect_arr = shlex.split(mesonintrospect) + +buildroot = os.environ['MESON_BUILD_ROOT'] + +subprocess.check_output([*introspect_arr, '--all', buildroot]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 mesonintrospect from scripts/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 mesonintrospect from scripts/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/139 mesonintrospect from scripts/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/139 mesonintrospect from scripts/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,14 @@ +project('mesonintrospect from scripts', 'c') + +python = import('python3').find_python() + +ret = run_command(python, ['check_env.py', '1'], check: false) +if ret.returncode() == 0 + find_program(ret.stdout()) +else + message(ret.stdout()) + message(ret.stderr()) +endif + +meson.add_postconf_script('check_introspection.py') +meson.add_install_script('check_env.py') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/c/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/c/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/c/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/c/prog.c" 2021-11-02 19:58:07.000000000 +0000 @@ -7,4 +7,3 @@ int main(void) { return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/generated/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/generated/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/generated/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/generated/prog.c" 2021-11-02 19:58:07.000000000 +0000 @@ -3,4 +3,3 @@ int main(void) { return FOO + BAR; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/meson.build" 2020-01-07 21:06:23.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/meson.build" 2021-10-23 16:47:57.000000000 +0000 @@ -13,6 +13,7 @@ subdir('generated') subdir('userDefined') subdir('withIncludeDirectories') +subdir('withIncludeFile') if meson.backend() == 'xcode' warning('Xcode backend only supports one precompiled header per target. Skipping "mixed" which has various precompiled headers.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/withIncludeDirectories/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/withIncludeDirectories/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/withIncludeDirectories/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/withIncludeDirectories/prog.c" 2021-11-02 19:58:07.000000000 +0000 @@ -7,4 +7,3 @@ int main(void) { return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/withIncludeFile/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/withIncludeFile/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/withIncludeFile/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/withIncludeFile/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,18 @@ +cc = meson.get_compiler('c') +cc_id = cc.get_id() + +if cc_id == 'lcc' + error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.') +endif + +if cc.get_argument_syntax() == 'gcc' + c_args = ['-include', 'locale.h'] +elif cc.get_argument_syntax() == 'msvc' + c_args = ['/FI' + 'locale.h'] +else + subdir_done() +endif + +exe = executable('prog', 'prog.c', +c_args: c_args, +c_pch : 'pch/prog.h') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/withIncludeFile/pch/prog.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/withIncludeFile/pch/prog.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/withIncludeFile/pch/prog.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/withIncludeFile/pch/prog.h" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef PROG_H +// Header guards for PCH confuse msvc in some situations. +// Using them here makes sure we handle this correctly. +#define PROG_H +#include +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/withIncludeFile/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/withIncludeFile/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/13 pch/withIncludeFile/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/13 pch/withIncludeFile/prog.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,10 @@ +// No includes here, they need to come from the PCH or explicit inclusion + +void func(void) { + fprintf(stdout, "This is a function that fails if stdio is not #included.\n"); + setlocale(LC_ALL, ""); /* This will fail if locale.h is not included */ +} + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/140 custom target multiple outputs/generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/140 custom target multiple outputs/generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/140 custom target multiple outputs/generator.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/140 custom target multiple outputs/generator.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +import sys, os + +if len(sys.argv) != 3: + print(sys.argv[0], '', '') + +name = sys.argv[1] +odir = sys.argv[2] + +with open(os.path.join(odir, name + '.h'), 'w') as f: + f.write('int func();\n') +with open(os.path.join(odir, name + '.sh'), 'w') as f: + f.write('#!/bin/bash') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/140 custom target multiple outputs/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/140 custom target multiple outputs/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/140 custom target multiple outputs/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/140 custom target multiple outputs/meson.build" 2021-10-23 16:49:27.000000000 +0000 @@ -0,0 +1,44 @@ +project('multiple outputs install', 'c') + +gen = find_program('generator.py') + +custom_target('different-install-dirs', + output : ['diff.h', 'diff.sh'], + command : [gen, 'diff', '@OUTDIR@'], + install : true, + install_dir : [join_paths(get_option('prefix'), get_option('includedir')), + join_paths(get_option('prefix'), get_option('bindir'))]) + +custom_target('same-install-dir', + output : ['same.h', 'same.sh'], + command : [gen, 'same', '@OUTDIR@'], + install : true, + install_dir : '/opt') + +custom_target('only-install-first', + output : ['first.h', 'first.sh'], + command : [gen, 'first', '@OUTDIR@'], + install : true, + install_dir : [join_paths(get_option('prefix'), get_option('includedir')), false]) + +targets = custom_target('only-install-second', + output : ['second.h', 'second.sh'], + command : [gen, 'second', '@OUTDIR@'], + install : true, + install_dir : [false, join_paths(get_option('prefix'), get_option('bindir'))]) + +paths = [] +foreach i : targets.to_list() + paths += i.full_path() +endforeach + +# The Xcode backend has a different output naming scheme. +if meson.backend() == 'xcode' + assert(paths == [meson.project_build_root() / get_option('buildtype') / 'second.h', + meson.project_build_root() / get_option('buildtype') / 'second.sh']) + +# Skip on Windows because paths are not identical, '/' VS '\'. +elif host_machine.system() != 'windows' + assert(paths == [meson.current_build_dir() / 'second.h', + meson.current_build_dir() / 'second.sh']) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/140 custom target multiple outputs/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/140 custom target multiple outputs/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/140 custom target multiple outputs/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/140 custom target multiple outputs/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "installed": [ + {"type": "file", "file": "usr/include/diff.h"}, + {"type": "file", "file": "usr/include/first.h"}, + {"type": "file", "file": "usr/bin/diff.sh"}, + {"type": "file", "file": "usr/bin/second.sh"}, + {"type": "file", "file": "opt/same.h"}, + {"type": "file", "file": "opt/same.sh"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/140 empty build file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/140 empty build file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/140 empty build file/meson.build" 2020-01-07 21:08:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/140 empty build file/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('subdir with empty meson.build test', 'c') -subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/arg-char-test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/arg-char-test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/arg-char-test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/arg-char-test.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include + +int main(int argc, char **argv) { + char c = CHAR; + assert(argc == 2); + if (c != argv[1][0]) + fprintf(stderr, "Expected %x, got %x\n", (unsigned int) c, (unsigned int) argv[1][0]); + assert(c == argv[1][0]); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/arg-string-test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/arg-string-test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/arg-string-test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/arg-string-test.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +#include +#include +#include + +int main(int argc, char **argv) { + const char *s = CHAR; + assert(argc == 2); + assert(strlen(s) == 1); + if (s[0] != argv[1][0]) + fprintf(stderr, "Expected %x, got %x\n", (unsigned int) s[0], (unsigned int) argv[1][0]); + assert(s[0] == argv[1][0]); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/arg-unquoted-test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/arg-unquoted-test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/arg-unquoted-test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/arg-unquoted-test.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +#include +#include +#include + +#define Q(x) #x +#define QUOTE(x) Q(x) + +int main(int argc, char **argv) { + const char *s = QUOTE(CHAR); + assert(argc == 2); + assert(strlen(s) == 1); + if (s[0] != argv[1][0]) + fprintf(stderr, "Expected %x, got %x\n", (unsigned int) s[0], (unsigned int) argv[1][0]); + assert(s[0] == argv[1][0]); + // There is no way to convert a macro argument into a character constant. + // Otherwise we'd test that as well +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/check_quoting.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/check_quoting.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/check_quoting.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/check_quoting.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import sys + +expected = { + 'newline': '\n', + 'dollar': '$', + 'colon': ':', + 'space': ' ', + 'multi1': ' ::$$ ::$$', + 'multi2': ' ::$$\n\n \n\n::$$', +} + +output = None + +for arg in sys.argv[1:]: + try: + name, value = arg.split('=', 1) + except ValueError: + output = arg + continue + + if expected[name] != value: + raise RuntimeError('{!r} is {!r} but should be {!r}'.format(name, value, expected[name])) + +if output is not None: + with open(output, 'w') as f: + f.write('Success!') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/.editorconfig" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/.editorconfig" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/.editorconfig" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/.editorconfig" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,2 @@ +[meson.build] +trim_trailing_whitespace = false diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/meson.build" 2021-10-23 16:49:30.000000000 +0000 @@ -0,0 +1,75 @@ +project('ninja special characters' ,'c') + +python = import('python3').find_python() + +# Without newlines, this should appear directly in build.ninja. +gen = custom_target('gen', + command : [ + python, + files('check_quoting.py'), + 'dollar=$', + 'colon=:', + 'space= ', + '''multi1= ::$$ ::$$''', + '@OUTPUT@'], + output : 'result', + install : true, + install_dir : get_option('datadir')) + +# With newlines, this should go through the exe wrapper. +gen2 = custom_target('gen2', + command : [ + python, + files('check_quoting.py'), + '''newline= +''', + 'dollar=$', + 'colon=:', + 'space= ', + '''multi2= ::$$ + + + +::$$''', + '@OUTPUT@'], + output : 'result2', + install : true, + install_dir : get_option('datadir')) + +# Test that we can pass these special characters in compiler arguments +# +# (this part of the test is crafted so we don't try to use these special +# characters in filenames or target names) +# +# TODO: similar tests needed for languages other than C +# TODO: add similar test for quote, doublequote, and hash, carefully +# Re hash, see +# https://docs.microsoft.com/en-us/cpp/build/reference/d-preprocessor-definitions + +special = [ + ['amp', '&'], + ['at', '@'], + ['backslash', '\\'], + ['dollar', '$'], + ['gt', '>'], + ['lt', '<'], + ['slash', '/'], +] + +cc = meson.get_compiler('c') + +foreach s : special + args = '-DCHAR="@0@"'.format(s[1]) + e = executable('arg-string-' + s[0], 'arg-string-test.c', c_args: args) + test('arg-string-' + s[0], e, args: s[1]) + + args = '-DCHAR=@0@'.format(s[1]) + e = executable('arg-unquoted-' + s[0], 'arg-unquoted-test.c', c_args: args) + test('arg-unquoted-' + s[0], e, args: s[1]) +endforeach + +foreach s : special + args = '-DCHAR=\'@0@\''.format(s[1]) + e = executable('arg-char-' + s[0], 'arg-char-test.c', c_args: args) + test('arg-char-' + s[0], e, args: s[1]) +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 special characters/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 special characters/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "file", "file": "usr/share/result"}, + {"type": "file", "file": "usr/share/result2"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/exe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/exe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/exe/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/exe/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -exe = executable('prog', '../prog.c', link_with : sh_func2_linked_func1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/exe2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/exe2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/exe2/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/exe2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -exe2 = executable('prog2', '../prog.c', link_with : sh_only_link_whole) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/exe3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/exe3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/exe3/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/exe3/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -exe3 = executable('prog3', '../prog.c', link_with : sh_func2_dep_func1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/exe4/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/exe4/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/exe4/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/exe4/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -exe4 = executable('prog4', '../prog.c', link_with : sh_func2_transdep_func1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/func1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/func1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/func1.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/func1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#define BUILDING_DLL - -#include - -int func1(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/func2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/func2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/func2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/func2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#define BUILDING_DLL - -#include - -int func2(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/meson.build" 2020-01-07 21:08:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -project('whole archive', 'c') - -add_project_arguments('-I' + meson.source_root(), language : 'c') - -cc = meson.get_compiler('c') - -if cc.get_id() == 'msvc' - if cc.version().version_compare('<19') - error('MESON_SKIP_TEST link_whole only works on VS2015 or newer.') - endif -endif - -# Test 1: link_whole keeps all symbols -# Make static func1 -subdir('st_func1') -# Make shared func2 linking whole func1 archive -subdir('sh_func2_linked_func1') -# Link exe with shared library only -subdir('exe') -# Test that both func1 and func2 are accessible from shared library -test('prog', exe) - -# Test 2: link_whole can be used instead of source list, see #2180 -# Make static func2 -subdir('st_func2') -# Link both func1 and func2 into same shared library -# which does not have any sources other than 2 static libraries -subdir('sh_only_link_whole') -# Link exe2 with shared library only -subdir('exe2') -# Test that both func1 and func2 are accessible from shared library -test('prog2', exe2) - -# Test 3: link_whole can be used in declare_dependency() -func1_dep = declare_dependency(link_whole : [st_func1]) -# Use dependency to link func1 into shared library -subdir('sh_func2_dep_func1') -# Link exe3 with shared library -subdir('exe3') -# Test that both func1 and func2 are accessible from shared library -test('prog3', exe3) - -# Test 4: link_whole can be used in transitive declare_dependency() -func1_trans_dep = declare_dependency(dependencies : func1_dep) -# Use transitive dependency to link func1 into shared library -subdir('sh_func2_transdep_func1') -# Link exe4 with shared library -subdir('exe4') -# Test that both func1 and func2 are accessible from shared library -test('prog4', exe4) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/mylib.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/mylib.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/mylib.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/mylib.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#pragma once - -/* Both funcs here for simplicity. */ - -#if defined _WIN32 || defined __CYGWIN__ -#if defined BUILDING_DLL - #define DLL_PUBLIC __declspec(dllexport) -#else - #define DLL_PUBLIC __declspec(dllimport) -#endif -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC func1(void); -int DLL_PUBLIC func2(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -int main(void) { - return func1() - func2(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/sh_func2_dep_func1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/sh_func2_dep_func1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/sh_func2_dep_func1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/sh_func2_dep_func1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -# Same as sh_func2_linked_func1, # func2.c does not depend on func1(), -# so without link_whole compiler would throw func1() away. -# This is the same version of the test with a dependency object instead. -sh_func2_dep_func1 = shared_library('sh_func2_dep_func1', '../func2.c', dependencies : func1_dep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/sh_func2_linked_func1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/sh_func2_linked_func1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/sh_func2_linked_func1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/sh_func2_linked_func1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -# Nothing in func2.c uses func1, so the linker would throw it -# away and thus linking the exe would fail. -sh_func2_linked_func1 = shared_library('sh_func2_linked_func1', '../func2.c', link_whole : st_func1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/sh_func2_transdep_func1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/sh_func2_transdep_func1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/sh_func2_transdep_func1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/sh_func2_transdep_func1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -# Same as sh_func2_dep_func1 but dependency is transitive. -# func2.c does not have any reference to func1() so without link_whole compiler -# should throw func1() out. -sh_func2_transdep_func1 = shared_library( - 'sh_func2_transdep_func1', '../func2.c', - dependencies : func1_trans_dep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/sh_only_link_whole/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/sh_only_link_whole/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/sh_only_link_whole/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/sh_only_link_whole/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -sh_only_link_whole = shared_library('sh_only_link_whole', link_whole : [st_func1, st_func2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/st_func1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/st_func1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/st_func1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/st_func1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -st_func1 = static_library('st_func1', '../func1.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/st_func2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/st_func2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/141 whole archive/st_func2/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/141 whole archive/st_func2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -st_func2 = static_library('st_func2', '../func2.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foobar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foobar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foobar.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foobar.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -/* Copyright © 2017 Dylan Baker - * - * 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. - */ - -#include "foo.h" -#include "foo.hpp" -#include "foobar.h" - -int get_number_index (void) { - return 1; -} - -void mynumbers(int nums[]) { - nums[0] = forty_two(); - nums[1] = six_one(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foobar.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foobar.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foobar.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foobar.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -/* Copyright © 2017 Dylan Baker - * - * 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. - */ - -void mynumbers(int nums[]); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foo.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* Copyright © 2017 Dylan Baker - * - * 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. - */ -#include "foo.h" - -int forty_two(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foo.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foo.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foo.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foo.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -/* Copyright © 2017 Dylan Baker - * - * 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. - */ -#include - -const int cnums[] = {0, 61}; - -/* Provided by foobar.c */ -extern "C" int get_number_index (void); - -template -std::vector makeVector(const T (&data)[N]) -{ - return std::vector(data, data+N); -} - -namespace { - std::vector numbers = makeVector(cnums); -} - -extern "C" int six_one(void) { - return numbers[get_number_index ()]; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foo.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foo.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -/* Copyright © 2017 Dylan Baker - * - * 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. - */ - -int forty_two(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foo.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foo.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/foo.hpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/foo.hpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* Copyright © 2017 Dylan Baker - * - * 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. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -int six_one(void); - -#ifdef __cplusplus -} -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/meson.build" 2020-01-07 21:08:33.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -# Copyright © 2017 Dylan Baker -# -# 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. - -project('C and C++ static link test', ['c', 'cpp']) - -# Verify that adding link arguments works. -add_global_link_arguments('', language : 'c') -add_project_link_arguments('', language : 'c') - -libc = static_library('cfoo', ['foo.c', 'foo.h']) - -# Test that linking C libs to external static C++ libs uses the C++ linker -# Since we can't depend on the test system to provide this, we create one -# ourselves at configure time and then 'find' it with cxx.find_library(). -cxx = meson.get_compiler('cpp') - -if cxx.get_argument_syntax() == 'msvc' - if cxx.get_id() == 'msvc' - static_linker = find_program('lib') - elif cxx.get_id() == 'clang-cl' - static_linker = find_program('llvm-lib') - elif cxx.get_id() == 'intel-cl' - static_linker = find_program('xilib') - else - error('unable to determine static linker to use with this compiler') - endif - compile_cmd = ['/c', '@INPUT@', '/Fo@OUTPUT@'] - stlib_cmd = [static_linker, '/OUT:@OUTPUT@', '@INPUT@'] -else - picflag = [] - if not ['darwin', 'windows'].contains(host_machine.system()) - picflag = ['-fPIC'] - endif - compile_cmd = ['-c', picflag, '@INPUT@', '-o', '@OUTPUT@'] - stlib_cmd = ['ar', 'csr', '@OUTPUT@', '@INPUT@'] -endif - -foo_cpp_o = configure_file( - input : 'foo.cpp', - output : 'foo.cpp.o', - command : cxx.cmd_array() + compile_cmd) - -configure_file( - input : foo_cpp_o, - output : 'libstcppext.a', - command : stlib_cmd) - -libstcppext = cxx.find_library('stcppext', dirs : meson.current_build_dir()) -lib_type_name = libstcppext.type_name() -assert(lib_type_name == 'library', 'type name is ' + lib_type_name) - -libfooext = shared_library( - 'fooext', - ['foobar.c', 'foobar.h'], - link_with : libc, - dependencies : libstcppext, -) - -# Test that linking C libs to internal static C++ libs uses the C++ linker -libcpp = static_library('cppfoo', ['foo.cpp', 'foo.hpp']) - -libfoo = shared_library( - 'foo', - ['foobar.c', 'foobar.h'], - link_with : [libc, libcpp], -) - -# Test that link_whole is also honored -# -# VS2010 lacks the /WHOLEARCHIVE option that later versions of MSVC support, so -# don't run this tests on that backend. -if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19')) - libfoowhole = shared_library( - 'foowhole', - ['foobar.c', 'foobar.h'], - link_whole : [libc, libcpp], - ) -endif - -# Test sublinking (linking C and C++, then linking that to C) -libfoo_static = static_library( - 'foo_static', - ['foobar.c', 'foobar.h'], - link_with : [libc, libcpp], -) - -libsub = shared_library( - 'sub', - ['sub.c', 'sub.h'], - link_with : libfoo_static, -) - -if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19')) - libsubwhole = shared_library( - 'subwhole', - ['sub.c', 'sub.h'], - link_whole : libfoo_static, - ) -endif - -# Test that it really is recursive -libsub_static = static_library( - 'sub_static', - ['sub.c', 'sub.h'], - link_with : libfoo_static, -) - -libsubsub = shared_library( - 'subsub', - ['dummy.c'], - link_with : libsub_static, -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/sub.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/sub.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* Copyright © 2017 Dylan Baker - * - * 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. - */ -#include "sub.h" - -float a_half(void) { - return .5; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 C and CPP link/sub.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 C and CPP link/sub.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -/* Copyright © 2017 Dylan Baker - * - * 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. - */ - -float a_half(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 nested links/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 nested links/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 nested links/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 nested links/meson.build" 2021-10-23 16:49:29.000000000 +0000 @@ -0,0 +1,8 @@ +project('test', 'c') + +libxserver_dri3 = [] +libxserver = [ libxserver_dri3 ] + +executable('Xephyr', 'xephyr.c', link_with: [ libxserver ]) + +executable('Zephyr', 'xephyr.c', link_args: [[], []]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 nested links/xephyr.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 nested links/xephyr.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/142 nested links/xephyr.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/142 nested links/xephyr.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 list of file sources/foo" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 list of file sources/foo" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 list of file sources/foo" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 list of file sources/foo" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +some text diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 list of file sources/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 list of file sources/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 list of file sources/gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 list of file sources/gen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +import shutil +import sys + +if __name__ == '__main__': + if len(sys.argv) != 3: + raise Exception('Requires exactly 2 args') + shutil.copy2(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 list of file sources/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 list of file sources/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 list of file sources/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 list of file sources/meson.build" 2021-10-23 16:49:30.000000000 +0000 @@ -0,0 +1,12 @@ +project('test', 'c') + +mod_py = import('python3') +python = mod_py.find_python() + +test_target = custom_target( + 'test_target', + input : [files('gen.py'), files('foo')], + output : 'bar', + command : [python, '@INPUT0@', '@INPUT1@', '@OUTPUT@'], + build_by_default : true, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 mesonintrospect from scripts/check_env.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 mesonintrospect from scripts/check_env.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 mesonintrospect from scripts/check_env.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 mesonintrospect from scripts/check_env.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import shlex - -do_print = False - -if len(sys.argv) > 1: - do_print = bool(sys.argv[1]) - -if 'MESONINTROSPECT' not in os.environ: - raise RuntimeError('MESONINTROSPECT not found') - -mesonintrospect = os.environ['MESONINTROSPECT'] - -introspect_arr = shlex.split(mesonintrospect) - -# print(mesonintrospect) -# print(introspect_arr) - -some_executable = introspect_arr[0] - -if not os.path.isfile(some_executable): - raise RuntimeError('{!r} does not exist'.format(mesonintrospect)) - -if do_print: - print(some_executable, end='') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 mesonintrospect from scripts/check_introspection.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 mesonintrospect from scripts/check_introspection.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 mesonintrospect from scripts/check_introspection.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 mesonintrospect from scripts/check_introspection.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 - -import os -import shlex -import subprocess - - -if 'MESONINTROSPECT' not in os.environ: - raise RuntimeError('MESONINTROSPECT not found') -if 'MESON_BUILD_ROOT' not in os.environ: - raise RuntimeError('MESON_BUILD_ROOT not found') - -mesonintrospect = os.environ['MESONINTROSPECT'] -introspect_arr = shlex.split(mesonintrospect) - -buildroot = os.environ['MESON_BUILD_ROOT'] - -subprocess.check_output([*introspect_arr, '--all', buildroot]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 mesonintrospect from scripts/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 mesonintrospect from scripts/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/143 mesonintrospect from scripts/meson.build" 2020-01-07 21:08:33.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/143 mesonintrospect from scripts/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('mesonintrospect from scripts', 'c') - -python = import('python3').find_python() - -ret = run_command(python, ['check_env.py', '1']) -if ret.returncode() == 0 - find_program(ret.stdout()) -else - message(ret.stdout()) - message(ret.stderr()) -endif - -meson.add_postconf_script('check_introspection.py') -meson.add_install_script('check_env.py') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 custom target multiple outputs/generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 custom target multiple outputs/generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 custom target multiple outputs/generator.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 custom target multiple outputs/generator.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os - -if len(sys.argv) != 3: - print(sys.argv[0], '', '') - -name = sys.argv[1] -odir = sys.argv[2] - -with open(os.path.join(odir, name + '.h'), 'w') as f: - f.write('int func();\n') -with open(os.path.join(odir, name + '.sh'), 'w') as f: - f.write('#!/bin/bash') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 custom target multiple outputs/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 custom target multiple outputs/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 custom target multiple outputs/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 custom target multiple outputs/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -usr/include/diff.h -usr/include/first.h -usr/bin/diff.sh -usr/bin/second.sh -opt/same.h -opt/same.sh diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 custom target multiple outputs/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 custom target multiple outputs/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 custom target multiple outputs/meson.build" 2020-01-07 21:08:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 custom target multiple outputs/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -project('multiple outputs install', 'c') - -gen = find_program('generator.py') - -custom_target('different-install-dirs', - output : ['diff.h', 'diff.sh'], - command : [gen, 'diff', '@OUTDIR@'], - install : true, - install_dir : [join_paths(get_option('prefix'), get_option('includedir')), - join_paths(get_option('prefix'), get_option('bindir'))]) - -custom_target('same-install-dir', - output : ['same.h', 'same.sh'], - command : [gen, 'same', '@OUTDIR@'], - install : true, - install_dir : '/opt') - -custom_target('only-install-first', - output : ['first.h', 'first.sh'], - command : [gen, 'first', '@OUTDIR@'], - install : true, - install_dir : [join_paths(get_option('prefix'), get_option('includedir')), false]) - -custom_target('only-install-second', - output : ['second.h', 'second.sh'], - command : [gen, 'second', '@OUTDIR@'], - install : true, - install_dir : [false, join_paths(get_option('prefix'), get_option('bindir'))]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 link depends custom target/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 link depends custom target/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 link depends custom target/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 link depends custom target/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#include + +int main(void) { + const char *fn = DEPFILE; + FILE *f = fopen(fn, "r"); + if (!f) { + printf("could not open %s", fn); + return 1; + } + else { + printf("successfully opened %s", fn); + } + + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 link depends custom target/make_file.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 link depends custom target/make_file.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 link depends custom target/make_file.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 link depends custom target/make_file.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 +import sys + +with open(sys.argv[1], 'w') as f: + print('# this file does nothing', file=f) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 link depends custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 link depends custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/144 link depends custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/144 link depends custom target/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,14 @@ +project('link_depends_custom_target', 'c') + +cmd = find_program('make_file.py') + +dep_file = custom_target('gen_dep', + command: [cmd, '@OUTPUT@'], + output: 'dep_file') + +exe = executable('foo', 'foo.c', + link_depends: dep_file, + c_args: ['-DDEPFILE="' + dep_file.full_path()+ '"']) + +# check that dep_file exists, which means that link_depends target ran +test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/3rdorderdeps/lib.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/3rdorderdeps/lib.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/3rdorderdeps/lib.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/3rdorderdeps/lib.c.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_@DEPENDENCY@dep_value (void); + +SYMBOL_EXPORT +int get_@LIBTYPE@@DEPENDENCY@dep_value (void) { + return get_@DEPENDENCY@dep_value (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/3rdorderdeps/main.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/3rdorderdeps/main.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/3rdorderdeps/main.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/3rdorderdeps/main.c.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include + +#include "../lib.h" + +SYMBOL_IMPORT int get_@LIBTYPE@@DEPENDENCY@dep_value (void); + +int main(void) { + int val; + + val = get_@LIBTYPE@@DEPENDENCY@dep_value (); + if (val != @VALUE@) { + printf("@LIBTYPE@@DEPENDENCY@ was %i instead of @VALUE@\n", val); + return -1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/3rdorderdeps/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/3rdorderdeps/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/3rdorderdeps/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/3rdorderdeps/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,49 @@ +dep3_libs = [] + +# Permutate all combinations of shared and static libraries up to three levels +# executable -> shared -> static -> shared (etc) +foreach dep2 : ['sh', 'st'] + foreach dep1 : ['sh', 'st'] + foreach libtype : ['sh', 'st'] + name = libtype + dep1 + dep2 + if dep2 == 'sh' + libret = 1 + elif dep2 == 'st' + libret = 2 + else + error('Unknown dep2 "@0@"'.format(dep2)) + endif + + if libtype == 'sh' + target = 'shared_library' + build_args = [] + elif libtype == 'st' + target = 'static_library' + build_args = ['-DMESON_STATIC_BUILD'] + else + error('Unknown libtype "@0@"'.format(libtype)) + endif + + cdata = configuration_data() + cdata.set('DEPENDENCY', dep1 + dep2) + cdata.set('LIBTYPE', libtype) + cdata.set('VALUE', libret) + + lib_c = configure_file(input : 'lib.c.in', + output : name + '-lib.c', + configuration : cdata) + dep = get_variable(dep1 + dep2 + 'dep') + dep3_lib = build_target(name, lib_c, link_with : dep, + target_type : target, + c_args : build_args) + dep3_libs += [dep3_lib] + + main_c = configure_file(input : 'main.c.in', + output : name + '-main.c', + configuration : cdata) + dep3_bin = executable(name + '_test', main_c, link_with : dep3_lib, + c_args : build_args) + test(name + 'test', dep3_bin) + endforeach + endforeach +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/lib1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/lib1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/lib1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/lib1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int get_st2_prop (void); +int get_st3_prop (void); + +int get_st1_value (void) { + return get_st2_prop () + get_st3_prop (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/lib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/lib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/lib2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/lib2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int get_st1_prop (void); +int get_st3_prop (void); + +int get_st2_value (void) { + return get_st1_prop () + get_st3_prop (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/lib3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/lib3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/lib3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/lib3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int get_st1_prop (void); +int get_st2_prop (void); + +int get_st3_value (void) { + return get_st1_prop () + get_st2_prop (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,28 @@ +#include + +#include "../lib.h" + +int get_st1_value (void); +int get_st2_value (void); +int get_st3_value (void); + +int main(void) { + int val; + + val = get_st1_value (); + if (val != 5) { + printf("st1 value was %i instead of 5\n", val); + return -1; + } + val = get_st2_value (); + if (val != 4) { + printf("st2 value was %i instead of 4\n", val); + return -2; + } + val = get_st3_value (); + if (val != 3) { + printf("st3 value was %i instead of 3\n", val); + return -3; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +st1 = static_library('st1', 'lib1.c', 'prop1.c') +st2 = static_library('st2', 'lib2.c', 'prop2.c') +st3 = static_library('st3', 'lib3.c', 'prop3.c') + +test('circular', executable('circular', 'main.c', link_with : [st1, st2, st3])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/prop1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/prop1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/prop1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/prop1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int get_st1_prop (void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/prop2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/prop2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/prop2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/prop2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int get_st2_prop (void) { + return 2; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/prop3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/prop3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/circular/prop3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/circular/prop3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int get_st3_prop (void) { + return 3; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/libsto.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/libsto.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/libsto.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/libsto.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_builto_value (void); + +SYMBOL_EXPORT +int get_stodep_value (void) { + return get_builto_value (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +# Test https://github.com/mesonbuild/meson/issues/2096 +# Note that removing 'shnodep' from link_with: makes the error go away because +# then it is added after the static library is added to the link command. +test('shared-static', executable('shstexe', 'shstmain.c', link_with : [shnodep, stshdep])) + +# Static library that needs a symbol defined in an object file. This already +# works, but good to add a test case early. +stodep = static_library('stodep', 'libsto.c') +test('stodep', executable('stodep', 'stomain.c', 'stobuilt.c', link_with : stodep)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/shstmain.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/shstmain.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/shstmain.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/shstmain.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include + +#include "../lib.h" + +int get_stshdep_value (void); + +int main(void) { + int val; + + val = get_stshdep_value (); + if (val != 1) { + printf("st1 value was %i instead of 1\n", val); + return -1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/stobuilt.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/stobuilt.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/stobuilt.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/stobuilt.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include "../lib.h" + + +SYMBOL_EXPORT +int get_builto_value (void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/stomain.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/stomain.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/edge-cases/stomain.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/edge-cases/stomain.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include + +#include "../lib.h" + +int get_stodep_value (void); + +int main(void) { + int val; + + val = get_stodep_value (); + if (val != 1) { + printf("st1 value was %i instead of 1\n", val); + return -1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/lib.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/lib.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/lib.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/lib.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +#if defined _WIN32 + #ifdef MESON_STATIC_BUILD + #define SYMBOL_EXPORT + #define SYMBOL_IMPORT + #else + #define SYMBOL_IMPORT __declspec(dllimport) + #define SYMBOL_EXPORT __declspec(dllexport) + #endif +#else + #define SYMBOL_IMPORT + #if defined __GNUC__ + #define SYMBOL_EXPORT __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define SYMBOL_EXPORT + #endif +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,46 @@ +#include + +#include "lib.h" + +int get_stnodep_value (void); +int get_stshdep_value (void); +int get_ststdep_value (void); +SYMBOL_IMPORT int get_shnodep_value (void); +SYMBOL_IMPORT int get_shshdep_value (void); +SYMBOL_IMPORT int get_shstdep_value (void); + +int main(void) { + int val; + + val = get_shnodep_value (); + if (val != 1) { + printf("shnodep was %i instead of 1\n", val); + return -1; + } + val = get_stnodep_value (); + if (val != 2) { + printf("stnodep was %i instead of 2\n", val); + return -2; + } + val = get_shshdep_value (); + if (val != 1) { + printf("shshdep was %i instead of 1\n", val); + return -3; + } + val = get_shstdep_value (); + if (val != 2) { + printf("shstdep was %i instead of 2\n", val); + return -4; + } + val = get_stshdep_value (); + if (val != 1) { + printf("shstdep was %i instead of 1\n", val); + return -5; + } + val = get_ststdep_value (); + if (val != 2) { + printf("ststdep was %i instead of 2\n", val); + return -6; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/meson.build" 2021-10-23 16:49:38.000000000 +0000 @@ -0,0 +1,29 @@ +project('recursive dependencies', 'c') + +# Test that you can link a shared executable to: +# - A shared library with no other deps +subdir('shnodep') +# - A static library with no other deps +subdir('stnodep') +# - A shared library with a shared library dep +subdir('shshdep') +# - A shared library with a static library dep +subdir('shstdep') +# - A static library with a shared library dep +subdir('stshdep') +# - A static library with a static library dep +subdir('ststdep') + +test('alldeps', + executable('alldeps', 'main.c', + link_with : [shshdep, shstdep, ststdep, stshdep])) + +# More combinations of static and shared libraries +subdir('3rdorderdeps') + +# Circular dependencies between static libraries +# This requires the use of --start/end-group with GNU ld +subdir('circular') + +# Various edge cases that have been reported +subdir('edge-cases') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shnodep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shnodep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shnodep/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shnodep/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include "../lib.h" + +SYMBOL_EXPORT +int get_shnodep_value (void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shnodep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shnodep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shnodep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shnodep/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +shnodep = shared_library('shnodep', 'lib.c', version: '0.0.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shshdep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shshdep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shshdep/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shshdep/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_shnodep_value (void); + +SYMBOL_EXPORT +int get_shshdep_value (void) { + return get_shnodep_value (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shshdep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shshdep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shshdep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shshdep/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +shshdep = shared_library('shshdep', 'lib.c', link_with : shnodep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shstdep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shstdep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shstdep/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shstdep/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_stnodep_value (void); + +SYMBOL_EXPORT +int get_shstdep_value (void) { + return get_stnodep_value (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shstdep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shstdep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/shstdep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/shstdep/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +shstdep = shared_library('shstdep', 'lib.c', link_with : stnodep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/stnodep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/stnodep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/stnodep/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/stnodep/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include "../lib.h" + +SYMBOL_EXPORT +int get_stnodep_value (void) { + return 2; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/stnodep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/stnodep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/stnodep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/stnodep/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +stnodep = static_library('stnodep', 'lib.c', + c_args : '-DMESON_STATIC_BUILD') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/stshdep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/stshdep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/stshdep/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/stshdep/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_shnodep_value (void); + +SYMBOL_EXPORT +int get_stshdep_value (void) { + return get_shnodep_value (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/stshdep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/stshdep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/stshdep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/stshdep/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +stshdep = static_library('stshdep', 'lib.c', link_with : shnodep, + c_args : '-DMESON_STATIC_BUILD') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/ststdep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/ststdep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/ststdep/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/ststdep/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_stnodep_value (void); + +SYMBOL_EXPORT +int get_ststdep_value (void) { + return get_stnodep_value (); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/ststdep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/ststdep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 recursive linking/ststdep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 recursive linking/ststdep/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +ststdep = static_library('ststdep', 'lib.c', link_with : stnodep, + c_args : '-DMESON_STATIC_BUILD') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 special characters/check_quoting.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 special characters/check_quoting.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 special characters/check_quoting.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 special characters/check_quoting.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -expected = { - 'newline': '\n', - 'dollar': '$', - 'colon': ':', - 'space': ' ', - 'multi1': ' ::$$ ::$$', - 'multi2': ' ::$$\n\n \n\n::$$', -} - -output = None - -for arg in sys.argv[1:]: - try: - name, value = arg.split('=', 1) - except ValueError: - output = arg - continue - - if expected[name] != value: - raise RuntimeError('{!r} is {!r} but should be {!r}'.format(name, value, expected[name])) - -if output is not None: - with open(output, 'w') as f: - f.write('Success!') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 special characters/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 special characters/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 special characters/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 special characters/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/share/result -usr/share/result2 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 special characters/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 special characters/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/145 special characters/meson.build" 2020-01-07 21:08:36.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/145 special characters/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -project('ninja special characters' ,'c') - -python = import('python3').find_python() - -# Without newlines, this should appear directly in build.ninja. -gen = custom_target('gen', - command : [ - python, - files('check_quoting.py'), - 'dollar=$', - 'colon=:', - 'space= ', - '''multi1= ::$$ ::$$''', - '@OUTPUT@'], - output : 'result', - install : true, - install_dir : get_option('datadir')) - -# With newlines, this should go through the exe wrapper. -gen2 = custom_target('gen2', - command : [ - python, - files('check_quoting.py'), - '''newline= -''', - 'dollar=$', - 'colon=:', - 'space= ', - '''multi2= ::$$ - - - -::$$''', - '@OUTPUT@'], - output : 'result2', - install : true, - install_dir : get_option('datadir')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 library at root/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 library at root/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 library at root/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 library at root/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#if defined _WIN32 || defined __CYGWIN__ +__declspec(dllexport) +#endif +int fn(void) { + return -1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 library at root/main/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 library at root/main/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 library at root/main/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 library at root/main/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +extern int fn(void); + +int main(void) { + return 1 + fn(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 library at root/main/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 library at root/main/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 library at root/main/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 library at root/main/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +exe = executable('main', 'main.c', link_with : lib) +test('stuff works', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 library at root/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 library at root/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 library at root/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 library at root/meson.build" 2021-10-23 16:49:35.000000000 +0000 @@ -0,0 +1,3 @@ +project('lib@root', 'c') +lib = library('lib', 'lib.c') +subdir('main') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 nested links/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 nested links/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 nested links/meson.build" 2020-01-07 21:08:37.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 nested links/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('test', 'c') - -libxserver_dri3 = [] -libxserver = [ libxserver_dri3 ] - -executable('Xephyr', 'xephyr.c', link_with: [ libxserver ]) - -executable('Zephyr', 'xephyr.c', link_args: [[], []]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 nested links/xephyr.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 nested links/xephyr.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/146 nested links/xephyr.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/146 nested links/xephyr.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 list of file sources/foo" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 list of file sources/foo" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 list of file sources/foo" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 list of file sources/foo" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -some text diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 list of file sources/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 list of file sources/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 list of file sources/gen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 list of file sources/gen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -import shutil -import sys - -if __name__ == '__main__': - if len(sys.argv) != 3: - raise Exception('Requires exactly 2 args') - shutil.copy2(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 list of file sources/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 list of file sources/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 list of file sources/meson.build" 2020-01-07 21:08:37.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 list of file sources/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -project('test', 'c') - -mod_py = import('python3') -python = mod_py.find_python() - -test_target = custom_target( - 'test_target', - input : [files('gen.py'), files('foo')], - output : 'bar', - command : [python, '@INPUT0@', '@INPUT1@', '@OUTPUT@'], - build_by_default : true, -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/fallback.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/fallback.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/fallback.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/fallback.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +void increment_fallback(float arr[4]) { + int i; + for(i=0; i<4; i++) { + arr[i]++; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/include/simdheader.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/include/simdheader.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/include/simdheader.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/include/simdheader.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +#define I_CAN_HAZ_SIMD diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,43 @@ +project('simd', 'c') + +simd = import('unstable-simd') + +cc = meson.get_compiler('c') + +cdata = configuration_data() + +if not meson.is_cross_build() and host_machine.cpu_family() == 'arm' and cc.get_id() == 'clang' + message('Adding -march=armv7 because assuming that this build happens on Raspbian.') + message('Its Clang seems to be misconfigured and does not support NEON by default.') + add_project_arguments('-march=armv7', language : 'c') +endif + +if cc.get_id() == 'msvc' and cc.version().version_compare('<17') + error('MESON_SKIP_TEST VS2010 produces broken binaries on x86.') +endif + +# FIXME add [a, b] = function() +rval = simd.check('mysimds', + mmx : 'simd_mmx.c', + sse : 'simd_sse.c', + sse2 : 'simd_sse2.c', + sse3 : 'simd_sse3.c', + ssse3 : 'simd_ssse3.c', + sse41 : 'simd_sse41.c', + sse42 : 'simd_sse42.c', + avx : 'simd_avx.c', + avx2 : 'simd_avx2.c', + neon : 'simd_neon.c', + compiler : cc, + include_directories : include_directories('include')) + +simdlibs = rval[0] +cdata.merge_from(rval[1]) + +configure_file(output : 'simdconfig.h', + configuration : cdata) + +p = executable('simdtest', 'simdchecker.c', 'fallback.c', + link_with : simdlibs) + +test('simdtest', p) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_avx2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_avx2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_avx2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_avx2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,42 @@ +#include +#include +#include + +/* + * FIXME add proper runtime detection for VS. + */ + +#ifdef _MSC_VER +#include +int avx2_available(void) { + return 0; +} +#else +#include +#include + +#if defined(__APPLE__) +int avx2_available(void) { return 0; } +#else +int avx2_available(void) { + return __builtin_cpu_supports("avx2"); +} +#endif +#endif + +void increment_avx2(float arr[4]) { + double darr[4]; + darr[0] = arr[0]; + darr[1] = arr[1]; + darr[2] = arr[2]; + darr[3] = arr[3]; + __m256d val = _mm256_loadu_pd(darr); + __m256d one = _mm256_set1_pd(1.0); + __m256d result = _mm256_add_pd(val, one); + _mm256_storeu_pd(darr, result); + one = _mm256_permute4x64_pd(one, 66); /* A no-op, just here to use AVX2. */ + arr[0] = (float)darr[0]; + arr[1] = (float)darr[1]; + arr[2] = (float)darr[2]; + arr[3] = (float)darr[3]; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_avx.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_avx.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_avx.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_avx.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,49 @@ +#include + +#ifndef I_CAN_HAZ_SIMD +#error The correct internal header was not used +#endif + +#include +#include +#include + +#ifdef _MSC_VER +#include +int avx_available(void) { + return 1; +} +#else +#include +#include + +#ifdef __APPLE__ +/* + * Apple ships a broken __builtin_cpu_supports and + * some machines in the CI farm seem to be too + * old to have AVX so just always return 0 here. + */ +int avx_available(void) { return 0; } +#else + +int avx_available(void) { + return __builtin_cpu_supports("avx"); +} +#endif +#endif + +void increment_avx(float arr[4]) { + double darr[4]; + darr[0] = arr[0]; + darr[1] = arr[1]; + darr[2] = arr[2]; + darr[3] = arr[3]; + __m256d val = _mm256_loadu_pd(darr); + __m256d one = _mm256_set1_pd(1.0); + __m256d result = _mm256_add_pd(val, one); + _mm256_storeu_pd(darr, result); + arr[0] = (float)darr[0]; + arr[1] = (float)darr[1]; + arr[2] = (float)darr[2]; + arr[3] = (float)darr[3]; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simdchecker.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simdchecker.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simdchecker.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simdchecker.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,143 @@ +#include +#include +#include + +typedef void (*simd_func)(float*); + +int check_simd_implementation(float *four, + const float *four_initial, + const char *simd_type, + const float *expected, + simd_func fptr, + const int blocksize) { + int rv = 0; + memcpy(four, four_initial, blocksize*sizeof(float)); + printf("Using %s.\n", simd_type); + fptr(four); + for(int i=0; i + +#ifdef _MSC_VER +#define ALIGN_16 __declspec(align(16)) +#else +#include +#define ALIGN_16 alignas(16) +#endif + + +/* Yes, I do know that arr[4] decays into a pointer + * as a function argument. Don't do this in real code + * but for this test it is ok. + */ + +void increment_fallback(float arr[4]); + +#if HAVE_MMX +int mmx_available(void); +void increment_mmx(float arr[4]); +#endif + +#if HAVE_SSE +int sse_available(void); +void increment_sse(float arr[4]); +#endif + +#if HAVE_SSE2 +int sse2_available(void); +void increment_sse2(float arr[4]); +#endif + +#if HAVE_SSE3 +int sse3_available(void); +void increment_sse3(float arr[4]); +#endif + +#if HAVE_SSSE3 +int ssse3_available(void); +void increment_ssse3(float arr[4]); +#endif + +#if HAVE_SSE41 +int sse41_available(void); +void increment_sse41(float arr[4]); +#endif + +#if HAVE_SSE42 +int sse42_available(void); +void increment_sse42(float arr[4]); +#endif + +#if HAVE_AVX +int avx_available(void); +void increment_avx(float arr[4]); +#endif + +#if HAVE_AVX2 +int avx2_available(void); +void increment_avx2(float arr[4]); +#endif + +#if HAVE_NEON +int neon_available(void); +void increment_neon(float arr[4]); +#endif + +#if HAVE_ALTIVEC +int altivec_available(void); +void increment_altivec(float arr[4]); +#endif + +/* And so on. */ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_mmx.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_mmx.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_mmx.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_mmx.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,67 @@ +#include +#include + +#include + +#ifdef _MSC_VER +#include +int mmx_available(void) { + return 1; +} +/* Contrary to MSDN documentation, MMX intrinsics + * just plain don't work. + */ +void increment_mmx(float arr[4]) { + arr[0]++; + arr[1]++; + arr[2]++; + arr[3]++; +} +#elif defined(__MINGW32__) +int mmx_available(void) { + return 1; +} +/* MinGW does not seem to ship with MMX or it is broken. + */ +void increment_mmx(float arr[4]) { + arr[0]++; + arr[1]++; + arr[2]++; + arr[3]++; +} +#else +#include +#include + +#if defined(__APPLE__) +int mmx_available(void) { return 1; } +#else +int mmx_available(void) { + return __builtin_cpu_supports("mmx"); +} +#endif +void increment_mmx(float arr[4]) { + /* Super ugly but we know that values in arr are always small + * enough to fit in int16; + */ + int i; + __m64 packed = _mm_set_pi16(arr[3], arr[2], arr[1], arr[0]); + __m64 incr = _mm_set1_pi16(1); + __m64 result = _mm_add_pi16(packed, incr); + /* Should be + * int64_t unpacker = _m_to_int64(result); + * but it does not exist on 32 bit platforms for some reason. + */ + int64_t unpacker = (int64_t)(result); + _mm_empty(); + for(i=0; i<4; i++) { + /* This fails on GCC 8 when optimizations are enabled. + * Disable it. Patches welcome to fix this. + arr[i] = (float)(unpacker & ((1<<16)-1)); + unpacker >>= 16; + */ + arr[i] += 1.0f; + } +} + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_neon.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_neon.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_neon.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_neon.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +#include +#include + +#include +#include + +int neon_available(void) { + return 1; /* Incorrect, but I don't know how to check this properly. */ +} + +void increment_neon(float arr[4]) { + float32x2_t a1, a2, one; + a1 = vld1_f32(arr); + a2 = vld1_f32(&arr[2]); + one = vdup_n_f32(1.0); + a1 = vadd_f32(a1, one); + a2 = vadd_f32(a2, one); + vst1_f32(arr, a1); + vst1_f32(&arr[2], a2); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse2.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,36 @@ +#include +#include +#include + +#ifdef _MSC_VER +int sse2_available(void) { + return 1; +} + +#else +#include +#include + +#if defined(__APPLE__) +int sse2_available(void) { return 1; } +#else +int sse2_available(void) { + return __builtin_cpu_supports("sse2"); +} +#endif +#endif + +void increment_sse2(float arr[4]) { + ALIGN_16 double darr[4]; + __m128d val1 = _mm_set_pd(arr[0], arr[1]); + __m128d val2 = _mm_set_pd(arr[2], arr[3]); + __m128d one = _mm_set_pd(1.0, 1.0); + __m128d result = _mm_add_pd(val1, one); + _mm_store_pd(darr, result); + result = _mm_add_pd(val2, one); + _mm_store_pd(&darr[2], result); + arr[0] = (float)darr[1]; + arr[1] = (float)darr[0]; + arr[2] = (float)darr[3]; + arr[3] = (float)darr[2]; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,38 @@ +#include +#include + +#ifdef _MSC_VER +#include +int sse3_available(void) { + return 1; +} +#else + +#include +#include +#include + +#if defined(__APPLE__) +int sse3_available(void) { return 1; } +#else +int sse3_available(void) { + return __builtin_cpu_supports("sse3"); +} +#endif +#endif + +void increment_sse3(float arr[4]) { + ALIGN_16 double darr[4]; + __m128d val1 = _mm_set_pd(arr[0], arr[1]); + __m128d val2 = _mm_set_pd(arr[2], arr[3]); + __m128d one = _mm_set_pd(1.0, 1.0); + __m128d result = _mm_add_pd(val1, one); + _mm_store_pd(darr, result); + result = _mm_add_pd(val2, one); + _mm_store_pd(&darr[2], result); + result = _mm_hadd_pd(val1, val2); /* This does nothing. Only here so we use an SSE3 instruction. */ + arr[0] = (float)darr[1]; + arr[1] = (float)darr[0]; + arr[2] = (float)darr[3]; + arr[3] = (float)darr[2]; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse41.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse41.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse41.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse41.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,40 @@ +#include +#include + +#include + +#ifdef _MSC_VER +#include + +int sse41_available(void) { + return 1; +} + +#else +#include +#include + +#if defined(__APPLE__) +int sse41_available(void) { return 1; } +#else +int sse41_available(void) { + return __builtin_cpu_supports("sse4.1"); +} +#endif +#endif + +void increment_sse41(float arr[4]) { + ALIGN_16 double darr[4]; + __m128d val1 = _mm_set_pd(arr[0], arr[1]); + __m128d val2 = _mm_set_pd(arr[2], arr[3]); + __m128d one = _mm_set_pd(1.0, 1.0); + __m128d result = _mm_add_pd(val1, one); + result = _mm_ceil_pd(result); /* A no-op, only here to use a SSE4.1 intrinsic. */ + _mm_store_pd(darr, result); + result = _mm_add_pd(val2, one); + _mm_store_pd(&darr[2], result); + arr[0] = (float)darr[1]; + arr[1] = (float)darr[0]; + arr[2] = (float)darr[3]; + arr[3] = (float)darr[2]; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse42.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse42.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse42.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse42.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,43 @@ +#include +#include +#include + +#ifdef _MSC_VER +#include + +int sse42_available(void) { + return 1; +} + +#else + +#include +#include + +#ifdef __APPLE__ +int sse42_available(void) { + return 1; +} +#else +int sse42_available(void) { + return __builtin_cpu_supports("sse4.2"); +} +#endif + +#endif + +void increment_sse42(float arr[4]) { + ALIGN_16 double darr[4]; + __m128d val1 = _mm_set_pd(arr[0], arr[1]); + __m128d val2 = _mm_set_pd(arr[2], arr[3]); + __m128d one = _mm_set_pd(1.0, 1.0); + __m128d result = _mm_add_pd(val1, one); + _mm_store_pd(darr, result); + result = _mm_add_pd(val2, one); + _mm_store_pd(&darr[2], result); + _mm_crc32_u32(42, 99); /* A no-op, only here to use an SSE4.2 instruction. */ + arr[0] = (float)darr[1]; + arr[1] = (float)darr[0]; + arr[2] = (float)darr[3]; + arr[3] = (float)darr[2]; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_sse.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_sse.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,29 @@ +#include +#include + +#ifdef _MSC_VER +#include +int sse_available(void) { + return 1; +} +#else + +#include +#include +#include + +#if defined(__APPLE__) +int sse_available(void) { return 1; } +#else +int sse_available(void) { + return __builtin_cpu_supports("sse"); +} +#endif +#endif + +void increment_sse(float arr[4]) { + __m128 val = _mm_load_ps(arr); + __m128 one = _mm_set_ps1(1.0); + __m128 result = _mm_add_ps(val, one); + _mm_storeu_ps(arr, result); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_ssse3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_ssse3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/147 simd/simd_ssse3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/147 simd/simd_ssse3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,48 @@ +#include +#include + +#include +#include + +#ifdef _MSC_VER +#include + +int ssse3_available(void) { + return 1; +} + +#else + +#include +#include + +int ssse3_available(void) { +#ifdef __APPLE__ + return 1; +#elif defined(__clang__) + /* https://github.com/numpy/numpy/issues/8130 */ + return __builtin_cpu_supports("sse4.1"); +#else + return __builtin_cpu_supports("ssse3"); +#endif +} + +#endif + +void increment_ssse3(float arr[4]) { + ALIGN_16 double darr[4]; + __m128d val1 = _mm_set_pd(arr[0], arr[1]); + __m128d val2 = _mm_set_pd(arr[2], arr[3]); + __m128d one = _mm_set_pd(1.0, 1.0); + __m128d result = _mm_add_pd(val1, one); + __m128i tmp1, tmp2; + tmp1 = tmp2 = _mm_set1_epi16(0); + _mm_store_pd(darr, result); + result = _mm_add_pd(val2, one); + _mm_store_pd(&darr[2], result); + tmp1 = _mm_hadd_epi32(tmp1, tmp2); /* This does nothing. Only here so we use an SSSE3 instruction. */ + arr[0] = (float)darr[1]; + arr[1] = (float)darr[0]; + arr[2] = (float)darr[3]; + arr[3] = (float)darr[2]; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 link depends custom target/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 link depends custom target/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 link depends custom target/foo.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 link depends custom target/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#include - -int main(void) { - const char *fn = DEPFILE; - FILE *f = fopen(fn, "r"); - if (!f) { - printf("could not open %s", fn); - return 1; - } - else { - printf("successfully opened %s", fn); - } - - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 link depends custom target/make_file.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 link depends custom target/make_file.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 link depends custom target/make_file.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 link depends custom target/make_file.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#!/usr/bin/env python3 -import sys - -with open(sys.argv[1], 'w') as f: - print('# this file does nothing', file=f) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 link depends custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 link depends custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 link depends custom target/meson.build" 2020-01-07 21:08:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 link depends custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -project('link_depends_custom_target', 'c') - -if meson.backend().startswith('vs') - # FIXME: Broken on the VS backends - error('MESON_SKIP_TEST see https://github.com/mesonbuild/meson/issues/1799') -endif - -cmd = find_program('make_file.py') - -dep_file = custom_target('gen_dep', - command: [cmd, '@OUTPUT@'], - output: 'dep_file') - -exe = executable('foo', 'foo.c', - link_depends: dep_file, - c_args: ['-DDEPFILE="' + dep_file.full_path()+ '"']) - -# check that dep_file exists, which means that link_depends target ran -test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 shared module resolving symbol in executable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 shared module resolving symbol in executable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 shared module resolving symbol in executable/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 shared module resolving symbol in executable/meson.build" 2021-10-23 16:49:35.000000000 +0000 @@ -0,0 +1,20 @@ +project('shared module resolving symbol in executable', 'c') + +# The shared module contains a reference to the symbol 'func_from_executable', +# which is always provided by the executable which loads it. This symbol can be +# resolved at run-time by an ELF loader. But when building PE/COFF objects, all +# symbols must be resolved at link-time, so an implib is generated for the +# executable, and the shared module linked with it. +# +# See testcase 125 for an example of the more complex portability gymnastics +# required if we do not know (at link-time) what provides the symbol. + +cc = meson.get_compiler('c') +if cc.get_id() == 'pgi' + error('MESON_SKIP_TEST PGI has its own unique set of macros that would need to be handled') +endif + +dl = meson.get_compiler('c').find_library('dl', required: false) +e = executable('prog', 'prog.c', dependencies: dl, export_dynamic: true) +m = shared_module('module', 'module.c', link_with: e) +test('test', e, args: m.full_path()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 shared module resolving symbol in executable/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 shared module resolving symbol in executable/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 shared module resolving symbol in executable/module.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 shared module resolving symbol in executable/module.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +extern int func_from_executable(void); + +int DLL_PUBLIC func(void) { + return func_from_executable(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 shared module resolving symbol in executable/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 shared module resolving symbol in executable/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/148 shared module resolving symbol in executable/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/148 shared module resolving symbol in executable/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,61 @@ +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif + +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +typedef int (*fptr) (void); + +int DLL_PUBLIC +func_from_executable(void) +{ + return 42; +} + +int main(int argc, char **argv) +{ + int expected, actual; + fptr importedfunc; + + if (argc=0) {}; // noop + +#ifdef _WIN32 + HMODULE h = LoadLibraryA(argv[1]); +#else + void *h = dlopen(argv[1], RTLD_NOW); +#endif + assert(h != NULL); + +#ifdef _WIN32 + importedfunc = (fptr) GetProcAddress (h, "func"); +#else + importedfunc = (fptr) dlsym(h, "func"); +#endif + assert(importedfunc != NULL); + assert(importedfunc != func_from_executable); + + actual = (*importedfunc)(); + expected = func_from_executable(); + assert(actual == expected); + +#ifdef _WIN32 + FreeLibrary(h); +#else + dlclose(h); +#endif + + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 dotinclude/dotproc.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 dotinclude/dotproc.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 dotinclude/dotproc.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 dotinclude/dotproc.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include"stdio.h" + +#ifndef WRAPPER_INCLUDED +#error The wrapper stdio.h was not included. +#endif + +int main(void) { + printf("Eventually I got printed.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 dotinclude/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 dotinclude/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 dotinclude/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 dotinclude/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,4 @@ +project('dotinclude', 'c') + +executable('dotproc', 'dotproc.c', + implicit_include_directories : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 dotinclude/stdio.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 dotinclude/stdio.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 dotinclude/stdio.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 dotinclude/stdio.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +// There is no #pragma once because we _want_ to cause an eternal loop +// if this wrapper invokes itself. + +#define WRAPPER_INCLUDED + +#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/3rdorderdeps/lib.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/3rdorderdeps/lib.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/3rdorderdeps/lib.c.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/3rdorderdeps/lib.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "../lib.h" - -int get_@DEPENDENCY@dep_value (void); - -SYMBOL_EXPORT -int get_@LIBTYPE@@DEPENDENCY@dep_value (void) { - return get_@DEPENDENCY@dep_value (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/3rdorderdeps/main.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/3rdorderdeps/main.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/3rdorderdeps/main.c.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/3rdorderdeps/main.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include - -#include "../lib.h" - -SYMBOL_IMPORT int get_@LIBTYPE@@DEPENDENCY@dep_value (void); - -int main(void) { - int val; - - val = get_@LIBTYPE@@DEPENDENCY@dep_value (); - if (val != @VALUE@) { - printf("@LIBTYPE@@DEPENDENCY@ was %i instead of @VALUE@\n", val); - return -1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/3rdorderdeps/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/3rdorderdeps/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/3rdorderdeps/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/3rdorderdeps/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -dep3_libs = [] - -# Permutate all combinations of shared and static libraries up to three levels -# executable -> shared -> static -> shared (etc) -foreach dep2 : ['sh', 'st'] - foreach dep1 : ['sh', 'st'] - foreach libtype : ['sh', 'st'] - name = libtype + dep1 + dep2 - if dep2 == 'sh' - libret = 1 - elif dep2 == 'st' - libret = 2 - else - error('Unknown dep2 "@0@"'.format(dep2)) - endif - - if libtype == 'sh' - target = 'shared_library' - build_args = [] - elif libtype == 'st' - target = 'static_library' - build_args = ['-DMESON_STATIC_BUILD'] - else - error('Unknown libtype "@0@"'.format(libtype)) - endif - - cdata = configuration_data() - cdata.set('DEPENDENCY', dep1 + dep2) - cdata.set('LIBTYPE', libtype) - cdata.set('VALUE', libret) - - lib_c = configure_file(input : 'lib.c.in', - output : name + '-lib.c', - configuration : cdata) - dep = get_variable(dep1 + dep2 + 'dep') - dep3_lib = build_target(name, lib_c, link_with : dep, - target_type : target, - c_args : build_args) - dep3_libs += [dep3_lib] - - main_c = configure_file(input : 'main.c.in', - output : name + '-main.c', - configuration : cdata) - dep3_bin = executable(name, main_c, link_with : dep3_lib, - c_args : build_args) - test(name + 'test', dep3_bin) - endforeach - endforeach -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/lib1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/lib1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/lib1.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/lib1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int get_st2_prop (void); -int get_st3_prop (void); - -int get_st1_value (void) { - return get_st2_prop () + get_st3_prop (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/lib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/lib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/lib2.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/lib2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int get_st1_prop (void); -int get_st3_prop (void); - -int get_st2_value (void) { - return get_st1_prop () + get_st3_prop (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/lib3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/lib3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/lib3.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/lib3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int get_st1_prop (void); -int get_st2_prop (void); - -int get_st3_value (void) { - return get_st1_prop () + get_st2_prop (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -#include - -#include "../lib.h" - -int get_st1_value (void); -int get_st2_value (void); -int get_st3_value (void); - -int main(void) { - int val; - - val = get_st1_value (); - if (val != 5) { - printf("st1 value was %i instead of 5\n", val); - return -1; - } - val = get_st2_value (); - if (val != 4) { - printf("st2 value was %i instead of 4\n", val); - return -2; - } - val = get_st3_value (); - if (val != 3) { - printf("st3 value was %i instead of 3\n", val); - return -3; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -st1 = static_library('st1', 'lib1.c', 'prop1.c') -st2 = static_library('st2', 'lib2.c', 'prop2.c') -st3 = static_library('st3', 'lib3.c', 'prop3.c') - -test('circular', executable('circular', 'main.c', link_with : [st1, st2, st3])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/prop1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/prop1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/prop1.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/prop1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int get_st1_prop (void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/prop2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/prop2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/prop2.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/prop2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int get_st2_prop (void) { - return 2; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/prop3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/prop3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/circular/prop3.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/circular/prop3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int get_st3_prop (void) { - return 3; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/libsto.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/libsto.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/libsto.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/libsto.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "../lib.h" - -int get_builto_value (void); - -SYMBOL_EXPORT -int get_stodep_value (void) { - return get_builto_value (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -# Test https://github.com/mesonbuild/meson/issues/2096 -# Note that removing 'shnodep' from link_with: makes the error go away because -# then it is added after the static library is added to the link command. -test('shared-static', executable('shstexe', 'shstmain.c', link_with : [shnodep, stshdep])) - -# Static library that needs a symbol defined in an object file. This already -# works, but good to add a test case early. -stodep = static_library('stodep', 'libsto.c') -test('stodep', executable('stodep', 'stomain.c', 'stobuilt.c', link_with : stodep)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/shstmain.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/shstmain.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/shstmain.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/shstmain.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include - -#include "../lib.h" - -int get_stshdep_value (void); - -int main(void) { - int val; - - val = get_stshdep_value (); - if (val != 1) { - printf("st1 value was %i instead of 1\n", val); - return -1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/stobuilt.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/stobuilt.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/stobuilt.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/stobuilt.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include "../lib.h" - - -SYMBOL_EXPORT -int get_builto_value (void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/stomain.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/stomain.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/edge-cases/stomain.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/edge-cases/stomain.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include - -#include "../lib.h" - -int get_stodep_value (void); - -int main(void) { - int val; - - val = get_stodep_value (); - if (val != 1) { - printf("st1 value was %i instead of 1\n", val); - return -1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/lib.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/lib.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/lib.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/lib.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -#if defined _WIN32 - #ifdef MESON_STATIC_BUILD - #define SYMBOL_EXPORT - #define SYMBOL_IMPORT - #else - #define SYMBOL_IMPORT __declspec(dllimport) - #define SYMBOL_EXPORT __declspec(dllexport) - #endif -#else - #define SYMBOL_IMPORT - #if defined __GNUC__ - #define SYMBOL_EXPORT __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define SYMBOL_EXPORT - #endif -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -#include - -#include "lib.h" - -int get_stnodep_value (void); -int get_stshdep_value (void); -int get_ststdep_value (void); -SYMBOL_IMPORT int get_shnodep_value (void); -SYMBOL_IMPORT int get_shshdep_value (void); -SYMBOL_IMPORT int get_shstdep_value (void); - -int main(void) { - int val; - - val = get_shnodep_value (); - if (val != 1) { - printf("shnodep was %i instead of 1\n", val); - return -1; - } - val = get_stnodep_value (); - if (val != 2) { - printf("stnodep was %i instead of 2\n", val); - return -2; - } - val = get_shshdep_value (); - if (val != 1) { - printf("shshdep was %i instead of 1\n", val); - return -3; - } - val = get_shstdep_value (); - if (val != 2) { - printf("shstdep was %i instead of 2\n", val); - return -4; - } - val = get_stshdep_value (); - if (val != 1) { - printf("shstdep was %i instead of 1\n", val); - return -5; - } - val = get_ststdep_value (); - if (val != 2) { - printf("ststdep was %i instead of 2\n", val); - return -6; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/meson.build" 2020-01-07 21:08:44.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -project('recursive dependencies', 'c') - -# Test that you can link a shared executable to: -# - A shared library with no other deps -subdir('shnodep') -# - A static library with no other deps -subdir('stnodep') -# - A shared library with a shared library dep -subdir('shshdep') -# - A shared library with a static library dep -subdir('shstdep') -# - A static library with a shared library dep -subdir('stshdep') -# - A static library with a static library dep -subdir('ststdep') - -test('alldeps', - executable('alldeps', 'main.c', - link_with : [shshdep, shstdep, ststdep, stshdep])) - -# More combinations of static and shared libraries -subdir('3rdorderdeps') - -# Circular dependencies between static libraries -# This requires the use of --start/end-group with GNU ld -subdir('circular') - -# Various edge cases that have been reported -subdir('edge-cases') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shnodep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shnodep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shnodep/lib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shnodep/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include "../lib.h" - -SYMBOL_EXPORT -int get_shnodep_value (void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shnodep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shnodep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shnodep/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shnodep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -shnodep = shared_library('shnodep', 'lib.c', version: '0.0.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shshdep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shshdep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shshdep/lib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shshdep/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "../lib.h" - -int get_shnodep_value (void); - -SYMBOL_EXPORT -int get_shshdep_value (void) { - return get_shnodep_value (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shshdep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shshdep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shshdep/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shshdep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -shshdep = shared_library('shshdep', 'lib.c', link_with : shnodep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shstdep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shstdep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shstdep/lib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shstdep/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "../lib.h" - -int get_stnodep_value (void); - -SYMBOL_EXPORT -int get_shstdep_value (void) { - return get_stnodep_value (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shstdep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shstdep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/shstdep/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/shstdep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -shstdep = shared_library('shstdep', 'lib.c', link_with : stnodep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/stnodep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/stnodep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/stnodep/lib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/stnodep/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include "../lib.h" - -SYMBOL_EXPORT -int get_stnodep_value (void) { - return 2; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/stnodep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/stnodep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/stnodep/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/stnodep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -stnodep = static_library('stnodep', 'lib.c', - c_args : '-DMESON_STATIC_BUILD') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/stshdep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/stshdep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/stshdep/lib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/stshdep/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "../lib.h" - -int get_shnodep_value (void); - -SYMBOL_EXPORT -int get_stshdep_value (void) { - return get_shnodep_value (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/stshdep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/stshdep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/stshdep/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/stshdep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -stshdep = static_library('stshdep', 'lib.c', link_with : shnodep, - c_args : '-DMESON_STATIC_BUILD') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/ststdep/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/ststdep/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/ststdep/lib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/ststdep/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "../lib.h" - -int get_stnodep_value (void); - -SYMBOL_EXPORT -int get_ststdep_value (void) { - return get_stnodep_value (); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/ststdep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/ststdep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/149 recursive linking/ststdep/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/149 recursive linking/ststdep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -ststdep = static_library('ststdep', 'lib.c', link_with : stnodep, - c_args : '-DMESON_STATIC_BUILD') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/check_file.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/check_file.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/check_file.py" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/check_file.py" 2021-11-02 19:58:07.000000000 +0000 @@ -3,8 +3,18 @@ import os import sys +def permit_osx_workaround(m1, m2): + import platform + if platform.system().lower() != 'darwin': + return False + if m2 % 10000 != 0: + return False + if m1//10000 != m2//10000: + return False + return True + if len(sys.argv) == 2: - assert(os.path.exists(sys.argv[1])) + assert os.path.exists(sys.argv[1]) elif len(sys.argv) == 3: f1 = sys.argv[1] f2 = sys.argv[2] @@ -12,9 +22,13 @@ m2 = os.stat(f2).st_mtime_ns # Compare only os.stat() if m1 != m2: - raise RuntimeError('mtime of {!r} () != mtime of {!r} ()'.format(f1, m1, f2, m2)) + # Under macOS the lower four digits sometimes get assigned + # zero, even though shutil.copy2 should preserve metadata. + # Just have to accept it, I guess. + if not permit_osx_workaround(m1, m2): + raise RuntimeError(f'mtime of {f1!r} ({m1!r}) != mtime of {f2!r} ({m2!r})') import filecmp if not filecmp.cmp(f1, f2): - raise RuntimeError('{!r} != {!r}'.format(f1, f2)) + raise RuntimeError(f'{f1!r} != {f2!r}') else: raise AssertionError diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/file_contains.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/file_contains.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/file_contains.py" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/file_contains.py" 2021-04-27 06:49:45.000000000 +0000 @@ -11,7 +11,7 @@ text = args.text[0] - with open(args.file[0], 'r', encoding='utf-8') as f: + with open(args.file[0], encoding='utf-8') as f: for line in f: if line.strip() == text: return 0 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/generator-deps.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/generator-deps.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/generator-deps.py" 2019-10-06 17:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/generator-deps.py" 2021-04-27 06:49:45.000000000 +0000 @@ -16,4 +16,4 @@ depf = Path(sys.argv[2]) if not depf.exists(): with depf.open('w') as ofile: - ofile.write("{}: depfile\n".format(outputf.name)) + ofile.write(f"{outputf.name}: depfile\n") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/generator.py" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/generator.py" 2021-11-02 19:58:07.000000000 +0000 @@ -11,7 +11,7 @@ inputf = Path(sys.argv[1]) outputf = Path(sys.argv[2]) -assert(inputf.exists()) +assert inputf.exists() with outputf.open('w') as ofile: ofile.write("#define ZERO_RESULT 0\n") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/installed_files.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -usr/share/appdir/config2.h -usr/share/appdir/config2b.h -usr/share/appdireh/config2-1.h -usr/share/appdirok/config2-2.h diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/meson.build" 2020-01-07 21:06:24.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -1,4 +1,4 @@ -project('configure file test', 'c') +project('configure file test', 'c', meson_version: '>=0.47.0') conf = configuration_data() @@ -10,6 +10,7 @@ assert(conf.get('var') == 'mystring', 'Get function is not working.') assert(conf.get('var', 'default') == 'mystring', 'Get function is not working.') assert(conf.get('notthere', 'default') == 'default', 'Default value getting is not working.') +assert(conf.keys() == ['BE_TRUE', 'other', 'second', 'var'], 'Keys function is not working') cfile = configure_file(input : 'config.h.in', output : 'config.h', @@ -39,7 +40,7 @@ output : 'config2.h', command : [genprog, scriptfile, ifile, ofile], install_dir : 'share/appdir') -ret = run_command(check_file, outf) +ret = run_command(check_file, outf, check: false) if ret.returncode() != 0 error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr())) endif @@ -52,7 +53,7 @@ output : 'config2b.h', command : [genprog, genscript2b, ofile2b], install_dir : 'share/appdir') -ret = run_command(check_file, outf) +ret = run_command(check_file, outf, check: false) if ret.returncode() != 0 error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr())) endif @@ -63,7 +64,7 @@ output : 'config2deps.h', depfile : 'depfile.d', command : [genprog, genscript2deps, ofile2deps, '@DEPFILE@']) -ret = run_command(check_file, outf) +ret = run_command(check_file, outf, check: false) if ret.returncode() != 0 error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr())) endif @@ -115,7 +116,7 @@ file_contains_py = find_program('file_contains.py') test_string = 'hello world' test_input_file = join_paths(meson.current_build_dir(), test_string) -run_command(find_program('touch.py'), test_input_file) +run_command(find_program('touch.py'), test_input_file, check: true) configs = [ # no input configure_file(command: [ basename_py, test_string ], capture: true, output: 'capture test 1'), @@ -181,7 +182,13 @@ outf = configure_file(input : inf, output : 'invalid-utf8.bin', copy: true) -ret = run_command(check_file, inf, outf) +ret = run_command(check_file, inf, outf, check: false) +if ret.returncode() != 0 + error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr())) +endif +# Now the same, but using a File object as an argument. +inf2 = files('invalid-utf8.bin.in')[0] +ret = run_command(check_file, inf2, outf, check: false) if ret.returncode() != 0 error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr())) endif @@ -190,7 +197,7 @@ outf = configure_file(input : inf, output : 'somebinary.bin', copy : true) -ret = run_command(check_file, inf, outf) +ret = run_command(check_file, inf, outf, check: false) if ret.returncode() != 0 error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr())) endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/subdir/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/subdir/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -3,20 +3,20 @@ output : 'config2-1.h', command : [genprog, scriptfile, ifile, 'config2-1.h'], install_dir : 'share/appdireh') -run_command(check_file, join_paths(meson.current_build_dir(), 'config2-1.h')) +run_command(check_file, join_paths(meson.current_build_dir(), 'config2-1.h'), check: true) # Configure in subdir with files() for input and relative for output configure_file(input : '../dummy.dat', output : 'config2-2.h', command : [genprog, scriptfile, files('../dummy.dat'), 'config2-2.h'], install_dir : 'share/appdirok') -run_command(check_file, join_paths(meson.current_build_dir(), 'config2-2.h')) +run_command(check_file, join_paths(meson.current_build_dir(), 'config2-2.h'), check: true) # Configure in subdir with string templates for input and output configure_file(input : '../dummy.dat', output : 'config2-3.h', command : [found_script, '@INPUT@', '@OUTPUT@']) -run_command(check_file, join_paths(meson.current_build_dir(), 'config2-3.h')) +run_command(check_file, join_paths(meson.current_build_dir(), 'config2-3.h'), check: true) # Test that overwriting an existing file creates a warning. configure_file( diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/14 configure file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/14 configure file/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "installed": [ + {"type": "file", "file": "usr/share/appdir/config2.h"}, + {"type": "file", "file": "usr/share/appdir/config2b.h"}, + {"type": "file", "file": "usr/share/appdireh/config2-1.h"}, + {"type": "file", "file": "usr/share/appdirok/config2-2.h"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 library at root/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 library at root/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 library at root/lib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 library at root/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ -__declspec(dllexport) -#endif -int fn(void) { - return -1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 library at root/main/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 library at root/main/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 library at root/main/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 library at root/main/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -extern int fn(void); - -int main(void) { - return 1 + fn(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 library at root/main/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 library at root/main/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 library at root/main/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 library at root/main/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -exe = executable('main', 'main.c', link_with : lib) -test('stuff works', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 library at root/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 library at root/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 library at root/meson.build" 2020-01-07 21:08:42.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 library at root/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('lib@root', 'c') -lib = shared_library('lib', 'lib.c') -subdir('main') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/all/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/all/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/all/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/all/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-all', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/benchmark/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/benchmark/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/benchmark/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/benchmark/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-benchmark', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/clean/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/clean/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/clean/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/clean/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-clean', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/clean-ctlist/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/clean-ctlist/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/clean-ctlist/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/clean-ctlist/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-clean-ctlist', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/clean-gcda/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/clean-gcda/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/clean-gcda/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/clean-gcda/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-clean-gcda', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/clean-gcno/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/clean-gcno/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/clean-gcno/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/clean-gcno/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-clean-gcno', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-coverage', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage-html/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage-html/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage-html/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage-html/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-coverage-html', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage-sonarqube/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage-sonarqube/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage-sonarqube/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage-sonarqube/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +executable('test-coverage-sonarqube', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage-text/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage-text/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage-text/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage-text/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-coverage-text', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage-xml/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage-xml/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/coverage-xml/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/coverage-xml/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-coverage-xml', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/dist/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/dist/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/dist/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/dist/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-dist', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/distcheck/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/distcheck/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/distcheck/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/distcheck/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-distcheck', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/install/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/install/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/install/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/install/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-install', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/meson.build" 2021-10-23 16:49:38.000000000 +0000 @@ -0,0 +1,34 @@ +project('reserved target names', 'c') + # FIXME: Setting this causes it to leak to all other tests + #default_options : ['b_coverage=true'] + +subdir('all') +subdir('benchmark') +subdir('clean') +subdir('clean-ctlist') +subdir('clean-gcda') +subdir('clean-gcno') +subdir('coverage') +subdir('coverage-html') +subdir('coverage-text') +subdir('coverage-xml') +subdir('dist') +subdir('distcheck') +subdir('install') +# We don't have a 'PHONY' directory because Windows and OSX +# choke horribly when there are two entries with the same +# name but different case. +subdir('phony') +subdir('reconfigure') +subdir('scan-build') +subdir('test') +subdir('uninstall') + +subdir('runtarget') + +py3 = import('python3').find_python() + +custom_target('ctlist-test', output : 'out.txt', + command : [py3, '-c', 'print("")'], + capture : true, + build_by_default : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/phony/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/phony/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/phony/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/phony/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-phony', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/reconfigure/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/reconfigure/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/reconfigure/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/reconfigure/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-reconfigure', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/runtarget/echo.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/runtarget/echo.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/runtarget/echo.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/runtarget/echo.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys + +if len(sys.argv) > 1: + print(sys.argv[1]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/runtarget/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/runtarget/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/runtarget/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/runtarget/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +configure_file(output : 'config.h', configuration: configuration_data()) +run_target('runtarget', command : [find_program('echo.py')]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/scan-build/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/scan-build/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/scan-build/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/scan-build/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-scan-build', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/test/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/test/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/test/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/test/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-test', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/test.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/uninstall/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/uninstall/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/150 reserved targets/uninstall/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/150 reserved targets/uninstall/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +executable('test-uninstall', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir1/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir1/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir1/file.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir1/file.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +extern int dir2; +extern int dir2_dir1; +extern int dir3; +extern int dir3_dir1; + +int main(void) { + if (dir2 != 20) + return 1; + if (dir2_dir1 != 21) + return 1; + if (dir3 != 30) + return 1; + if (dir3_dir1 != 31) + return 1; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +sources += files('file.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir2/dir1/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir2/dir1/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir2/dir1/file.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir2/dir1/file.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int dir2_dir1 = 21; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir2/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir2/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir2/file.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir2/file.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int dir2 = 20; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +sources += files('file.c', 'dir1/file.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir3/dir1/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir3/dir1/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir3/dir1/file.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir3/dir1/file.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int dir3_dir1 = 31; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir3/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir3/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir3/file.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir3/file.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int dir3 = 30; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/dir3/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/dir3/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +lib = static_library('lib', 'file.c', 'dir1/file.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 duplicate source names/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 duplicate source names/meson.build" 2021-10-23 16:49:37.000000000 +0000 @@ -0,0 +1,19 @@ +project('proj', 'c') + +if meson.backend() == 'xcode' + # Xcode gives object files unique names but only if they would clash. For example + # two files named lib.o instead get the following names: + # + # lib-4fbe522d8ba4cb1f1b89cc2df640a2336b92e1a5565f0a4c5a79b5b5e2969eb9.o + # lib-4fbe522d8ba4cb1f1b89cc2df640a2336deeff2bc2297affaadbe20f5cbfee56.o + # + # No-one has reverse engineered the naming scheme so we would access them. + # IF you feel up to the challenge, patches welcome. + error('MESON_SKIP_TEST, Xcode can not extract objs when they would have the same filename.') +endif + +sources = [] +subdir('dir1') +subdir('dir2') +subdir('dir3') +executable('a.out', sources : sources, objects : lib.extract_all_objects()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/fallback.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/fallback.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/fallback.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/fallback.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include - -void increment_fallback(float arr[4]) { - int i; - for(i=0; i<4; i++) { - arr[i]++; - } -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/include/simdheader.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/include/simdheader.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/include/simdheader.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/include/simdheader.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#pragma once - -#define I_CAN_HAZ_SIMD diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/meson.build" 2020-01-07 21:08:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -project('simd', 'c') - -simd = import('unstable-simd') - -cc = meson.get_compiler('c') - -cdata = configuration_data() - -if not meson.is_cross_build() and host_machine.cpu_family() == 'arm' and cc.get_id() == 'clang' - message('Adding -march=armv7 because assuming that this build happens on Raspbian.') - message('Its Clang seems to be misconfigured and does not support NEON by default.') - add_project_arguments('-march=armv7', language : 'c') -endif - -if cc.get_id() == 'msvc' and cc.version().version_compare('<17') - error('MESON_SKIP_TEST VS2010 produces broken binaries on x86.') -endif - -# FIXME add [a, b] = function() -rval = simd.check('mysimds', - mmx : 'simd_mmx.c', - sse : 'simd_sse.c', - sse2 : 'simd_sse2.c', - sse3 : 'simd_sse3.c', - ssse3 : 'simd_ssse3.c', - sse41 : 'simd_sse41.c', - sse42 : 'simd_sse42.c', - avx : 'simd_avx.c', - avx2 : 'simd_avx2.c', - neon : 'simd_neon.c', - compiler : cc, - include_directories : include_directories('include')) - -simdlibs = rval[0] -cdata.merge_from(rval[1]) - -configure_file(output : 'simdconfig.h', - configuration : cdata) - -p = executable('simdtest', 'simdchecker.c', 'fallback.c', - link_with : simdlibs) - -test('simdtest', p) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_avx2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_avx2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_avx2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_avx2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -#include -#include -#include - -/* - * FIXME add proper runtime detection for VS. - */ - -#ifdef _MSC_VER -#include -int avx2_available(void) { - return 0; -} -#else -#include -#include - -#if defined(__APPLE__) -int avx2_available(void) { return 0; } -#else -int avx2_available(void) { - return __builtin_cpu_supports("avx2"); -} -#endif -#endif - -void increment_avx2(float arr[4]) { - double darr[4]; - darr[0] = arr[0]; - darr[1] = arr[1]; - darr[2] = arr[2]; - darr[3] = arr[3]; - __m256d val = _mm256_loadu_pd(darr); - __m256d one = _mm256_set1_pd(1.0); - __m256d result = _mm256_add_pd(val, one); - _mm256_storeu_pd(darr, result); - one = _mm256_permute4x64_pd(one, 66); /* A no-op, just here to use AVX2. */ - arr[0] = (float)darr[0]; - arr[1] = (float)darr[1]; - arr[2] = (float)darr[2]; - arr[3] = (float)darr[3]; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_avx.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_avx.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_avx.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_avx.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -#include - -#ifndef I_CAN_HAZ_SIMD -#error The correct internal header was not used -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#include -int avx_available(void) { - return 1; -} -#else -#include -#include - -#ifdef __APPLE__ -/* - * Apple ships a broken __builtin_cpu_supports and - * some machines in the CI farm seem to be too - * old to have AVX so just always return 0 here. - */ -int avx_available(void) { return 0; } -#else - -int avx_available(void) { - return __builtin_cpu_supports("avx"); -} -#endif -#endif - -void increment_avx(float arr[4]) { - double darr[4]; - darr[0] = arr[0]; - darr[1] = arr[1]; - darr[2] = arr[2]; - darr[3] = arr[3]; - __m256d val = _mm256_loadu_pd(darr); - __m256d one = _mm256_set1_pd(1.0); - __m256d result = _mm256_add_pd(val, one); - _mm256_storeu_pd(darr, result); - arr[0] = (float)darr[0]; - arr[1] = (float)darr[1]; - arr[2] = (float)darr[2]; - arr[3] = (float)darr[3]; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simdchecker.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simdchecker.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simdchecker.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simdchecker.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ -#include -#include -#include - -typedef void (*simd_func)(float*); - -int check_simd_implementation(float *four, - const float *four_initial, - const char *simd_type, - const float *expected, - simd_func fptr, - const int blocksize) { - int rv = 0; - memcpy(four, four_initial, blocksize*sizeof(float)); - printf("Using %s.\n", simd_type); - fptr(four); - for(int i=0; i - -#ifdef _MSC_VER -#define ALIGN_16 __declspec(align(16)) -#else -#include -#define ALIGN_16 alignas(16) -#endif - - -/* Yes, I do know that arr[4] decays into a pointer - * as a function argument. Don't do this in real code - * but for this test it is ok. - */ - -void increment_fallback(float arr[4]); - -#if HAVE_MMX -int mmx_available(void); -void increment_mmx(float arr[4]); -#endif - -#if HAVE_SSE -int sse_available(void); -void increment_sse(float arr[4]); -#endif - -#if HAVE_SSE2 -int sse2_available(void); -void increment_sse2(float arr[4]); -#endif - -#if HAVE_SSE3 -int sse3_available(void); -void increment_sse3(float arr[4]); -#endif - -#if HAVE_SSSE3 -int ssse3_available(void); -void increment_ssse3(float arr[4]); -#endif - -#if HAVE_SSE41 -int sse41_available(void); -void increment_sse41(float arr[4]); -#endif - -#if HAVE_SSE42 -int sse42_available(void); -void increment_sse42(float arr[4]); -#endif - -#if HAVE_AVX -int avx_available(void); -void increment_avx(float arr[4]); -#endif - -#if HAVE_AVX2 -int avx2_available(void); -void increment_avx2(float arr[4]); -#endif - -#if HAVE_NEON -int neon_available(void); -void increment_neon(float arr[4]); -#endif - -#if HAVE_ALTIVEC -int altivec_available(void); -void increment_altivec(float arr[4]); -#endif - -/* And so on. */ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_mmx.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_mmx.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_mmx.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_mmx.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -#include -#include - -#include - -#ifdef _MSC_VER -#include -int mmx_available(void) { - return 1; -} -/* Contrary to MSDN documentation, MMX intrinsics - * just plain don't work. - */ -void increment_mmx(float arr[4]) { - arr[0]++; - arr[1]++; - arr[2]++; - arr[3]++; -} -#elif defined(__MINGW32__) -int mmx_available(void) { - return 1; -} -/* MinGW does not seem to ship with MMX or it is broken. - */ -void increment_mmx(float arr[4]) { - arr[0]++; - arr[1]++; - arr[2]++; - arr[3]++; -} -#else -#include -#include - -#if defined(__APPLE__) -int mmx_available(void) { return 1; } -#else -int mmx_available(void) { - return __builtin_cpu_supports("mmx"); -} -#endif -void increment_mmx(float arr[4]) { - /* Super ugly but we know that values in arr are always small - * enough to fit in int16; - */ - int i; - __m64 packed = _mm_set_pi16(arr[3], arr[2], arr[1], arr[0]); - __m64 incr = _mm_set1_pi16(1); - __m64 result = _mm_add_pi16(packed, incr); - /* Should be - * int64_t unpacker = _m_to_int64(result); - * but it does not exist on 32 bit platforms for some reason. - */ - int64_t unpacker = (int64_t)(result); - _mm_empty(); - for(i=0; i<4; i++) { - /* This fails on GCC 8 when optimizations are enabled. - * Disable it. Patches welcome to fix this. - arr[i] = (float)(unpacker & ((1<<16)-1)); - unpacker >>= 16; - */ - arr[i] += 1.0f; - } -} - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_neon.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_neon.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_neon.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_neon.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#include -#include - -#include -#include - -int neon_available(void) { - return 1; /* Incorrect, but I don't know how to check this properly. */ -} - -void increment_neon(float arr[4]) { - float32x2_t a1, a2, one; - a1 = vld1_f32(arr); - a2 = vld1_f32(&arr[2]); - one = vdup_n_f32(1.0); - a1 = vadd_f32(a1, one); - a2 = vadd_f32(a2, one); - vst1_f32(arr, a1); - vst1_f32(&arr[2], a2); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -#include -#include -#include - -#ifdef _MSC_VER -int sse2_available(void) { - return 1; -} - -#else -#include -#include - -#if defined(__APPLE__) -int sse2_available(void) { return 1; } -#else -int sse2_available(void) { - return __builtin_cpu_supports("sse2"); -} -#endif -#endif - -void increment_sse2(float arr[4]) { - ALIGN_16 double darr[4]; - __m128d val1 = _mm_set_pd(arr[0], arr[1]); - __m128d val2 = _mm_set_pd(arr[2], arr[3]); - __m128d one = _mm_set_pd(1.0, 1.0); - __m128d result = _mm_add_pd(val1, one); - _mm_store_pd(darr, result); - result = _mm_add_pd(val2, one); - _mm_store_pd(&darr[2], result); - arr[0] = (float)darr[1]; - arr[1] = (float)darr[0]; - arr[2] = (float)darr[3]; - arr[3] = (float)darr[2]; -} - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse3.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -#include -#include - -#ifdef _MSC_VER -#include -int sse3_available(void) { - return 1; -} -#else - -#include -#include -#include - -#if defined(__APPLE__) -int sse3_available(void) { return 1; } -#else -int sse3_available(void) { - return __builtin_cpu_supports("sse3"); -} -#endif -#endif - -void increment_sse3(float arr[4]) { - ALIGN_16 double darr[4]; - __m128d val1 = _mm_set_pd(arr[0], arr[1]); - __m128d val2 = _mm_set_pd(arr[2], arr[3]); - __m128d one = _mm_set_pd(1.0, 1.0); - __m128d result = _mm_add_pd(val1, one); - _mm_store_pd(darr, result); - result = _mm_add_pd(val2, one); - _mm_store_pd(&darr[2], result); - result = _mm_hadd_pd(val1, val2); /* This does nothing. Only here so we use an SSE3 instruction. */ - arr[0] = (float)darr[1]; - arr[1] = (float)darr[0]; - arr[2] = (float)darr[3]; - arr[3] = (float)darr[2]; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse41.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse41.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse41.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse41.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#include -#include - -#include - -#ifdef _MSC_VER -#include - -int sse41_available(void) { - return 1; -} - -#else -#include -#include - -#if defined(__APPLE__) -int sse41_available(void) { return 1; } -#else -int sse41_available(void) { - return __builtin_cpu_supports("sse4.1"); -} -#endif -#endif - -void increment_sse41(float arr[4]) { - ALIGN_16 double darr[4]; - __m128d val1 = _mm_set_pd(arr[0], arr[1]); - __m128d val2 = _mm_set_pd(arr[2], arr[3]); - __m128d one = _mm_set_pd(1.0, 1.0); - __m128d result = _mm_add_pd(val1, one); - result = _mm_ceil_pd(result); /* A no-op, only here to use a SSE4.1 intrinsic. */ - _mm_store_pd(darr, result); - result = _mm_add_pd(val2, one); - _mm_store_pd(&darr[2], result); - arr[0] = (float)darr[1]; - arr[1] = (float)darr[0]; - arr[2] = (float)darr[3]; - arr[3] = (float)darr[2]; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse42.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse42.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse42.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse42.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -#include -#include -#include - -#ifdef _MSC_VER -#include - -int sse42_available(void) { - return 1; -} - -#else - -#include -#include - -#ifdef __APPLE__ -int sse42_available(void) { - return 1; -} -#else -int sse42_available(void) { - return __builtin_cpu_supports("sse4.2"); -} -#endif - -#endif - -void increment_sse42(float arr[4]) { - ALIGN_16 double darr[4]; - __m128d val1 = _mm_set_pd(arr[0], arr[1]); - __m128d val2 = _mm_set_pd(arr[2], arr[3]); - __m128d one = _mm_set_pd(1.0, 1.0); - __m128d result = _mm_add_pd(val1, one); - _mm_store_pd(darr, result); - result = _mm_add_pd(val2, one); - _mm_store_pd(&darr[2], result); - _mm_crc32_u32(42, 99); /* A no-op, only here to use an SSE4.2 instruction. */ - arr[0] = (float)darr[1]; - arr[1] = (float)darr[0]; - arr[2] = (float)darr[3]; - arr[3] = (float)darr[2]; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_sse.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_sse.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -#include -#include - -#ifdef _MSC_VER -#include -int sse_available(void) { - return 1; -} -#else - -#include -#include -#include - -#if defined(__APPLE__) -int sse_available(void) { return 1; } -#else -int sse_available(void) { - return __builtin_cpu_supports("sse"); -} -#endif -#endif - -void increment_sse(float arr[4]) { - __m128 val = _mm_load_ps(arr); - __m128 one = _mm_set_ps1(1.0); - __m128 result = _mm_add_ps(val, one); - _mm_storeu_ps(arr, result); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_ssse3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_ssse3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/151 simd/simd_ssse3.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/151 simd/simd_ssse3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -#include -#include - -#include -#include - -#ifdef _MSC_VER -#include - -int ssse3_available(void) { - return 1; -} - -#else - -#include -#include - -int ssse3_available(void) { -#ifdef __APPLE__ - return 1; -#elif defined(__clang__) - /* https://github.com/numpy/numpy/issues/8130 */ - return __builtin_cpu_supports("sse4.1"); -#else - return __builtin_cpu_supports("ssse3"); -#endif -} - -#endif - -void increment_ssse3(float arr[4]) { - ALIGN_16 double darr[4]; - __m128d val1 = _mm_set_pd(arr[0], arr[1]); - __m128d val2 = _mm_set_pd(arr[2], arr[3]); - __m128d one = _mm_set_pd(1.0, 1.0); - __m128d result = _mm_add_pd(val1, one); - __m128i tmp1, tmp2; - tmp1 = tmp2 = _mm_set1_epi16(0); - _mm_store_pd(darr, result); - result = _mm_add_pd(val2, one); - _mm_store_pd(&darr[2], result); - tmp1 = _mm_hadd_epi32(tmp1, tmp2); /* This does nothing. Only here so we use an SSSE3 instruction. */ - arr[0] = (float)darr[1]; - arr[1] = (float)darr[0]; - arr[2] = (float)darr[3]; - arr[3] = (float)darr[2]; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/check_args.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/check_args.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/check_args.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/check_args.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#!python3 + +import sys +from pathlib import Path + +def main(): + if len(sys.argv) != 2: + print(sys.argv) + return 1 + if sys.argv[1] != 'gen.c': + print(sys.argv) + return 2 + Path('foo').touch() + + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/gen_sources.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/gen_sources.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/gen_sources.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/gen_sources.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,49 @@ +# Copyright © 2017 Intel Corporation +# +# 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 argparse +import textwrap + +HEADER = textwrap.dedent('''\ + void stringify(int foo, char * buffer); + ''') + +CODE = textwrap.dedent('''\ + #include + + #ifndef WORKS + # error "This shouldn't have been included" + #endif + + void stringify(int foo, char * buffer) { + sprintf(buffer, "%i", foo); + } + ''') + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--header') + parser.add_argument('--code') + args = parser.parse_args() + + with open(args.header, 'w') as f: + f.write(HEADER) + + with open(args.code, 'w') as f: + f.write(CODE) + + +if __name__ == '__main__': + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +/* Copyright © 2017 Intel Corporation + * + * 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. + */ + +#include "gen.h" + +void func(char * buffer) { + stringify(1, buffer); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/meson.build" 2021-10-23 16:49:38.000000000 +0000 @@ -0,0 +1,80 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +project('custom_target_index', 'c', default_options : 'c_std=c89') + +py_mod = import('python3') +prog_python = py_mod.find_python() + +gen = custom_target( + 'gen.[ch]', + input : 'gen_sources.py', + output : ['gen.c', 'gen.h'], + command : [prog_python, '@INPUT@', '--header', '@OUTPUT1@', '--code', '@OUTPUT0@'], +) + +has_not_changed = false +if is_disabler(gen) + has_not_changed = true +else + has_not_changed = true +endif + +assert(has_not_changed, 'Custom target has changed.') + +assert(not is_disabler(gen), 'Custom target is a disabler.') + +lib = static_library( + 'libfoo', + ['lib.c', gen[1]], +) + +has_not_changed = false +if is_disabler(lib) + has_not_changed = true +else + has_not_changed = true +endif + +assert(has_not_changed, 'Static library has changed.') + +assert(not is_disabler(lib), 'Static library is a disabler.') + +custom_target( + 'foo', + input: gen[0], + output: 'foo', + command: [find_program('check_args.py'), '@INPUT@'], +) + +subdir('subdir') + +gen = disabler() + +assert(is_disabler(gen), 'Generator is not a disabler.') + +lib = static_library( + 'libfoo', + ['lib.c', gen[1]], +) + +assert(is_disabler(lib), 'Static library is not a disabler.') + +if lib.found() + lib_disabled = false +else + lib_disabled = true +endif + +assert(lib_disabled, 'Static library was not disabled.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/subdir/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/subdir/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/subdir/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/subdir/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,22 @@ +/* Copyright © 2017 Intel Corporation + * + * 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. + */ + +#include "gen.h" + +int main(void) { + char buf[50]; + stringify(10, buf); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 index customtarget/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 index customtarget/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +foo = executable( + 'foo', + ['foo.c', gen[0], gen[1]], + c_args : '-DWORKS', +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 shared module resolving symbol in executable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 shared module resolving symbol in executable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 shared module resolving symbol in executable/meson.build" 2020-01-07 21:08:44.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 shared module resolving symbol in executable/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -project('shared module resolving symbol in executable', 'c') - -# The shared module contains a reference to the symbol 'func_from_executable', -# which is always provided by the executable which loads it. This symbol can be -# resolved at run-time by an ELF loader. But when building PE/COFF objects, all -# symbols must be resolved at link-time, so an implib is generated for the -# executable, and the shared module linked with it. -# -# See testcase 125 for an example of the more complex portability gymnastics -# required if we do not know (at link-time) what provides the symbol. - -cc = meson.get_compiler('c') -if cc.get_id() == 'pgi' - error('MESON_SKIP_TEST PGI has its own unique set of macros that would need to be handled') -endif - -dl = meson.get_compiler('c').find_library('dl', required: false) -e = executable('prog', 'prog.c', dependencies: dl, export_dynamic: true) -m = shared_module('module', 'module.c', link_with: e) -test('test', e, args: m.full_path()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 shared module resolving symbol in executable/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 shared module resolving symbol in executable/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 shared module resolving symbol in executable/module.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 shared module resolving symbol in executable/module.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -extern int func_from_executable(void); - -int DLL_PUBLIC func(void) { - return func_from_executable(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 shared module resolving symbol in executable/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 shared module resolving symbol in executable/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/152 shared module resolving symbol in executable/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/152 shared module resolving symbol in executable/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -#include -#include -#ifdef _WIN32 -#include -#else -#include -#endif - -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -typedef int (*fptr) (void); - -int DLL_PUBLIC -func_from_executable(void) -{ - return 42; -} - -int main(int argc, char **argv) -{ - int expected, actual; - fptr importedfunc; - - if (argc=0) {}; // noop - -#ifdef _WIN32 - HMODULE h = LoadLibraryA(argv[1]); -#else - void *h = dlopen(argv[1], RTLD_NOW); -#endif - assert(h != NULL); - -#ifdef _WIN32 - importedfunc = (fptr) GetProcAddress (h, "func"); -#else - importedfunc = (fptr) dlsym(h, "func"); -#endif - assert(importedfunc != NULL); - assert(importedfunc != func_from_executable); - - actual = (*importedfunc)(); - expected = func_from_executable(); - assert(actual == expected); - -#ifdef _WIN32 - FreeLibrary(h); -#else - dlclose(h); -#endif - - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 dotinclude/dotproc.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 dotinclude/dotproc.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 dotinclude/dotproc.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 dotinclude/dotproc.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include"stdio.h" - -#ifndef WRAPPER_INCLUDED -#error The wrapper stdio.h was not included. -#endif - -int main(void) { - printf("Eventually I got printed.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 dotinclude/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 dotinclude/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 dotinclude/meson.build" 2020-01-07 21:08:46.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 dotinclude/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('dotinclude', 'c') - -executable('dotproc', 'dotproc.c', - implicit_include_directories : false) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 dotinclude/stdio.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 dotinclude/stdio.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 dotinclude/stdio.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 dotinclude/stdio.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -// There is no #pragma once because we _want_ to cause an eternal loop -// if this wrapper invokes itself. - -#define WRAPPER_INCLUDED - -#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/meson.build" 2021-10-23 16:49:40.000000000 +0000 @@ -0,0 +1,16 @@ +project('mainproj', 'c', + default_options : ['wrap_mode=nodownload'], +) + +subproject('zlib') +foo = subproject('foo') +bar = subproject('bar') + +libfoo = foo.get_variable('libfoo') +libbar = bar.get_variable('libbar') + +executable('grabprog', files('src/subprojects/prog.c')) +executable('grabprog2', files('src/subprojects/foo/prog2.c')) +subdir('src') + +subproject('patchdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +executable('grabprog3', files('subprojects/prog.c')) +executable('grabprog4', files('subprojects/foo/prog2.c')) + +texe = executable('testexe', files('test.c'), link_with: [libfoo, libbar]) + +test('t1', texe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/src/subprojects/foo/prog2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/src/subprojects/foo/prog2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/src/subprojects/foo/prog2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/src/subprojects/foo/prog2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +int main(void) { + printf("Do not have a file layout like this in your own projects.\n"); + printf("This is only to test that this works.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/src/subprojects/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/src/subprojects/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/src/subprojects/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/src/subprojects/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +int main(void) { + printf("Do not have a file layout like this in your own projects.\n"); + printf("This is only to test that this works.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/src/test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/src/test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/src/test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/src/test.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#include + +int bar_dummy_func(void); +int dummy_func(void); + +int main(void) { + printf("Hello world %d\n", bar_dummy_func() + dummy_func()); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/bar-1.0/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/bar-1.0/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/bar-1.0/bar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/bar-1.0/bar.c" 2020-03-21 10:05:46.000000000 +0000 @@ -0,0 +1,3 @@ +int bar_dummy_func(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/bar-1.0/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/bar-1.0/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/bar-1.0/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/bar-1.0/meson.build" 2020-04-25 13:59:16.000000000 +0000 @@ -0,0 +1,2 @@ +project('static lib bar', 'c') +libbar = static_library('bar', 'bar.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/bar.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/bar.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/bar.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/bar.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +[wrap-file] +directory = bar-1.0 +lead_directory_missing = true + +source_filename = bar-1.0.tar.xz +source_hash = f0f61948530dc0d33e3028cd71a9f8ee869f6b3665960d8f41d715cf4aed6467 + +patch_filename = bar-1.0-patch.tar.xz diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0/foo.c" 2020-03-21 10:23:04.000000000 +0000 @@ -0,0 +1,3 @@ +int dummy_func(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0/meson.build" 2020-04-25 13:52:29.000000000 +0000 @@ -0,0 +1,2 @@ +project('static lib', 'c') +libfoo = static_library('foo', 'foo.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/foo.c" 2020-03-21 10:23:04.000000000 +0000 @@ -0,0 +1,3 @@ +int dummy_func(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +project('static lib patchdir', 'c') +libfoo = static_library('foo', 'foo.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/foo.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/foo.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +[wrap-file] +directory = foo-1.0 + +source_url = http://something.invalid +source_filename = foo-1.0.tar.xz +source_hash = 9ed8f67d75e43d3be161efb6eddf30dd01995a958ca83951ea64234bac8908c1 +lead_directory_missing = true + +patch_url = https://something.invalid/patch +patch_filename = foo-1.0-patch.tar.xz +patch_hash = d0ddc5e60fdb27d808552f5ac8d0bb603ea2cba306538b4427b985535b26c9c5 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/.gitignore" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/.gitignore" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/.gitignore" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/.gitignore" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +/foo-1.0 +/bar-1.0 +/foo-1.0-patchdir Binary files /tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/foo-1.0-patch.tar.xz and /tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/foo-1.0-patch.tar.xz differ Binary files /tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/foo-1.0.tar.xz and /tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/foo-1.0.tar.xz differ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +dummy diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +dummy Binary files /tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagefiles/bar-1.0-patch.tar.xz and /tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagefiles/bar-1.0-patch.tar.xz differ Binary files /tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagefiles/bar-1.0.tar.xz and /tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagefiles/bar-1.0.tar.xz differ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagefiles/foo-1.0/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagefiles/foo-1.0/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/packagefiles/foo-1.0/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/packagefiles/foo-1.0/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +project('static lib patchdir', 'c') +libfoo = static_library('foo', 'foo.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/patchdir.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/patchdir.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/patchdir.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/patchdir.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +[wrap-file] +directory = foo-1.0-patchdir + +source_url = http://something.invalid +source_filename = foo-1.0.tar.xz +source_hash = 9ed8f67d75e43d3be161efb6eddf30dd01995a958ca83951ea64234bac8908c1 +lead_directory_missing = true + +patch_directory = foo-1.0 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int dummy_func(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('shared lib', 'c') +library('foo', 'foo.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/zlib.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/zlib.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/153 wrap file should not failed/subprojects/zlib.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/153 wrap file should not failed/subprojects/zlib.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +[wrap-file] +directory = zlib-1.2.8 + +source_url = http://zlib.net/fossils/zlib-1.2.8.tar.gz +source_filename = zlib-1.2.8.tar.gz +source_hash = 36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d + +patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/8/get_zip +patch_filename = zlib-1.2.8-8-wrap.zip +patch_hash = 17c52a0e0c59ce926d3959005d5cd8178c6c7e2c9a4a1304279a8320c955ac60 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 includedir subproj/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 includedir subproj/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 includedir subproj/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 includedir subproj/meson.build" 2021-10-23 16:49:40.000000000 +0000 @@ -0,0 +1,9 @@ +project('include dir in subproj test', 'c') + + +subproject('inctest') + + +exe = executable('prog', 'prog.c') + +test('dummy', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 includedir subproj/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 includedir subproj/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 includedir subproj/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 includedir subproj/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 includedir subproj/subprojects/inctest/include/incfile.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 includedir subproj/subprojects/inctest/include/incfile.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 includedir subproj/subprojects/inctest/include/incfile.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 includedir subproj/subprojects/inctest/include/incfile.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ + +/* file which is used in the subproject */ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 includedir subproj/subprojects/inctest/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 includedir subproj/subprojects/inctest/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 includedir subproj/subprojects/inctest/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 includedir subproj/subprojects/inctest/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ + +project('subproj with includedir', 'c') + + + +compile_check = ''' +#include "incfile.h" +''' + +if not meson.get_compiler('c').compiles(compile_check, name : 'include in subproj', + include_directories: include_directories('include')) + error('failed') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/all/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/all/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/all/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/all/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-all', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/benchmark/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/benchmark/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/benchmark/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/benchmark/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-benchmark', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/clean/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/clean/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/clean/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/clean/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-clean', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/clean-ctlist/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/clean-ctlist/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/clean-ctlist/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/clean-ctlist/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-clean-ctlist', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/clean-gcda/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/clean-gcda/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/clean-gcda/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/clean-gcda/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-clean-gcda', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/clean-gcno/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/clean-gcno/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/clean-gcno/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/clean-gcno/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-clean-gcno', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/coverage/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/coverage/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/coverage/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/coverage/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-coverage', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/coverage-html/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/coverage-html/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/coverage-html/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/coverage-html/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-coverage-html', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/coverage-text/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/coverage-text/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/coverage-text/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/coverage-text/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-coverage-text', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/coverage-xml/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/coverage-xml/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/coverage-xml/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/coverage-xml/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-coverage-xml', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/dist/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/dist/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/dist/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/dist/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-dist', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/distcheck/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/distcheck/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/distcheck/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/distcheck/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-distcheck', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/install/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/install/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/install/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/install/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-install', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/meson.build" 2020-01-07 21:08:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -project('reserved target names', 'c') - # FIXME: Setting this causes it to leak to all other tests - #default_options : ['b_coverage=true'] - -subdir('all') -subdir('benchmark') -subdir('clean') -subdir('clean-ctlist') -subdir('clean-gcda') -subdir('clean-gcno') -subdir('coverage') -subdir('coverage-html') -subdir('coverage-text') -subdir('coverage-xml') -subdir('dist') -subdir('distcheck') -subdir('install') -# We don't have a 'PHONY' directory because Windows and OSX -# choke horribly when there are two entries with the same -# name but different case. -subdir('phony') -subdir('reconfigure') -subdir('scan-build') -subdir('test') -subdir('uninstall') - -subdir('runtarget') - -py3 = import('python3').find_python() - -custom_target('ctlist-test', output : 'out.txt', - command : [py3, '-c', 'print("")'], - capture : true, - build_by_default : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/phony/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/phony/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/phony/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/phony/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-phony', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/reconfigure/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/reconfigure/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/reconfigure/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/reconfigure/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-reconfigure', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/runtarget/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/runtarget/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/runtarget/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/runtarget/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -configure_file(output : 'config.h', configuration: configuration_data()) -run_target('runtarget', command : ['echo']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/scan-build/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/scan-build/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/scan-build/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/scan-build/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-scan-build', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/test/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/test/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/test/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/test/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-test', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/test.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/test.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/uninstall/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/uninstall/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/154 reserved targets/uninstall/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/154 reserved targets/uninstall/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -executable('test-uninstall', '../test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir1/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir1/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir1/file.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir1/file.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -extern int dir2; -extern int dir2_dir1; -extern int dir3; -extern int dir3_dir1; - -int main(void) { - if (dir2 != 20) - return 1; - if (dir2_dir1 != 21) - return 1; - if (dir3 != 30) - return 1; - if (dir3_dir1 != 31) - return 1; - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -sources += files('file.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir2/dir1/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir2/dir1/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir2/dir1/file.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir2/dir1/file.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int dir2_dir1 = 21; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir2/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir2/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir2/file.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir2/file.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int dir2 = 20; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir2/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -sources += files('file.c', 'dir1/file.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir3/dir1/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir3/dir1/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir3/dir1/file.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir3/dir1/file.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int dir3_dir1 = 31; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir3/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir3/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir3/file.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir3/file.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int dir3 = 30; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/dir3/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/dir3/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -lib = static_library('lib', 'file.c', 'dir1/file.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 duplicate source names/meson.build" 2020-01-07 21:08:48.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 duplicate source names/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('proj', 'c') - -sources = [] -subdir('dir1') -subdir('dir2') -subdir('dir3') -executable('a.out', sources : sources, objects : lib.extract_all_objects()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/a.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include +char func_b(void); +char func_c(void); + +int main(void) { + if(func_b() != 'b') { + return 1; + } + if(func_c() != 'c') { + return 2; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/B/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/B/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/B/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/B/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +#include +char func_c(void); + +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +char DLL_PUBLIC func_b(void) { + if(func_c() != 'c') { + exit(3); + } + return 'b'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/B/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/B/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/B/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/B/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('B', 'c') +C = subproject('C') +c = C.get_variable('c') +b = library('b', 'b.c', link_with : c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/C/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/C/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/C/c.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/C/c.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +char DLL_PUBLIC func_c(void) { + return 'c'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/C/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/C/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/C/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/custom_subproject_dir/C/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('C', 'c') +c = library('c', 'c.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/meson.build" 2021-10-23 16:49:43.000000000 +0000 @@ -0,0 +1,12 @@ +project('A', 'c', subproject_dir:'custom_subproject_dir') + +B = subproject('B') +b = B.get_variable('b') + +C = subproject('C') +c = C.get_variable('c') + +subdir('other_subdir') + +a = executable('a', 'a.c', link_with : [b, c]) +test('a test', a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/other_subdir/custom_subproject_dir/other.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/other_subdir/custom_subproject_dir/other.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/other_subdir/custom_subproject_dir/other.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/other_subdir/custom_subproject_dir/other.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +#include + +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +char DLL_PUBLIC func_b(void) { + if('c' != 'c') { + exit(3); + } + return 'b'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/other_subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/other_subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/155 subproject dir name collision/other_subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/155 subproject dir name collision/other_subdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +other = library('other', 'custom_subproject_dir/other.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 config tool variable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 config tool variable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 config tool variable/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 config tool variable/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,31 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +project('config tool variable', 'cpp') + + +dep_llvm = dependency('llvm', method : 'config-tool', required : false) +if not dep_llvm.found() + error('MESON_SKIP_TEST LLVM not installed.') +endif + +includedir = dep_llvm.get_configtool_variable('includedir') +includedir = join_paths(includedir, 'llvm') +if host_machine.system() == 'windows' + cmd = run_command(['dir', includedir], check: false) +else + cmd = run_command(['ls', includedir], check: false) +endif + +assert(cmd.returncode() == 0, 'did not run successfully') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/check_args.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/check_args.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/check_args.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/check_args.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!python3 - -import sys -from pathlib import Path - -def main(): - if len(sys.argv) != 2: - print(sys.argv) - return 1 - if sys.argv[1] != 'gen.c': - print(sys.argv) - return 2 - Path('foo').touch() - - return 0 - -if __name__ == '__main__': - sys.exit(main()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/gen_sources.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/gen_sources.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/gen_sources.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/gen_sources.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -# Copyright © 2017 Intel Corporation -# -# 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 argparse -import textwrap - -HEADER = textwrap.dedent('''\ - void stringify(int foo, char * buffer); - ''') - -CODE = textwrap.dedent('''\ - #include - - #ifndef WORKS - # error "This shouldn't have been included" - #endif - - void stringify(int foo, char * buffer) { - sprintf(buffer, "%i", foo); - } - ''') - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--header') - parser.add_argument('--code') - args = parser.parse_args() - - with open(args.header, 'w') as f: - f.write(HEADER) - - with open(args.code, 'w') as f: - f.write(CODE) - - -if __name__ == '__main__': - main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/lib.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -/* Copyright © 2017 Intel Corporation - * - * 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. - */ - -#include "gen.h" - -void func(char * buffer) { - stringify(1, buffer); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/meson.build" 2020-01-07 21:08:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -# Copyright © 2017 Intel Corporation -# -# 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. - -project('custom_target_index', 'c', default_options : 'c_std=c89') - -py_mod = import('python3') -prog_python = py_mod.find_python() - -gen = custom_target( - 'gen.[ch]', - input : 'gen_sources.py', - output : ['gen.c', 'gen.h'], - command : [prog_python, '@INPUT@', '--header', '@OUTPUT1@', '--code', '@OUTPUT0@'], -) - -has_not_changed = false -if is_disabler(gen) - has_not_changed = true -else - has_not_changed = true -endif - -assert(has_not_changed, 'Custom target has changed.') - -assert(not is_disabler(gen), 'Custom target is a disabler.') - -lib = static_library( - 'libfoo', - ['lib.c', gen[1]], -) - -has_not_changed = false -if is_disabler(lib) - has_not_changed = true -else - has_not_changed = true -endif - -assert(has_not_changed, 'Static library has changed.') - -assert(not is_disabler(lib), 'Static library is a disabler.') - -custom_target( - 'foo', - input: gen[0], - output: 'foo', - command: [find_program('check_args.py'), '@INPUT@'], -) - -subdir('subdir') - -gen = disabler() - -assert(is_disabler(gen), 'Generator is not a disabler.') - -lib = static_library( - 'libfoo', - ['lib.c', gen[1]], -) - -assert(is_disabler(lib), 'Static library is not a disabler.') - -if lib.found() - lib_disabled = false -else - lib_disabled = true -endif - -assert(lib_disabled, 'Static library was not disabled.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/subdir/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/subdir/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/subdir/foo.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/subdir/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -/* Copyright © 2017 Intel Corporation - * - * 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. - */ - -#include "gen.h" - -int main(void) { - char buf[50]; - stringify(10, buf); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/156 index customtarget/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/156 index customtarget/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# Copyright © 2017 Intel Corporation -# -# 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. - -foo = executable( - 'foo', - ['foo.c', gen[0], gen[1]], - c_args : '-DWORKS', -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/copyfile.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/meson.build" 2021-10-23 16:49:42.000000000 +0000 @@ -0,0 +1,7 @@ +project('custom target subdir depend files', 'c') + +copy = find_program('copyfile.py') + +subdir('subdir') + +executable('foo', foo_src) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/subdir/dep.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/subdir/dep.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/subdir/dep.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/subdir/dep.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +You can depend on this file. \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/subdir/foo.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/subdir/foo.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/subdir/foo.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/subdir/foo.c.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("foo is working.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 custom target subdir depend files/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 custom target subdir depend files/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +foo_src = custom_target('foo_src', + depend_files : 'dep.dat', + input : 'foo.c.in', + output : 'foo.c', + command : [copy, '@INPUT@', '@OUTPUT@'] +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/meson.build" 2020-01-07 21:08:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('mainproj', 'c', - default_options : ['wrap_mode=nodownload'], -) - -subproject('zlib') -subproject('foo') - -executable('grabprog', files('src/subprojects/prog.c')) -executable('grabprog2', files('src/subprojects/foo/prog2.c')) -subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/src/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -executable('grabprog3', files('subprojects/prog.c')) -executable('grabprog4', files('subprojects/foo/prog2.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/src/subprojects/foo/prog2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/src/subprojects/foo/prog2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/src/subprojects/foo/prog2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/src/subprojects/foo/prog2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include - -int main(void) { - printf("Do not have a file layout like this in your own projects.\n"); - printf("This is only to test that this works.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/src/subprojects/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/src/subprojects/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/src/subprojects/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/src/subprojects/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include - -int main(void) { - printf("Do not have a file layout like this in your own projects.\n"); - printf("This is only to test that this works.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/foo-1.0/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/foo-1.0/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/foo-1.0/foo.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/foo-1.0/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int dummy_func(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/foo-1.0/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/foo-1.0/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/foo-1.0/meson.build" 2019-10-06 17:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/foo-1.0/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('shared lib', 'c') -libfoo = shared_library('foo', 'foo.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/foo.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/foo.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/foo.wrap" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/foo.wrap" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -[wrap-file] -directory = foo-1.0 - -source_url = http://something.invalid -source_filename = foo-1.0.tar.xz -source_hash = ae5fc03185654f76b459db16ca25809703f8821aeb39a433902244bb479c4b79 -lead_directory_missing = true - -patch_url = https://something.invalid/patch -patch_filename = foo-1.0-patch.tar.xz -patch_hash = 8f2e286a4b190228d4e0c25ddc91195449cfb5e5c52006355838964b244037da Binary files /tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/foo-1.0-patch.tar.xz and /tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/foo-1.0-patch.tar.xz differ Binary files /tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/foo-1.0.tar.xz and /tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/foo-1.0.tar.xz differ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -dummy diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -dummy diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/foo.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int dummy_func(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/zlib-1.2.8/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('shared lib', 'c') -shared_library('foo', 'foo.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/zlib.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/zlib.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/157 wrap file should not failed/subprojects/zlib.wrap" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/157 wrap file should not failed/subprojects/zlib.wrap" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -[wrap-file] -directory = zlib-1.2.8 - -source_url = http://zlib.net/fossils/zlib-1.2.8.tar.gz -source_filename = zlib-1.2.8.tar.gz -source_hash = 36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d - -patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/8/get_zip -patch_filename = zlib-1.2.8-8-wrap.zip -patch_hash = 17c52a0e0c59ce926d3959005d5cd8178c6c7e2c9a4a1304279a8320c955ac60 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 disabler/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 disabler/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 disabler/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 disabler/meson.build" 2021-10-23 16:49:45.000000000 +0000 @@ -0,0 +1,153 @@ +project('dolphin option', 'c') + +d = disabler() + +full_path = d.full_path() +assert(is_disabler(full_path), 'Method call is not a disabler') + +d2 = dependency(d) +d3 = (d == d2) +d4 = d + 0 +d5 = d2 or true +set_variable('d6', disabler()) + +has_not_changed = false +if is_disabler(d) + has_not_changed = true +else + has_not_changed = true +endif +assert(has_not_changed, 'Disabler has changed.') + +assert(is_disabler(d), 'Disabler was not identified correctly.') +assert(is_disabler(d2), 'Function laundered disabler was not identified correctly.') +assert(is_disabler(d3), 'Disabler comparison should yield disabler.') +assert(is_disabler(d4), 'Disabler addition should yield disabler.') +assert(is_disabler(d5), 'Disabler logic op should yield disabler.') +assert(is_disabler(d6), 'set_variable with a disabler should set variable to disabler.') + +assert(d, 'Disabler did not cause this to be skipped.') +assert(d2, 'Function laundered disabler did not cause this to be skipped.') +assert(d3, 'Disabler comparison should yield disabler and thus this would not be called.') +assert(d4, 'Disabler addition should yield disabler and thus this would not be called.') +assert(d5, 'Disabler logic op should yield disabler and thus this would not be called.') +assert(d6, 'set_variable with a disabler did not cause this to be skipped.') + +number = 0 + +if d + number = 1 +else + number = 2 +endif + +has_not_changed = false +if is_disabler(number) + has_not_changed = true +else + has_not_changed = true +endif +assert(has_not_changed, 'Number has changed.') + +assert(not is_disabler(number), 'Number should not be a disabler.') +assert(number == 0, 'Plain if handled incorrectly, value should be 0 but is @0@'.format(number)) + +if d.found() + number = 1 +else + number = 2 +endif + +assert(number == 2, 'If found handled incorrectly, value should be 2 but is @0@'.format(number)) + +dep = dependency('notfounddep', required : false, disabler : true) +app = executable('myapp', 'notfound.c', dependencies : [dep]) +assert(is_disabler(app), 'App is not a disabler.') +app = executable('myapp', 'notfound.c', dependencies : [[dep]]) +assert(is_disabler(app), 'App is not a disabler.') + +cc = meson.get_compiler('c') +dep = cc.find_library('notfounddep', required : false, disabler : true) +app = executable('myapp', 'notfound.c', dependencies : [dep]) +assert(is_disabler(app), 'App is not a disabler.') + +dep = find_program('donotfindme', required : false, disabler : true) +app = executable('myapp', 'notfound.c', dependencies : [dep]) +assert(is_disabler(app), 'App is not a disabler.') + +has_not_changed = false +if is_disabler(app) + has_not_changed = true +else + has_not_changed = true +endif +assert(has_not_changed, 'App has changed.') + +assert(not is_disabler(is_variable('d6')), 'is_variable should not return a disabler') +assert(is_variable('d6'), 'is_variable for a disabler should return true') + +if_is_not_disabled = false +if is_variable('d6') + if_is_not_disabled = true +else + if_is_not_disabled = true +endif +assert(if_is_not_disabled, 'Disabler in is_variable should not skip blocks') + +get_d = get_variable('d6') +assert(is_disabler(get_d), 'get_variable should yield a disabler') + +get_fallback_d = get_variable('nonexistant', disabler()) +assert(is_disabler(get_fallback_d), 'get_variable fallback should yield a disabler') + +var_true = true +get_no_fallback_d = get_variable('var_true', disabler()) +assert(not is_disabler(get_no_fallback_d), 'get_variable should not fallback to disabler') +assert(get_no_fallback_d, 'get_variable should yield true') + +assert(is_disabler(get_variable(disabler())), 'get_variable should yield a disabler') +assert(is_disabler(get_variable(disabler(), var_true)), 'get_variable should yield a disabler') + +if_is_disabled = true +if disabler() + if_is_disabled = false +else + if_is_disabled = false +endif +assert(if_is_disabled, 'Disabler in "if condition" must skip both blocks') + +if not disabler() + if_is_disabled = false +else + if_is_disabled = false +endif +assert(if_is_disabled, 'Disabler in "if not condition" must skip both blocks') + +if disabler() == 1 + if_is_disabled = false +else + if_is_disabled = false +endif +assert(if_is_disabled, 'Disabler in "if a==b" must skip both blocks') + +loops = 0 +disablers = 0 +foreach i : [true, disabler(), true] + loops += 1 + if is_disabler(i) + disablers += 1 + endif +endforeach +assert(loops == 3, 'Disabler in foreach array') +assert(disablers == 1, 'Disabler in foreach array') + +loops = 0 +disablers = 0 +foreach k, i : {'a': true, 'b': disabler(), 'c': true} + loops += 1 + if is_disabler(i) + disablers += 1 + endif +endforeach +assert(loops == 3, 'Disabler in foreach dict') +assert(disablers == 1, 'Disabler in foreach dict') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 includedir subproj/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 includedir subproj/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 includedir subproj/meson.build" 2020-01-07 21:08:52.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 includedir subproj/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('include dir in subproj test', 'c') - - -subproject('inctest') - - -exe = executable('prog', 'prog.c') - -test('dummy', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 includedir subproj/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 includedir subproj/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 includedir subproj/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 includedir subproj/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 includedir subproj/subprojects/inctest/include/incfile.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 includedir subproj/subprojects/inctest/include/incfile.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 includedir subproj/subprojects/inctest/include/incfile.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 includedir subproj/subprojects/inctest/include/incfile.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ - -/* file which is used in the subproject */ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 includedir subproj/subprojects/inctest/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 includedir subproj/subprojects/inctest/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/158 includedir subproj/subprojects/inctest/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/158 includedir subproj/subprojects/inctest/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -project('subproj with includedir', 'c') - - - -compile_check = ''' -#include "incfile.h" -''' - -if not meson.get_compiler('c').compiles(compile_check, name : 'include in subproj', - include_directories: include_directories('include')) - error('failed') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 array option/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 array option/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 array option/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 array option/meson.build" 2021-10-23 16:49:42.000000000 +0000 @@ -0,0 +1,17 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +project('array default options') + +assert(get_option('array') == ['foo', 'bar'], 'Default value for array is not equal to choices') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 array option/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 array option/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 array option/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 array option/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +option( + 'array', + type : 'array', + choices : ['foo', 'bar'], +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/a.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include -char func_b(void); -char func_c(void); - -int main(void) { - if(func_b() != 'b') { - return 1; - } - if(func_c() != 'c') { - return 2; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/B/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/B/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/B/b.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/B/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#include -char func_c(void); - -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -char DLL_PUBLIC func_b(void) { - if(func_c() != 'c') { - exit(3); - } - return 'b'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/B/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/B/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/B/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/B/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('B', 'c') -C = subproject('C') -c = C.get_variable('c') -b = shared_library('b', 'b.c', link_with : c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/C/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/C/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/C/c.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/C/c.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -char DLL_PUBLIC func_c(void) { - return 'c'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/C/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/C/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/C/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/custom_subproject_dir/C/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('C', 'c') -c = shared_library('c', 'c.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/meson.build" 2020-01-07 21:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -project('A', 'c', subproject_dir:'custom_subproject_dir') - -B = subproject('B') -b = B.get_variable('b') - -C = subproject('C') -c = C.get_variable('c') - -subdir('other_subdir') - -a = executable('a', 'a.c', link_with : [b, c]) -test('a test', a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/other_subdir/custom_subproject_dir/other.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/other_subdir/custom_subproject_dir/other.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/other_subdir/custom_subproject_dir/other.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/other_subdir/custom_subproject_dir/other.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -#include - -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -char DLL_PUBLIC func_b(void) { - if('c' != 'c') { - exit(3); - } - return 'b'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/other_subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/other_subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/159 subproject dir name collision/other_subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/159 subproject dir name collision/other_subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -other = shared_library('other', 'custom_subproject_dir/other.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/15 if/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/15 if/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/15 if/meson.build" 2020-01-07 21:06:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/15 if/meson.build" 2021-10-23 16:47:54.000000000 +0000 @@ -58,3 +58,15 @@ else message('Ok') endif + +# Test plain else + +var = false + +if var + exe = executable('break', 'break.c') +else + exe = executable('eprog', 'prog.c') +endif + +test('elsetest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/160 config tool variable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/160 config tool variable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/160 config tool variable/meson.build" 2020-01-07 21:08:54.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/160 config tool variable/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -# Copyright © 2017 Intel Corporation -# -# 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. - -project('config tool variable', 'cpp') - - -dep_llvm = dependency('llvm', method : 'config-tool', required : false) -if not dep_llvm.found() - error('MESON_SKIP_TEST LLVM not installed.') -endif - -includedir = dep_llvm.get_configtool_variable('includedir') -includedir = join_paths(includedir, 'llvm') -if host_machine.system() == 'windows' - cmd = run_command(['dir', includedir]) -else - cmd = run_command(['ls', includedir]) -endif - -assert(cmd.returncode() == 0, 'did not run successfully') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/160 custom target template substitution/checkcopy.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/160 custom target template substitution/checkcopy.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/160 custom target template substitution/checkcopy.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/160 custom target template substitution/checkcopy.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +if '@INPUT1@' in sys.argv[1]: + shutil.copyfile(sys.argv[2], sys.argv[3]) +else: + sys.exit('String @INPUT1@ not found in "{}"'.format(sys.argv[1])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/160 custom target template substitution/foo.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/160 custom target template substitution/foo.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/160 custom target template substitution/foo.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/160 custom target template substitution/foo.c.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("foo is working.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/160 custom target template substitution/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/160 custom target template substitution/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/160 custom target template substitution/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/160 custom target template substitution/meson.build" 2021-10-23 16:49:44.000000000 +0000 @@ -0,0 +1,17 @@ +project('custom target template substitution', 'c') + +check = find_program('checkcopy.py') + +config = configuration_data() + +config_file = configure_file(configuration : config, output : 'x@IN') + +# Check that substitution does not find @FOO@ and then misses @INPUT0@. +# Check the resulting x@INPUT1@ is not replaced. +foo = custom_target('runcheck', + input : [config_file, 'foo.c.in'], + output : 'foo.c', + command : [check, '-D@FOO@INPUT0@PUT1@', '@INPUT1@', '@OUTPUT@'] +) + +executable('foo', foo) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/copyfile.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import shutil - -shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/meson.build" 2020-01-07 21:08:54.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('custom target subdir depend files', 'c') - -copy = find_program('copyfile.py') - -subdir('subdir') - -executable('foo', foo_src) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/subdir/dep.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/subdir/dep.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/subdir/dep.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/subdir/dep.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -You can depend on this file. \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/subdir/foo.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/subdir/foo.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/subdir/foo.c.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/subdir/foo.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("foo is working.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 custom target subdir depend files/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 custom target subdir depend files/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -foo_src = custom_target('foo_src', - depend_files : 'dep.dat', - input : 'foo.c.in', - output : 'foo.c', - command : [copy, '@INPUT@', '@OUTPUT@'] -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 not-found dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 not-found dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 not-found dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 not-found dependency/meson.build" 2021-10-23 16:49:45.000000000 +0000 @@ -0,0 +1,14 @@ +project('dep-test', 'c') + +dep = dependency('', required:false) +if dep.found() + error('not-found dependency was found') +endif + +assert(dep.type_name() == 'not-found', 'dependency should be of type "not-found" not ' + dep.type_name()) + +library('testlib', 'testlib.c', dependencies: [dep]) +subdir('sub', if_found: dep) + +subdep = dependency('', fallback: ['trivial', 'trivial_dep']) +missing = dependency('', fallback: ['missing', 'missing_dep'], required: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 not-found dependency/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 not-found dependency/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 not-found dependency/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 not-found dependency/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +error('should be disabled by subdir(if_found:)') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 not-found dependency/subprojects/trivial/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 not-found dependency/subprojects/trivial/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 not-found dependency/subprojects/trivial/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 not-found dependency/subprojects/trivial/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('trivial subproject', 'c') +trivial_lib = static_library('trivial', 'trivial.c', install: false) +trivial_dep = declare_dependency(link_with: trivial_lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 not-found dependency/subprojects/trivial/trivial.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 not-found dependency/subprojects/trivial/trivial.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/161 not-found dependency/subprojects/trivial/trivial.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/161 not-found dependency/subprojects/trivial/trivial.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int subfunc(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 external program shebang parsing/input.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 external program shebang parsing/input.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 external program shebang parsing/input.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 external program shebang parsing/input.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -some stuff here diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 external program shebang parsing/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 external program shebang parsing/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 external program shebang parsing/main.c" 2019-09-16 21:20:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 external program shebang parsing/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 - #include - #include -#else - #include -#endif - -/* Who cares about stack sizes in test programs anyway */ -#define LINE_LENGTH 4096 - -static int -intrp_copyfile (char * src, char * dest) -{ -#ifdef _WIN32 - if (!CopyFile (src, dest, FALSE)) - return 1; - return 0; -#else - return execlp ("cp", "cp", src, dest, NULL); -#endif -} - -static void -parser_get_line (FILE * f, char line[LINE_LENGTH]) -{ - if (!fgets (line, LINE_LENGTH, f)) - fprintf (stderr, "%s\n", strerror (errno)); -} - -int -main (int argc, char * argv[]) -{ - FILE *f = NULL; - char line[LINE_LENGTH]; - - if (argc != 4) { - fprintf (stderr, "Invalid number of arguments: %i\n", argc); - goto err; - } - - if ((f = fopen (argv[1], "r")) == NULL) { - fprintf (stderr, "%s\n", strerror (errno)); - goto err; - } - - parser_get_line (f, line); - - if (!line || line[0] != '#' || line[1] != '!') { - fprintf (stderr, "Invalid script\n"); - goto err; - } - - parser_get_line (f, line); - - if (!line || strncmp (line, "copy", 4) != 0) { - fprintf (stderr, "Syntax error: %s\n", line); - goto err; - } - - return intrp_copyfile (argv[2], argv[3]); - -err: - fclose (f); - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 external program shebang parsing/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 external program shebang parsing/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 external program shebang parsing/meson.build" 2020-01-07 21:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 external program shebang parsing/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -project('shebang parsing', 'c') - -interpreter = executable('aninterp', 'main.c', native : true) - -cdata = configuration_data() -cdata.set('INTRP', interpreter.full_path()) - -f = configure_file(input : 'script.int.in', - output : 'script.int', - configuration : cdata) - -# Test that parsing a shebang with spaces works properly. See `man execve`, -# specifically the section on "Interpreter scripts" and the one under "NOTES". -script = find_program(f) - -custom_target('interpthis', - input : 'input.txt', - output : 'output.txt', - depends : interpreter, - command : [script, '@INPUT@', '@OUTPUT@'], - build_by_default : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 external program shebang parsing/script.int.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 external program shebang parsing/script.int.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 external program shebang parsing/script.int.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 external program shebang parsing/script.int.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -#!/usr/bin/env @INTRP@ -copy diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 subdir if_found/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 subdir if_found/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 subdir if_found/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 subdir if_found/meson.build" 2021-10-23 16:49:46.000000000 +0000 @@ -0,0 +1,11 @@ +project('subdir if found', 'c') + +found_dep = declare_dependency() +not_found_dep = dependency('nonexisting', required : false) + +subdir('nonexisting_dir', if_found : not_found_dep) + +variable = 3 + +subdir('subdir', if_found : found_dep) +assert(variable == 5, 'Subdir was not properly entered.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 subdir if_found/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 subdir if_found/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/162 subdir if_found/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/162 subdir if_found/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +variable = 5 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/163 default options prefix dependent defaults/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/163 default options prefix dependent defaults/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/163 default options prefix dependent defaults/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/163 default options prefix dependent defaults/meson.build" 2021-10-23 16:49:46.000000000 +0000 @@ -0,0 +1 @@ +project('default options prefix dependent defaults ', 'c', default_options : ['sharedstatedir=/sharedstate', 'prefix=/usr']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/163 disabler/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/163 disabler/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/163 disabler/meson.build" 2020-01-07 21:08:58.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/163 disabler/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,125 +0,0 @@ -project('dolphin option', 'c') - -d = disabler() - -full_path = d.full_path() -assert(is_disabler(full_path), 'Method call is not a disabler') - -d2 = dependency(d) -d3 = (d == d2) -d4 = d + 0 -d5 = d2 or true - -has_not_changed = false -if is_disabler(d) - has_not_changed = true -else - has_not_changed = true -endif -assert(has_not_changed, 'Disabler has changed.') - -assert(is_disabler(d), 'Disabler was not identified correctly.') -assert(is_disabler(d2), 'Function laundered disabler was not identified correctly.') -assert(is_disabler(d3), 'Disabler comparison should yield disabler.') -assert(is_disabler(d4), 'Disabler addition should yield disabler.') -assert(is_disabler(d5), 'Disabler logic op should yield disabler.') - -assert(d, 'Disabler did not cause this to be skipped.') -assert(d2, 'Function laundered disabler did not cause this to be skipped.') -assert(d3, 'Disabler comparison should yield disabler and thus this would not be called.') -assert(d4, 'Disabler addition should yield disabler and thus this would not be called.') -assert(d5, 'Disabler logic op should yield disabler and thus this would not be called.') - -number = 0 - -if d - number = 1 -else - number = 2 -endif - -has_not_changed = false -if is_disabler(number) - has_not_changed = true -else - has_not_changed = true -endif -assert(has_not_changed, 'Number has changed.') - -assert(not is_disabler(number), 'Number should not be a disabler.') -assert(number == 0, 'Plain if handled incorrectly, value should be 0 but is @0@'.format(number)) - -if d.found() - number = 1 -else - number = 2 -endif - -assert(number == 2, 'If found handled incorrectly, value should be 2 but is @0@'.format(number)) - -dep = dependency('notfounddep', required : false, disabler : true) -app = executable('myapp', 'notfound.c', dependencies : [dep]) -assert(is_disabler(app), 'App is not a disabler.') -app = executable('myapp', 'notfound.c', dependencies : [[dep]]) -assert(is_disabler(app), 'App is not a disabler.') - -cc = meson.get_compiler('c') -dep = cc.find_library('notfounddep', required : false, disabler : true) -app = executable('myapp', 'notfound.c', dependencies : [dep]) -assert(is_disabler(app), 'App is not a disabler.') - -dep = find_program('donotfindme', required : false, disabler : true) -app = executable('myapp', 'notfound.c', dependencies : [dep]) -assert(is_disabler(app), 'App is not a disabler.') - -has_not_changed = false -if is_disabler(app) - has_not_changed = true -else - has_not_changed = true -endif -assert(has_not_changed, 'App has changed.') - -if_is_disabled = true -if disabler() - if_is_disabled = false -else - if_is_disabled = false -endif -assert(if_is_disabled, 'Disabler in "if condition" must skip both blocks') - -if not disabler() - if_is_disabled = false -else - if_is_disabled = false -endif -assert(if_is_disabled, 'Disabler in "if not condition" must skip both blocks') - -if disabler() == 1 - if_is_disabled = false -else - if_is_disabled = false -endif -assert(if_is_disabled, 'Disabler in "if a==b" must skip both blocks') - -loops = 0 -disablers = 0 -foreach i : [true, disabler(), true] - loops += 1 - if is_disabler(i) - disablers += 1 - endif -endforeach -assert(loops == 3, 'Disabler in foreach array') -assert(disablers == 1, 'Disabler in foreach array') - -loops = 0 -disablers = 0 -foreach k, i : {'a': true, 'b': disabler(), 'c': true} - loops += 1 - if is_disabler(i) - disablers += 1 - endif -endforeach -assert(loops == 3, 'Disabler in foreach dict') -assert(disablers == 1, 'Disabler in foreach dict') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/164 array option/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/164 array option/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/164 array option/meson.build" 2020-01-07 21:08:56.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/164 array option/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -# Copyright © 2017 Intel Corporation -# -# 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. - -project('array default options') - -assert(get_option('array') == ['foo', 'bar'], 'Default value for array is not equal to choices') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/164 array option/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/164 array option/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/164 array option/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/164 array option/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# Copyright © 2017 Intel Corporation -# -# 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. - -option( - 'array', - type : 'array', - choices : ['foo', 'bar'], -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/164 dependency factory/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/164 dependency factory/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/164 dependency factory/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/164 dependency factory/meson.build" 2021-10-23 16:49:49.000000000 +0000 @@ -0,0 +1,66 @@ +project('dependency factory', 'c', meson_version : '>=0.53') + +dep = dependency('gl', method: 'pkg-config', required: false) +if dep.found() + assert(dep.type_name() == 'pkgconfig') + dep.get_pkgconfig_variable('prefix') +endif + +dep = dependency('SDL2', method: 'pkg-config', required: false) +if dep.found() + assert(dep.type_name() == 'pkgconfig') + dep.get_pkgconfig_variable('prefix') +endif + +dep = dependency('SDL2', method: 'config-tool', required: false) +if dep.found() + assert(dep.type_name() == 'config-tool') + dep.get_configtool_variable('prefix') +endif + +dep = dependency('Vulkan', method: 'pkg-config', required: false) +if dep.found() + assert(dep.type_name() == 'pkgconfig') + dep.get_pkgconfig_variable('prefix') +endif + +dep = dependency('pcap', method: 'pkg-config', required: false) +if dep.found() + assert(dep.type_name() == 'pkgconfig') + dep.get_pkgconfig_variable('prefix') +endif + +dep = dependency('pcap', method: 'config-tool', required: false) +if dep.found() + assert(dep.type_name() == 'config-tool') + dep.get_configtool_variable('prefix') +endif + +dep = dependency('cups', method: 'pkg-config', required: false) +if dep.found() + assert(dep.type_name() == 'pkgconfig') + dep.get_pkgconfig_variable('prefix') +endif + +dep = dependency('cups', method: 'config-tool', required: false) +if dep.found() + assert(dep.type_name() == 'config-tool') + dep.get_configtool_variable('prefix') +endif + +dep = dependency('libwmf', method: 'pkg-config', required: false) +if dep.found() + assert(dep.type_name() == 'pkgconfig') + dep.get_pkgconfig_variable('prefix') +endif + +dep = dependency('libwmf', method: 'config-tool', required: false) +if dep.found() + assert(dep.type_name() == 'config-tool') + dep.get_configtool_variable('prefix') +endif + +dep = dependency('boost', method: 'system', required: false) +if dep.found() + assert(dep.type_name() == 'system') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 custom target template substitution/checkcopy.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 custom target template substitution/checkcopy.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 custom target template substitution/checkcopy.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 custom target template substitution/checkcopy.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import shutil - -if '@INPUT1@' in sys.argv[1]: - shutil.copyfile(sys.argv[2], sys.argv[3]) -else: - sys.exit('String @INPUT1@ not found in "{}"'.format(sys.argv[1])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 custom target template substitution/foo.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 custom target template substitution/foo.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 custom target template substitution/foo.c.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 custom target template substitution/foo.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("foo is working.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 custom target template substitution/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 custom target template substitution/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 custom target template substitution/meson.build" 2020-01-07 21:08:58.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 custom target template substitution/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -project('custom target template substitution', 'c') - -check = find_program('checkcopy.py') - -config = configuration_data() - -config_file = configure_file(configuration : config, output : 'x@IN') - -# Check that substitution does not find @FOO@ and then misses @INPUT0@. -# Check the resulting x@INPUT1@ is not replaced. -foo = custom_target('runcheck', - input : [config_file, 'foo.c.in'], - output : 'foo.c', - command : [check, '-D@FOO@INPUT0@PUT1@', '@INPUT1@', '@OUTPUT@'] -) - -executable('foo', foo) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 get project license/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 get project license/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 get project license/bar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 get project license/bar.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I'm a main project bar.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 get project license/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 get project license/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/165 get project license/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/165 get project license/meson.build" 2021-10-23 16:49:47.000000000 +0000 @@ -0,0 +1,8 @@ +project('bar', 'c', license: 'Apache-2.0') + +executable('bar', 'bar.c') + +license = meson.project_license()[0] +if license != 'Apache-2.0' + error('The license should be Apache-2.0, but it is: ' + license) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 not-found dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 not-found dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 not-found dependency/meson.build" 2020-01-07 21:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 not-found dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('dep-test', 'c') - -dep = dependency('', required:false) -if dep.found() - error('not-found dependency was found') -endif - -assert(dep.type_name() == 'not-found', 'dependency should be of type "not-found" not ' + dep.type_name()) - -library('testlib', 'testlib.c', dependencies: [dep]) -subdir('sub', if_found: dep) - -subdep = dependency('', fallback: ['trivial', 'trivial_dep']) -missing = dependency('', fallback: ['missing', 'missing_dep'], required: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 not-found dependency/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 not-found dependency/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 not-found dependency/sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 not-found dependency/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -error('should be disabled by subdir(if_found:)') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 not-found dependency/subprojects/trivial/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 not-found dependency/subprojects/trivial/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 not-found dependency/subprojects/trivial/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 not-found dependency/subprojects/trivial/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('trivial subproject', 'c') -trivial_lib = static_library('trivial', 'trivial.c', install: false) -trivial_dep = declare_dependency(link_with: trivial_lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 not-found dependency/subprojects/trivial/trivial.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 not-found dependency/subprojects/trivial/trivial.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 not-found dependency/subprojects/trivial/trivial.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 not-found dependency/subprojects/trivial/trivial.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int subfunc(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 yield/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 yield/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 yield/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 yield/meson.build" 2021-10-23 16:49:47.000000000 +0000 @@ -0,0 +1,7 @@ +project('yield_options', 'c') + +subproject('sub') + +assert(get_option('unshared_option') == 'one', 'Unshared option has wrong value in superproject.') +assert(get_option('shared_option') == 'two', 'Shared option has wrong value in superproject..') +assert(get_option('wrongtype_option') == 'three', 'Wrongtype option has wrong value in superproject..') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 yield/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 yield/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 yield/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 yield/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +option('unshared_option', type : 'string', value : 'one') +option('shared_option', type : 'string', value : 'two') +option('wrongtype_option', type : 'string', value : 'three') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 yield/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 yield/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 yield/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 yield/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +project('subbie', 'c') + +assert(get_option('unshared_option') == 'three', 'Unshared option has wrong value in subproject.') +assert(get_option('shared_option') == 'two', 'Shared option has wrong value in subproject.') +assert(get_option('wrongtype_option') == true, 'Wrongtype option has wrong value in subproject.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 yield/subprojects/sub/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 yield/subprojects/sub/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/166 yield/subprojects/sub/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/166 yield/subprojects/sub/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +option('unshared_option', type : 'string', value : 'three', yield : false) +option('shared_option', type : 'string', value : 'four', yield : true) +option('wrongtype_option', type : 'boolean', value : true, yield : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subdir if_found/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subdir if_found/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subdir if_found/meson.build" 2020-01-07 21:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subdir if_found/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('subdir if found', 'c') - -found_dep = declare_dependency() -not_found_dep = dependency('nonexisting', required : false) - -subdir('nonexisting_dir', if_found : not_found_dep) - -variable = 3 - -subdir('subdir', if_found : found_dep) -assert(variable == 5, 'Subdir was not properly entered.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subdir if_found/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subdir if_found/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subdir if_found/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subdir if_found/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -variable = 5 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/a.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,14 @@ +int func2(void); + +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC func(void) { return func2(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('alpha project', 'c', subproject_dir: 'var/subprojects') + +b = subproject('beta') +l = library('a', 'a.c', link_with : b.get_variable('lb')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC func2(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('beta project', 'c') + +lb = shared_library('b', 'b.c') +notfound = dependency('', required : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/meson.build" 2021-10-23 16:49:52.000000000 +0000 @@ -0,0 +1,11 @@ +project('gamma project', 'c', subproject_dir: 'contrib/subprojects') + +a = subproject('alpha') +lib = a.get_variable('l') + +# Ensure that the dependency version is not checked for a not-found dependency +notfound = dependency('', version : '>=1.0', required : false, + fallback : ['beta', 'notfound']) + +exe = executable('prog', 'prog.c', link_with : lib) +test('basic', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/167 subproject nested subproject dirs/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/167 subproject nested subproject dirs/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int func(void); + +int main(void) { + return func() == 42 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 default options prefix dependent defaults/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 default options prefix dependent defaults/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 default options prefix dependent defaults/meson.build" 2020-01-07 21:09:01.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 default options prefix dependent defaults/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -project('default options prefix dependent defaults ', 'c', default_options : ['sharedstatedir=/sharedstate', 'prefix=/usr']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/base.inp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/base.inp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/base.inp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/base.inp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +base diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/com/mesonbuild/subbie.inp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/com/mesonbuild/subbie.inp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/com/mesonbuild/subbie.inp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/com/mesonbuild/subbie.inp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +subbie diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/genprog.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/genprog.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/genprog.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/genprog.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +import os, sys, argparse + +h_templ = '''#pragma once + +int %s(void); +''' + +c_templ = '''#include"%s.h" + +int %s(void) { + return 0; +} +''' + +parser = argparse.ArgumentParser() +parser.add_argument('--searchdir', required=True) +parser.add_argument('--outdir', required=True) +parser.add_argument('ifiles', nargs='+') + +options = parser.parse_args() + +searchdir = options.searchdir +outdir = options.outdir +ifiles = options.ifiles + +rel_ofiles = [] + +for ifile in ifiles: + if not ifile.startswith(options.searchdir): + sys.exit(f'Input file {ifile} does not start with search dir {searchdir}.') + rel_ofile = ifile[len(searchdir):] + if rel_ofile[0] == '/' or rel_ofile[0] == '\\': + rel_ofile = rel_ofile[1:] + rel_ofiles.append(os.path.splitext(rel_ofile)[0]) + +ofile_bases = [os.path.join(outdir, i) for i in rel_ofiles] + +for i, ifile_name in enumerate(ifiles): + proto_name = open(ifile_name).readline().strip() + h_out = ofile_bases[i] + '.h' + c_out = ofile_bases[i] + '.c' + os.makedirs(os.path.split(ofile_bases[i])[0], exist_ok=True) + open(h_out, 'w').write(h_templ % (proto_name)) + open(c_out, 'w').write(c_templ % (proto_name, proto_name)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/meson.build" 2021-10-23 16:49:50.000000000 +0000 @@ -0,0 +1,13 @@ +project('preserve subdir', 'c') + +gprog = find_program('genprog.py') + +gen = generator(gprog, \ + output : ['@BASENAME@.c', '@BASENAME@.h'], + arguments : ['--searchdir=@CURRENT_SOURCE_DIR@', '--outdir=@BUILD_DIR@', '@INPUT@']) + +generated = gen.process('base.inp', 'com/mesonbuild/subbie.inp', + preserve_path_from : meson.current_source_dir()) + +e = executable('testprog', 'testprog.c', generated) +test('testprog', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/testprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/testprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/168 preserve gendir/testprog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/168 preserve gendir/testprog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include"base.h" +#include"com/mesonbuild/subbie.h" + +int main(void) { + return base() + subbie(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 dependency factory/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 dependency factory/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 dependency factory/meson.build" 2020-01-07 21:09:03.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 dependency factory/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -project('dependency factory', 'c', meson_version : '>=0.40') - -dep = dependency('gl', method: 'pkg-config', required: false) -if dep.found() and dep.type_name() == 'pkgconfig' - dep.get_pkgconfig_variable('prefix') -endif - -dep = dependency('SDL2', method: 'pkg-config', required: false) -if dep.found() and dep.type_name() == 'pkgconfig' - dep.get_pkgconfig_variable('prefix') -endif - -dep = dependency('SDL2', method: 'config-tool', required: false) -if dep.found() and dep.type_name() == 'configtool' - dep.get_configtool_variable('prefix') -endif - -dep = dependency('Vulkan', method: 'pkg-config', required: false) -if dep.found() and dep.type_name() == 'pkgconfig' - dep.get_pkgconfig_variable('prefix') -endif - -dep = dependency('pcap', method: 'pkg-config', required: false) -if dep.found() and dep.type_name() == 'pkgconfig' - dep.get_pkgconfig_variable('prefix') -endif - -dep = dependency('pcap', method: 'config-tool', required: false) -if dep.found() and dep.type_name() == 'configtool' - dep.get_configtool_variable('prefix') -endif - -dep = dependency('cups', method: 'pkg-config', required: false) -if dep.found() and dep.type_name() == 'pkgconfig' - dep.get_pkgconfig_variable('prefix') -endif - -dep = dependency('cups', method: 'config-tool', required: false) -if dep.found() and dep.type_name() == 'configtool' - dep.get_configtool_variable('prefix') -endif - -dep = dependency('libwmf', method: 'pkg-config', required: false) -if dep.found() and dep.type_name() == 'pkgconfig' - dep.get_pkgconfig_variable('prefix') -endif - -dep = dependency('libwmf', method: 'config-tool', required: false) -if dep.found() and dep.type_name() == 'configtool' - dep.get_configtool_variable('prefix') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/bar.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/bar.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/bar.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/bar.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +extern "C" int foo(void); + +int main(void) { + return foo() != 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int foo(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/generated/funname" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/generated/funname" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/generated/funname" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/generated/funname" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +my_wonderful_function diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/generated/genheader.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/generated/genheader.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/generated/genheader.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/generated/genheader.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +import sys + +ifile = sys.argv[1] +ofile = sys.argv[2] + +templ = '''#pragma once + +int %s(void) { + return 42; +} +''' + +funname = open(ifile).readline().strip() + +open(ofile, 'w').write(templ % funname) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/generated/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/generated/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/generated/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/generated/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"funheader.h" + +int main(void) { + return my_wonderful_function() != 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/generated/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/generated/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/generated/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/generated/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,12 @@ +fp = find_program('genheader.py') + +genh = custom_target('genh', + input : 'funname', + output : 'funheader.h', + command : [fp, '@INPUT@', '@OUTPUT@']) + +dep = declare_dependency(sources : [genh]) + +e = executable('genuser', 'main.c', + dependencies : dep) +test('genuser', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/169 source in dep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/169 source in dep/meson.build" 2021-10-23 16:49:51.000000000 +0000 @@ -0,0 +1,8 @@ +project('foo', 'c', 'cpp') + +dep = declare_dependency(sources : 'foo.c') + +executable('bar', 'bar.cpp', + dependencies : dep) + +subdir('generated') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/16 comparison/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/16 comparison/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/16 comparison/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/16 comparison/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,143 @@ +project('comparison', 'c') + +# Compare equality of strings + +var1 = 'foo' +var2 = 'bar' + +if var1 == var2 + exe1 = executable('broken', 'broken.c') +else + exe1 = executable('prog1', 'prog.c') +endif + +if var1 == var1 + exe2 = executable('prog2', 'prog.c') +else + exe2 = executable('broken', 'broken.c') +endif + +if var1 != var2 + exe3 = executable('prog3', 'prog.c') +else + exe3 = executable('broken', 'broken.c') +endif + +if var1 != var1 + exe4 = executable('broken', 'broken.c') +else + exe4 = executable('prog4', 'prog.c') +endif + +test('equalfalse', exe1) +test('equaltrue', exe2) +test('nequaltrue', exe3) +test('nequalfalse', exe4) + +# Non-equality comparisons + +var3 = 3 +var4 = 4 + +if var3 < var4 + exe5 = executable('prog5', 'prog.c') +else + exe5 = executable('broken', 'broken.c') +endif + +if var3 < var3 + exe6 = executable('broken', 'broken.c') +else + exe6 = executable('prog6', 'prog.c') +endif + +if var4 > var3 + exe7 = executable('prog7', 'prog.c') +else + exe7 = executable('broken', 'broken.c') +endif + +if var3 > var3 + exe8 = executable('broken', 'broken.c') +else + exe8 = executable('prog8', 'prog.c') +endif + +if var4 <= var3 + exe9 = executable('broken', 'broken.c') +else + exe9 = executable('prog9', 'prog.c') +endif + +if var3 <= var3 + exe10 = executable('prog10', 'prog.c') +else + exe10 = executable('broken', 'broken.c') +endif + +if var3 >= var4 + exe11 = executable('broken', 'broken.c') +else + exe11 = executable('prog11', 'prog.c') +endif + +if var3 >= var3 + exe12 = executable('prog12', 'prog.c') +else + exe12 = executable('broken', 'broken.c') +endif + +test('lttrue', exe5) +test('ltfalse', exe6) +test('gttrue', exe7) +test('gtfalse', exe8) +test('lefalse', exe9) +test('letrue', exe10) +test('gefalse', exe11) +test('getrue', exe12) + +# Non-elementary type comparisons + +if exe1 == exe2 + exe13 = executable('broken', 'broken.c') +else + exe13 = executable('prog13', 'prog.c') +endif + +if exe1 == exe1 + exe14 = executable('prog14', 'prog.c') +else + exe14 = executable('broken', 'broken.c') +endif + +if exe1 != exe2 + exe15 = executable('prog15', 'prog.c') +else + exe15 = executable('broken', 'broken.c') +endif + +if exe1 != exe1 + exe16 = executable('broken', 'broken.c') +else + exe16 = executable('prog16', 'prog.c') +endif + +test('equalfalse', exe13) +test('equaltrue', exe14) +test('nequaltrue', exe15) +test('nequalfalse', exe16) + +# "in" and "not in" operators + +assert(1 in [1, 2], '''1 should be in [1, 2]''') +assert(3 not in [1, 2], '''3 shouldn't be in [1, 2]''') +assert(not (3 in [1, 2]), '''3 shouldn't be in [1, 2]''') + +assert('b' in ['a', 'b'], ''''b' should be in ['a', 'b']''') +assert('c' not in ['a', 'b'], ''''c' shouldn't be in ['a', 'b']''') + +assert(exe1 in [exe1, exe2], ''''exe1 should be in [exe1, exe2]''') +assert(exe3 not in [exe1, exe2], ''''exe3 shouldn't be in [exe1, exe2]''') + +assert('a' in {'a': 'b'}, '''1 should be in {'a': 'b'}''') +assert('b' not in {'a': 'b'}, '''1 should be in {'a': 'b'}''') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/16 comparison/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/16 comparison/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/16 comparison/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/16 comparison/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/16 else/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/16 else/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/16 else/meson.build" 2020-01-07 21:06:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/16 else/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('else test', 'c') - -var = false - -if var - exe = executable('break', 'break.c') -else - exe = executable('prog', 'prog.c') -endif - -test('elsetest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/16 else/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/16 else/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/16 else/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/16 else/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/export.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/export.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/export.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/export.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#pragma once + +#if defined BUILDING_EMBEDDED + #define DLL_PUBLIC +#elif defined _WIN32 || defined __CYGWIN__ + #if defined BUILDING_DLL + #define DLL_PUBLIC __declspec(dllexport) + #else + #define DLL_PUBLIC __declspec(dllimport) + #endif +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/generator.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/generator.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import os +import os.path +import sys + + +def main(): + name = os.path.splitext(os.path.basename(sys.argv[1]))[0] + out = sys.argv[2] + hname = os.path.join(out, name + '.h') + cname = os.path.join(out, name + '.c') + print(os.getcwd(), hname) + with open(hname, 'w') as hfile: + hfile.write(''' +#pragma once +#include "export.h" +int DLL_PUBLIC {name}(void); +'''.format(name=name)) + with open(cname, 'w') as cfile: + cfile.write(''' +#include "{name}.h" +int {name}(void) {{ + return {size}; +}} +'''.format(name=name, size=len(name))) + + +if __name__ == '__main__': + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include "meson_test_function.h" + +#include + +int main(void) { + if (meson_test_function() != 19) { + printf("Bad meson_test_function()\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/meson.build" 2021-10-23 16:49:53.000000000 +0000 @@ -0,0 +1,62 @@ +project('generator link_whole', 'c') + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: whole-archive not supported in Xcode. Patches welcome.') +endif + +# This just generates foo.h and foo.c with int foo() defined. +gen_py = find_program('generator.py') +gen = generator(gen_py, + output: ['@BASENAME@.h', '@BASENAME@.c'], + arguments : ['@INPUT@', '@BUILD_DIR@']) + +# Test 1: link directly into executable +srcs = gen.process('meson_test_function.tmpl') +exe = executable('exe1', [srcs, 'main.c'], c_args : '-DBUILDING_EMBEDDED') +test('test1', exe) + +# Test 2: link into shared library and access from executable +srcs = gen.process('meson_test_function.tmpl') +shlib2 = shared_library('shlib2', [srcs], c_args : '-DBUILDING_DLL') +exe = executable('exe2', 'main.c', + link_with : shlib2, + include_directories : shlib2.private_dir_include(), +) +test('test2', exe) + +# Test 3: link into static library and access from executable +srcs = gen.process('meson_test_function.tmpl') +stlib3 = static_library('stlib3', [srcs], c_args : '-DBUILDING_EMBEDDED') +exe = executable('exe3', 'main.c', + c_args : '-DBUILDING_EMBEDDED', + link_with : stlib3, + include_directories : stlib3.private_dir_include(), +) +test('test3', exe) + +# Test 4: link into static library, link into shared +# and access from executable. To make sure static_library +# is not dropped use pull_meson_test_function helper. +srcs = gen.process('meson_test_function.tmpl') +stlib4 = static_library('stlib4', [srcs], c_args : '-DBUILDING_DLL') +shlib4 = shared_library('shlib4', 'pull_meson_test_function.c', + c_args : '-DBUILDING_DLL', + link_with : stlib4, + include_directories : stlib4.private_dir_include(), +) +exe = executable('exe4', 'main.c', + link_with : shlib4, + include_directories : stlib4.private_dir_include(), +) +test('test4', exe) + +# Test 5: link into static library, link_whole into shared +# and access from executable +srcs = gen.process('meson_test_function.tmpl') +stlib5 = static_library('stlib5', [srcs], c_args : '-DBUILDING_DLL') +shlib5 = shared_library('shlib5', link_whole : stlib5) +exe = executable('exe5', 'main.c', + link_with : shlib5, + include_directories : stlib5.private_dir_include(), +) +test('test5', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/pull_meson_test_function.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/pull_meson_test_function.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 generator link whole/pull_meson_test_function.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 generator link whole/pull_meson_test_function.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include "export.h" +#include "meson_test_function.h" + +int DLL_PUBLIC function_puller(void) { + return meson_test_function(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 get project license/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 get project license/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 get project license/bar.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 get project license/bar.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I'm a main project bar.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 get project license/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 get project license/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/170 get project license/meson.build" 2020-01-07 21:09:03.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/170 get project license/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('bar', 'c', license: 'Apache') - -executable('bar', 'bar.c') - -license = meson.project_license()[0] -if license != 'Apache' - error('The license should be Apache, but it is: ' + license) -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 initial c_args/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 initial c_args/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 initial c_args/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 initial c_args/meson.build" 2021-10-23 16:49:51.000000000 +0000 @@ -0,0 +1,7 @@ +project('options', 'c') + +# Test passing c_args and c_link_args options from the command line. +assert(get_option('c_args') == ['-funroll-loops'], + 'Incorrect value for c_args option.') +assert(get_option('c_link_args') == ['-Dtest_harmless_but_useless_link_arg'], + 'Incorrect value for c_link_args option.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 initial c_args/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 initial c_args/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 initial c_args/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 initial c_args/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "matrix": { + "options": { + "c_args": [{ "val": "-funroll-loops" }], + "c_link_args": [{ "val": "-Dtest_harmless_but_useless_link_arg" }] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 yield/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 yield/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 yield/meson.build" 2020-01-07 21:09:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 yield/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('yield_options', 'c') - -subproject('sub') - -assert(get_option('unshared_option') == 'one', 'Unshared option has wrong value in superproject.') -assert(get_option('shared_option') == 'two', 'Shared option has wrong value in superproject..') -assert(get_option('wrongtype_option') == 'three', 'Wrongtype option has wrong value in superproject..') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 yield/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 yield/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 yield/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 yield/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -option('unshared_option', type : 'string', value : 'one') -option('shared_option', type : 'string', value : 'two') -option('wrongtype_option', type : 'string', value : 'three') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 yield/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 yield/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 yield/subprojects/sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 yield/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('subbie', 'c') - -assert(get_option('unshared_option') == 'three', 'Unshared option has wrong value in subproject.') -assert(get_option('shared_option') == 'two', 'Shared option has wrong value in subproject.') -assert(get_option('wrongtype_option') == true, 'Wrongtype option has wrong value in subproject.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 yield/subprojects/sub/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 yield/subprojects/sub/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/171 yield/subprojects/sub/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/171 yield/subprojects/sub/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -option('unshared_option', type : 'string', value : 'three', yield : false) -option('shared_option', type : 'string', value : 'four', yield : true) -option('wrongtype_option', type : 'boolean', value : true, yield : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int meson_test_main_foo(void) { return 10; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include + +int meson_test_main_foo(void); +int meson_test_subproj_foo(void); + +int main(void) { + if (meson_test_main_foo() != 10) { + printf("Failed meson_test_main_foo\n"); + return 1; + } + if (meson_test_subproj_foo() != 20) { + printf("Failed meson_test_subproj_foo\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/meson.build" 2021-10-23 16:49:52.000000000 +0000 @@ -0,0 +1,15 @@ +project('subproject targets', 'c') + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: many targets with the same name not supported in Xcode. Patches welcome.') +endif + +# Idea behind this test is to create targets with identical name +# but different output files. We can do this by choosing different +# name_prefix of libraries. Target id does not depend on name_prefix. + +main_foo = static_library('foo', 'foo.c', name_prefix : 'main') +subproj_foo = subproject('subproj').get_variable('foo') + +exe = executable('prog', 'main.c', link_with : [main_foo, subproj_foo]) +test('main test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int meson_test_subproj_foo(void) { return 20; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('subproj', 'c') + +foo = static_library('foo', 'foo.c', name_prefix : 'subproj') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/a.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -int func2(void); - -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC func(void) { return func2(); } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('alpha project', 'c', subproject_dir: 'var/subprojects') - -b = subproject('beta') -l = shared_library('a', 'a.c', link_with : b.get_variable('lb')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/b.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC func2(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/contrib/subprojects/beta/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('beta project', 'c') - -lb = shared_library('b', 'b.c') -notfound = dependency('', required : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/meson.build" 2020-01-07 21:09:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('gamma project', 'c', subproject_dir: 'contrib/subprojects') - -a = subproject('alpha') -lib = a.get_variable('l') - -# Ensure that the dependency version is not checked for a not-found dependency -notfound = dependency('', version : '>=1.0', required : false, - fallback : ['beta', 'notfound']) - -exe = executable('prog', 'prog.c', link_with : lib) -test('basic', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/172 subproject nested subproject dirs/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/172 subproject nested subproject dirs/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int func(void); - -int main(void) { - return func() == 42 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/config.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/config.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/config.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/config.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ + #if defined BUILDING_DLL + #define DLL_PUBLIC __declspec(dllexport) + #else + #define DLL_PUBLIC __declspec(dllimport) + #endif +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/libA.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/libA.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/libA.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/libA.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#define BUILDING_DLL + +#include "libA.h" + +namespace meson_test_as_needed { + DLL_PUBLIC bool linked = false; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/libA.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/libA.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/libA.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/libA.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "config.h" + +namespace meson_test_as_needed { + DLL_PUBLIC extern bool linked; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/libB.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/libB.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/libB.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/libB.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +#include "libA.h" + +#undef DLL_PUBLIC +#define BUILDING_DLL +#include "config.h" + +namespace meson_test_as_needed { + namespace { + bool set_linked() { + linked = true; + return true; + } + bool stub = set_linked(); + } + + DLL_PUBLIC int libB_unused_func() { + return 0; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +#include "libA.h" + +int main(void) { + return !meson_test_as_needed::linked ? EXIT_SUCCESS : EXIT_FAILURE; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 as-needed/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 as-needed/meson.build" 2021-10-23 16:49:55.000000000 +0000 @@ -0,0 +1,13 @@ +project('as-needed test', 'cpp') + +# Idea behind this test is to have -Wl,--as-needed prune +# away unneeded linkages, which would otherwise cause global +# static initialiser side-effects to set a boolean to true. + +# Credits for portable ISO C++ idea go to sarum9in + +libA = library('A', 'libA.cpp') +libB = library('B', 'libB.cpp', link_with : libA) + +main_exe = executable('C', 'main.cpp', link_with : [libA, libB]) +test('main test', main_exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/base.inp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/base.inp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/base.inp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/base.inp" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -base diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/com/mesonbuild/subbie.inp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/com/mesonbuild/subbie.inp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/com/mesonbuild/subbie.inp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/com/mesonbuild/subbie.inp" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -subbie diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/genprog.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/genprog.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/genprog.py" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/genprog.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 - -import os, sys, argparse - -h_templ = '''#pragma once - -int %s(void); -''' - -c_templ = '''#include"%s.h" - -int %s(void) { - return 0; -} -''' - -parser = argparse.ArgumentParser() -parser.add_argument('--searchdir', required=True) -parser.add_argument('--outdir', required=True) -parser.add_argument('ifiles', nargs='+') - -options = parser.parse_args() - -searchdir = options.searchdir -outdir = options.outdir -ifiles = options.ifiles - -rel_ofiles = [] - -for ifile in ifiles: - if not ifile.startswith(options.searchdir): - sys.exit('Input file %s does not start with search dir %s.' % (ifile, searchdir)) - rel_ofile = ifile[len(searchdir):] - if rel_ofile[0] == '/' or rel_ofile[0] == '\\': - rel_ofile = rel_ofile[1:] - rel_ofiles.append(os.path.splitext(rel_ofile)[0]) - -ofile_bases = [os.path.join(outdir, i) for i in rel_ofiles] - -for i, ifile_name in enumerate(ifiles): - proto_name = open(ifile_name).readline().strip() - h_out = ofile_bases[i] + '.h' - c_out = ofile_bases[i] + '.c' - os.makedirs(os.path.split(ofile_bases[i])[0], exist_ok=True) - open(h_out, 'w').write(h_templ % (proto_name)) - open(c_out, 'w').write(c_templ % (proto_name, proto_name)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/meson.build" 2020-01-07 21:09:06.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('preserve subdir', 'c') - -gprog = find_program('genprog.py') - -gen = generator(gprog, \ - output : ['@BASENAME@.c', '@BASENAME@.h'], - arguments : ['--searchdir=@CURRENT_SOURCE_DIR@', '--outdir=@BUILD_DIR@', '@INPUT@']) - -generated = gen.process('base.inp', 'com/mesonbuild/subbie.inp', - preserve_path_from : meson.current_source_dir()) - -e = executable('testprog', 'testprog.c', generated) -test('testprog', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/testprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/testprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/173 preserve gendir/testprog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/173 preserve gendir/testprog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include"base.h" -#include"com/mesonbuild/subbie.h" - -int main(void) { - return base() + subbie(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 ndebug if-release enabled/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 ndebug if-release enabled/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 ndebug if-release enabled/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 ndebug if-release enabled/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#include +#include + +int meson_test_side_effect = EXIT_FAILURE; + +int meson_test_set_side_effect(void) { + meson_test_side_effect = EXIT_SUCCESS; + return 1; +} + +int main(void) { + // meson_test_side_effect is set only if assert is executed + assert(meson_test_set_side_effect()); + return meson_test_side_effect; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 ndebug if-release enabled/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 ndebug if-release enabled/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 ndebug if-release enabled/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 ndebug if-release enabled/meson.build" 2021-10-23 16:49:55.000000000 +0000 @@ -0,0 +1,7 @@ +project('ndebug enabled', 'c', + default_options : [ + 'buildtype=debugoptimized', + 'b_ndebug=if-release', + ]) + +test('exe', executable('main', 'main.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/bar.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/bar.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/bar.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/bar.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -extern "C" int foo(void); - -int main(void) { - return foo() != 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/foo.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int foo(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/generated/funname" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/generated/funname" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/generated/funname" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/generated/funname" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -my_wonderful_function diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/generated/genheader.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/generated/genheader.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/generated/genheader.py" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/generated/genheader.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -ifile = sys.argv[1] -ofile = sys.argv[2] - -templ = '''#pragma once - -int %s(void) { - return 42; -} -''' - -funname = open(ifile).readline().strip() - -open(ofile, 'w').write(templ % funname) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/generated/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/generated/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/generated/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/generated/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"funheader.h" - -int main(void) { - return my_wonderful_function() != 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/generated/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/generated/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/generated/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/generated/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -fp = find_program('genheader.py') - -genh = custom_target('genh', - input : 'funname', - output : 'funheader.h', - command : [fp, '@INPUT@', '@OUTPUT@']) - -dep = declare_dependency(sources : [genh]) - -e = executable('genuser', 'main.c', - dependencies : dep) -test('genuser', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/174 source in dep/meson.build" 2020-01-07 21:09:07.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/174 source in dep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('foo', 'c', 'cpp') - -dep = declare_dependency(sources : 'foo.c') - -executable('bar', 'bar.cpp', - dependencies : dep) - -subdir('generated') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/export.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/export.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/export.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/export.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#pragma once - -#if defined BUILDING_EMBEDDED - #define DLL_PUBLIC -#elif defined _WIN32 || defined __CYGWIN__ - #if defined BUILDING_DLL - #define DLL_PUBLIC __declspec(dllexport) - #else - #define DLL_PUBLIC __declspec(dllimport) - #endif -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/generator.py" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/generator.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 - -import os -import os.path -import sys - - -def main(): - name = os.path.splitext(os.path.basename(sys.argv[1]))[0] - out = sys.argv[2] - hname = os.path.join(out, name + '.h') - cname = os.path.join(out, name + '.c') - print(os.getcwd(), hname) - with open(hname, 'w') as hfile: - hfile.write(''' -#pragma once -#include "export.h" -int DLL_PUBLIC {name}(void); -'''.format(name=name)) - with open(cname, 'w') as cfile: - cfile.write(''' -#include "{name}.h" -int {name}(void) {{ - return {size}; -}} -'''.format(name=name, size=len(name))) - - -if __name__ == '__main__': - main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include "meson_test_function.h" - -#include - -int main(void) { - if (meson_test_function() != 19) { - printf("Bad meson_test_function()\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/meson.build" 2020-01-07 21:09:08.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -project('generator link_whole', 'c') - -cc = meson.get_compiler('c') -if cc.get_id() == 'msvc' - if cc.version().version_compare('<19') - error('MESON_SKIP_TEST link_whole only works on VS2015 or newer.') - endif -endif - -# This just generates foo.h and foo.c with int foo() defined. -gen_py = find_program('generator.py') -gen = generator(gen_py, - output: ['@BASENAME@.h', '@BASENAME@.c'], - arguments : ['@INPUT@', '@BUILD_DIR@']) - -# Test 1: link directly into executable -srcs = gen.process('meson_test_function.tmpl') -exe = executable('exe1', [srcs, 'main.c'], c_args : '-DBUILDING_EMBEDDED') -test('test1', exe) - -# Test 2: link into shared library and access from executable -srcs = gen.process('meson_test_function.tmpl') -shlib2 = shared_library('shlib2', [srcs], c_args : '-DBUILDING_DLL') -exe = executable('exe2', 'main.c', - link_with : shlib2, - include_directories : shlib2.private_dir_include(), -) -test('test2', exe) - -# Test 3: link into static library and access from executable -srcs = gen.process('meson_test_function.tmpl') -stlib3 = static_library('stlib3', [srcs], c_args : '-DBUILDING_EMBEDDED') -exe = executable('exe3', 'main.c', - c_args : '-DBUILDING_EMBEDDED', - link_with : stlib3, - include_directories : stlib3.private_dir_include(), -) -test('test3', exe) - -# Test 4: link into static library, link into shared -# and access from executable. To make sure static_library -# is not dropped use pull_meson_test_function helper. -srcs = gen.process('meson_test_function.tmpl') -stlib4 = static_library('stlib4', [srcs], c_args : '-DBUILDING_DLL') -shlib4 = shared_library('shlib4', 'pull_meson_test_function.c', - c_args : '-DBUILDING_DLL', - link_with : stlib4, - include_directories : stlib4.private_dir_include(), -) -exe = executable('exe4', 'main.c', - link_with : shlib4, - include_directories : stlib4.private_dir_include(), -) -test('test4', exe) - -# Test 5: link into static library, link_whole into shared -# and access from executable -srcs = gen.process('meson_test_function.tmpl') -stlib5 = static_library('stlib5', [srcs], c_args : '-DBUILDING_DLL') -shlib5 = shared_library('shlib5', link_whole : stlib5) -exe = executable('exe5', 'main.c', - link_with : shlib5, - include_directories : stlib5.private_dir_include(), -) -test('test5', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/pull_meson_test_function.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/pull_meson_test_function.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 generator link whole/pull_meson_test_function.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 generator link whole/pull_meson_test_function.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include "export.h" -#include "meson_test_function.h" - -int DLL_PUBLIC function_puller(void) { - return meson_test_function(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 ndebug if-release disabled/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 ndebug if-release disabled/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 ndebug if-release disabled/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 ndebug if-release disabled/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include +#include + +int main(void) { + assert(0); + return EXIT_SUCCESS; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 ndebug if-release disabled/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 ndebug if-release disabled/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/175 ndebug if-release disabled/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/175 ndebug if-release disabled/meson.build" 2021-10-23 16:49:55.000000000 +0000 @@ -0,0 +1,7 @@ +project('ndebug disabled', 'c', + default_options : [ + 'buildtype=release', + 'b_ndebug=if-release', + ]) + +test('exe', executable('main', 'main.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/176 initial c_args/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/176 initial c_args/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/176 initial c_args/meson.build" 2020-01-07 21:09:09.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/176 initial c_args/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('options', 'c') - -# Test passing c_args and c_link_args options from the command line. -assert(get_option('c_args') == ['-funroll-loops'], - 'Incorrect value for c_args option.') -assert(get_option('c_link_args') == ['-Dtest_harmless_but_useless_link_arg'], - 'Incorrect value for c_link_args option.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/176 initial c_args/test_args.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/176 initial c_args/test_args.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/176 initial c_args/test_args.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/176 initial c_args/test_args.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -# This file is not read by meson itself, but by the test framework. -# It is not possible to pass arguments to meson from a file. -['-Dc_args=-march=native', '-Dc_args=-funroll-loops', - '-Dc_link_args=-Dtest_harmless_but_useless_link_arg'] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/176 subproject version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/176 subproject version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/176 subproject version/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/176 subproject version/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,9 @@ +project('subproject version', 'c', + version : '2.3.4', + license: 'mylicense') + +subproject('a') + +liba_dep = dependency('a', + fallback: ['a', 'liba_dep'], + version: ['>= 0.30.0', '!= 0.99.0']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/176 subproject version/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/176 subproject version/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/176 subproject version/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/176 subproject version/subprojects/a/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +project('mysubproject', 'c', + version : '1.0.0', + license : 'sublicense') + +liba_dep = declare_dependency (version : '1.0.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/foo.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int meson_test_main_foo(void) { return 10; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/main.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include - -int meson_test_main_foo(void); -int meson_test_subproj_foo(void); - -int main(void) { - if (meson_test_main_foo() != 10) { - printf("Failed meson_test_main_foo\n"); - return 1; - } - if (meson_test_subproj_foo() != 20) { - printf("Failed meson_test_subproj_foo\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/meson.build" 2020-01-07 21:09:09.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('subproject targets', 'c') - -# Idea behind this test is to create targets with identical name -# but different output files. We can do this by choosing different -# name_prefix of libraries. Target id does not depend on name_prefix. - -main_foo = static_library('foo', 'foo.c', name_prefix : 'main') -subproj_foo = subproject('subproj').get_variable('foo') - -exe = executable('prog', 'main.c', link_with : [main_foo, subproj_foo]) -test('main test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/foo.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int meson_test_subproj_foo(void) { return 20; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 identical target name in subproject flat layout/subprojects/subproj/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('subproj', 'c') - -foo = static_library('foo', 'foo.c', name_prefix : 'subproj') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 subdir_done/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 subdir_done/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/177 subdir_done/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/177 subdir_done/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,11 @@ +# Should run, even though main.cpp does not exist and we call error in the last line. +# subdir_done jumps to end, so both lines are not executed. + +project('example exit', 'cpp') + +if true + subdir_done() +endif + +executable('main', 'main.cpp') +error('Unreachable') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/config.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/config.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/config.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/config.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #if defined BUILDING_DLL - #define DLL_PUBLIC __declspec(dllexport) - #else - #define DLL_PUBLIC __declspec(dllimport) - #endif -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/libA.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/libA.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/libA.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/libA.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#define BUILDING_DLL - -#include "libA.h" - -namespace meson_test_as_needed { - DLL_PUBLIC bool linked = false; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/libA.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/libA.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/libA.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/libA.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "config.h" - -namespace meson_test_as_needed { - DLL_PUBLIC extern bool linked; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/libB.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/libB.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/libB.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/libB.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -#include "libA.h" - -#undef DLL_PUBLIC -#define BUILDING_DLL -#include "config.h" - -namespace meson_test_as_needed { - namespace { - bool set_linked() { - linked = true; - return true; - } - bool stub = set_linked(); - } - - DLL_PUBLIC int libB_unused_func() { - return 0; - } -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/main.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include - -#include "libA.h" - -int main(void) { - return !meson_test_as_needed::linked ? EXIT_SUCCESS : EXIT_FAILURE; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 as-needed/meson.build" 2020-01-07 21:09:12.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 as-needed/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('as-needed test', 'cpp') - -# Idea behind this test is to have -Wl,--as-needed prune -# away unneeded linkages, which would otherwise cause global -# static initialiser side-effects to set a boolean to true. - -# Credits for portable ISO C++ idea go to sarum9in - -libA = library('A', 'libA.cpp') -libB = library('B', 'libB.cpp', link_with : libA) - -main_exe = executable('C', 'main.cpp', link_with : [libA, libB]) -test('main test', main_exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/dummy.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/dummy.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/dummy.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/dummy.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import sys + +if __name__ == '__main__': + Path(sys.argv[1]).write_text('Hello World\n') + raise SystemExit(0) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/libfile.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/libfile.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/libfile.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/libfile.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include "mylib.h" + +DO_EXPORT int retval = 42; + +DO_EXPORT int func(void) { + return retval; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "mylib.h" + +DO_IMPORT int func(void); +DO_IMPORT int retval; + +int main(void) { + return func() == retval ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/meson.build" 2021-10-23 16:49:59.000000000 +0000 @@ -0,0 +1,50 @@ +project('both libraries linking test', 'c') + +both_libs = both_libraries('mylib', 'libfile.c') +dep = declare_dependency(link_with: both_libs) +exe_shared = executable('prog-shared', 'main.c', link_with : both_libs.get_shared_lib()) +exe_static = executable('prog-static', 'main.c', + c_args : ['-DSTATIC_COMPILATION'], + link_with : both_libs.get_static_lib()) +exe_both = executable('prog-both', 'main.c', link_with : both_libs) +exe_dep = executable('prog-dep', 'main.c', dependencies : [dep]) + +# Try using it in a custom_target +custom_target('tgt_a', + command: [ + find_program('./dummy.py'), + '@OUTPUT@', + both_libs, + ], + output: ['hello1.txt'], + input: [both_libs], +) + +test('runtest-shared', exe_shared) +test('runtest-static', exe_static) +test('runtest-both', exe_both) +test('runtest-dep', exe_dep) + +# Same as above, but using build_target() +both_libs2 = build_target('mylib2', 'libfile.c', target_type: 'both_libraries') +exe_shared2 = executable('prog-shared2', 'main.c', + link_with : both_libs2.get_shared_lib()) +exe_static2 = executable('prog-static2', 'main.c', + c_args : ['-DSTATIC_COMPILATION'], + link_with : both_libs2.get_static_lib()) +exe_both2 = executable('prog-both2', 'main.c', link_with : both_libs2) + +# Test {set,get}_variable +set_variable('both_libs2', both_libs) +both_libs3 = get_variable('both_libs') + +# Ensure that calling the build target methods also works +assert(both_libs.name() == 'mylib') +assert(both_libs2.name() == 'mylib') +assert(both_libs3.name() == 'mylib') +assert(both_libs2.get_shared_lib().name() == 'mylib') +assert(both_libs3.get_static_lib().name() == 'mylib') + +test('runtest-shared-2', exe_shared2) +test('runtest-static-2', exe_static2) +test('runtest-both-2', exe_both2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/mylib.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/mylib.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/178 bothlibraries/mylib.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/178 bothlibraries/mylib.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#pragma once + +#ifdef _WIN32 + #ifdef STATIC_COMPILATION + #define DO_IMPORT extern + #else + #define DO_IMPORT __declspec(dllimport) + #endif + #define DO_EXPORT __declspec(dllexport) +#else + #define DO_IMPORT extern + #define DO_EXPORT +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/file.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/file.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/file.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/file.c.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include +const char* does_it_work(void) { + printf("{NAME}\n"); + return "yes it does"; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/file.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/file.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/file.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/file.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +import sys +import os + +with open(sys.argv[1]) as fh: + content = fh.read().replace("{NAME}", sys.argv[2]) + +with open(os.path.join(sys.argv[3]), 'w', errors='replace') as fh: + fh.write(content) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/find.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/find.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/find.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/find.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import os +import sys + +for fh in os.listdir('.'): + if os.path.isfile(fh): + if fh.endswith('.c'): + sys.stdout.write(fh + '\0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/fun.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/fun.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/fun.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/fun.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int a_fun(void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +#include + +const char* does_it_work(void); + +int a_fun(void); + +int main(void) { + if(strcmp(does_it_work(), "yes it does") != 0) { + return -a_fun(); + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 escape and unicode/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 escape and unicode/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,38 @@ +project('180 escape', 'c') + +gen = generator(find_program('file.py'), arguments:['@INPUT@', 'erd\u0151', '@OUTPUT@'], output: '@BASENAME@') + +gen_file = gen.process('file.c.in') + +find_file_list = run_command(find_program('find.py'), check: true) +assert(find_file_list.returncode() == 0, 'Didn\'t find any files.') + +# Strings should support both octal \ooo and hex \xhh encodings + +found_files_oct = [] +foreach l : find_file_list.stdout().strip('\0').split('\000') + found_files_oct += [files(l)] +endforeach + +test('first', executable('first', found_files_oct + [gen_file])) + +found_files_hex = [] +foreach l : find_file_list.stdout().strip('\x00').split('\x00') + found_files_hex += [files(l)] +endforeach + +test('second', executable('second', found_files_hex + [gen_file])) + +# Unrecognized and malformed escape sequences are literal + +malformed = [ + [ '\c', 'c' ], + [ '\Uabcdefghi', 'Uabcdefghi'], + [ '\u123 ', 'u123 '], + [ '\xqr', 'xqr'], +] + +foreach m : malformed + assert(m[0].endswith(m[1]), 'bad escape sequence had unexpected end') + assert(m[0].startswith('\\'), 'bad escape sequence had unexpected start') +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 ndebug if-release enabled/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 ndebug if-release enabled/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 ndebug if-release enabled/main.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 ndebug if-release enabled/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#include -#include - -int meson_test_side_effect = EXIT_FAILURE; - -int meson_test_set_side_effect(void) { - meson_test_side_effect = EXIT_SUCCESS; - return 1; -} - -int main(void) { - // meson_test_side_effect is set only if assert is executed - assert(meson_test_set_side_effect()); - return meson_test_side_effect; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 ndebug if-release enabled/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 ndebug if-release enabled/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/179 ndebug if-release enabled/meson.build" 2020-01-07 21:09:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/179 ndebug if-release enabled/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('ndebug enabled', 'c', - default_options : [ - 'buildtype=debugoptimized', - 'b_ndebug=if-release', - ]) - -test('exe', executable('main', 'main.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 array/func.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 array/func.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 array/func.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 array/func.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int func(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 array/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 array/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 array/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 array/meson.build" 2021-10-23 16:47:54.000000000 +0000 @@ -0,0 +1,8 @@ +project('array test', 'c') + +arr = [ + 'func.c', + 'prog.c'] + +exe = executable('prog', sources : arr) +test('arr test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 array/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 array/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 array/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 array/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +extern int func(void); + +int main(void) { return func(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 comparison/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 comparison/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 comparison/meson.build" 2020-01-07 21:06:26.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 comparison/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ -project('comparison', 'c') - -# Compare equality of strings - -var1 = 'foo' -var2 = 'bar' - -if var1 == var2 - exe1 = executable('broken', 'broken.c') -else - exe1 = executable('prog1', 'prog.c') -endif - -if var1 == var1 - exe2 = executable('prog2', 'prog.c') -else - exe2 = executable('broken', 'broken.c') -endif - -if var1 != var2 - exe3 = executable('prog3', 'prog.c') -else - exe3 = executable('broken', 'broken.c') -endif - -if var1 != var1 - exe4 = executable('broken', 'broken.c') -else - exe4 = executable('prog4', 'prog.c') -endif - -test('equalfalse', exe1) -test('equaltrue', exe2) -test('nequaltrue', exe3) -test('nequalfalse', exe4) - -# Non-equality comparisons - -var3 = 3 -var4 = 4 - -if var3 < var4 - exe5 = executable('prog5', 'prog.c') -else - exe5 = executable('broken', 'broken.c') -endif - -if var3 < var3 - exe6 = executable('broken', 'broken.c') -else - exe6 = executable('prog6', 'prog.c') -endif - -if var4 > var3 - exe7 = executable('prog7', 'prog.c') -else - exe7 = executable('broken', 'broken.c') -endif - -if var3 > var3 - exe8 = executable('broken', 'broken.c') -else - exe8 = executable('prog8', 'prog.c') -endif - -if var4 <= var3 - exe9 = executable('broken', 'broken.c') -else - exe9 = executable('prog9', 'prog.c') -endif - -if var3 <= var3 - exe10 = executable('prog10', 'prog.c') -else - exe10 = executable('broken', 'broken.c') -endif - -if var3 >= var4 - exe11 = executable('broken', 'broken.c') -else - exe11 = executable('prog11', 'prog.c') -endif - -if var3 >= var3 - exe12 = executable('prog12', 'prog.c') -else - exe12 = executable('broken', 'broken.c') -endif - -test('lttrue', exe5) -test('ltfalse', exe6) -test('gttrue', exe7) -test('gtfalse', exe8) -test('lefalse', exe9) -test('letrue', exe10) -test('gefalse', exe11) -test('getrue', exe12) - -# Non-elementary type comparisons - -if exe1 == exe2 - exe13 = executable('broken', 'broken.c') -else - exe13 = executable('prog13', 'prog.c') -endif - -if exe1 == exe1 - exe14 = executable('prog14', 'prog.c') -else - exe14 = executable('broken', 'broken.c') -endif - -if exe1 != exe2 - exe15 = executable('prog15', 'prog.c') -else - exe15 = executable('broken', 'broken.c') -endif - -if exe1 != exe1 - exe16 = executable('broken', 'broken.c') -else - exe16 = executable('prog16', 'prog.c') -endif - -test('equalfalse', exe13) -test('equaltrue', exe14) -test('nequaltrue', exe15) -test('nequalfalse', exe16) - -# Equality comparisons of different elementary types -# (these all cause warnings currently, will become an error in future) - -assert([] != 'st', 'not equal') -assert([] != 1, 'not equal') -assert(2 != 'st', 'not equal') - -assert(not ([] == 'st'), 'not equal') -assert(not ([] == 1), 'not equal') -assert(not (2 == 'st'), 'not equal') - -# "in" and "not in" operators - -assert(1 in [1, 2], '''1 should be in [1, 2]''') -assert(3 not in [1, 2], '''3 shouldn't be in [1, 2]''') -assert(not (3 in [1, 2]), '''3 shouldn't be in [1, 2]''') - -assert('b' in ['a', 'b'], ''''b' should be in ['a', 'b']''') -assert('c' not in ['a', 'b'], ''''c' shouldn't be in ['a', 'b']''') - -assert(exe1 in [exe1, exe2], ''''exe1 should be in [exe1, exe2]''') -assert(exe3 not in [exe1, exe2], ''''exe3 shouldn't be in [exe1, exe2]''') - -assert('a' in {'a': 'b'}, '''1 should be in {'a': 'b'}''') -assert('b' not in {'a': 'b'}, '''1 should be in {'a': 'b'}''') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 comparison/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 comparison/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/17 comparison/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/17 comparison/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/180 has link arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/180 has link arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/180 has link arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/180 has link arg/meson.build" 2021-10-23 16:49:59.000000000 +0000 @@ -0,0 +1,47 @@ +project('has link arg', 'c', 'cpp') + +cc = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') + +if cc.get_argument_syntax() == 'msvc' + is_arg = '/OPT:REF' + useless = '/DEBUG' + isnt_arg = '/iambroken' +else + is_arg = '-Wl,-L/tmp' + useless = '-Wl,-L/usr' + isnt_arg = '-Wl,-iambroken' +endif + +assert(cc.has_link_argument(is_arg), 'Arg that should have worked does not work.') +assert(cpp.has_link_argument(is_arg), 'Arg that should have worked does not work.') + +if cc.get_id() != 'pgi' +assert(not cc.has_link_argument(isnt_arg), 'Arg that should be broken is not.') +assert(not cpp.has_link_argument(isnt_arg), 'Arg that should be broken is not.') + +assert(cc.get_supported_link_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') +assert(cpp.get_supported_link_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') + +# Have useless at the end to ensure that the search goes from front to back. +l1 = cc.first_supported_link_argument([isnt_arg, is_arg, isnt_arg, useless]) +l2 = cc.first_supported_link_argument(isnt_arg, isnt_arg, isnt_arg) + +assert(l1.length() == 1, 'First supported returned wrong result.') +assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') +assert(l2.length() == 0, 'First supported did not return empty array.') + +l1 = cpp.first_supported_link_argument([isnt_arg, is_arg, isnt_arg, useless]) +l2 = cpp.first_supported_link_argument(isnt_arg, isnt_arg, isnt_arg) + +assert(l1.length() == 1, 'First supported returned wrong result.') +assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') +assert(l2.length() == 0, 'First supported did not return empty array.') + +assert(not cc.has_multi_link_arguments([isnt_arg, is_arg]), 'Arg that should be broken is not.') + +assert(not cc.has_link_argument('-Wl,-z,nodelete42'), 'Did not detect wrong -z linker argument') +endif + +assert(cc.has_multi_link_arguments(is_arg), 'Arg that should have worked does not work.') +assert(cc.has_multi_link_arguments([useless, is_arg]), 'Arg that should have worked does not work.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/180 ndebug if-release disabled/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/180 ndebug if-release disabled/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/180 ndebug if-release disabled/main.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/180 ndebug if-release disabled/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include -#include - -int main(void) { - assert(0); - return EXIT_SUCCESS; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/180 ndebug if-release disabled/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/180 ndebug if-release disabled/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/180 ndebug if-release disabled/meson.build" 2020-01-07 21:09:12.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/180 ndebug if-release disabled/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('ndebug disabled', 'c', - default_options : [ - 'buildtype=release', - 'b_ndebug=if-release', - ]) - -test('exe', executable('main', 'main.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int meson_test_main_foo(void) { return 10; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include + +int meson_test_main_foo(void); +int meson_test_subproj_foo(void); + +int main(void) { + if (meson_test_main_foo() != 10) { + printf("Failed meson_test_main_foo\n"); + return 1; + } + if (meson_test_subproj_foo() != 20) { + printf("Failed meson_test_subproj_foo\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/meson.build" 2021-10-23 16:50:00.000000000 +0000 @@ -0,0 +1,15 @@ +project('subdir targets', 'c') + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: many targets with the same name not supported in Xcode. Patches welcome.') +endif + +# Idea behind this test is to create targets with identical name +# but different output files. We can do this by choosing different +# name_prefix of libraries. Target id does not depend on name_prefix. + +main_foo = static_library('foo', 'foo.c', name_prefix : 'main') +subdir('subdir') # defines subdir_foo + +exe = executable('prog', 'main.c', link_with : [main_foo, subdir_foo]) +test('main test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/subdir/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/subdir/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/subdir/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/subdir/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int meson_test_subproj_foo(void) { return 20; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 same target name flat layout/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 same target name flat layout/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +subdir_foo = static_library('foo', 'foo.c', name_prefix : 'subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 subproject version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 subproject version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 subproject version/meson.build" 2020-01-07 21:09:12.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 subproject version/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('subproject version', 'c', - version : '2.3.4', - license: 'mylicense') - -subproject('a') - -liba_dep = dependency('a', - fallback: ['a', 'liba_dep'], - version: ['>= 0.30.0', '!= 0.99.0']) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 subproject version/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 subproject version/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/181 subproject version/subprojects/a/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/181 subproject version/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('mysubproject', 'c', - version : '1.0.0', - license : 'sublicense') - -liba_dep = declare_dependency (version : '1.0.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/meson.build" 2021-10-23 16:50:00.000000000 +0000 @@ -0,0 +1,25 @@ +project('find program override', 'c') + +gencodegen = find_program('gencodegen', required : false) +six_prog = find_program('six_meson_exe', required : false) + +assert(not gencodegen.found(), 'gencodegen is an internal program, should not be found') +assert(not six_prog.found(), 'six_meson_exe is an internal program, should not be found') + +# Test the check-if-found-else-override workflow +if not gencodegen.found() + subdir('subdir') +endif + +subdir('otherdir') + +tool = find_program('sometool') +assert(tool.found()) +assert(tool.full_path() != '') +assert(tool.full_path() == tool.path()) + +# six_meson_exe is an overritten project executable +six_prog = find_program('six_meson_exe') +assert(six_prog.found()) +assert(six_prog.full_path() != '') +assert(six_prog.full_path() == six_prog.path()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/main2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/main2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/main2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/main2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int number_returner(void); + +int main(void) { + return number_returner() == 100 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int be_seeing_you(void); + +int main(void) { + return be_seeing_you() == 6 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,30 @@ +gen = find_program('codegen') # Should use overridden value set in "subdir". + +src = custom_target('arrival', + input : 'source.desc', + output : 'file.c', + command : [gen, '@INPUT@', '@OUTPUT@'] + ) + +e = executable('six', 'main.c', src) + +test('six', e) + +# Override stuff with an executables +meson.override_find_program('six_meson_exe', e) + + +# The same again, but this time with a program that was generated +# with configure_file. + +gen = find_program('gencodegen') + +src = custom_target('hundred', + input : 'source2.desc', + output : 'file2.c', + command : [gen, '@INPUT@', '@OUTPUT@'] + ) + +e = executable('hundred', 'main2.c', src) + +test('hundred', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/source2.desc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/source2.desc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/source2.desc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/source2.desc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +number_returner diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/source.desc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/source.desc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/otherdir/source.desc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/otherdir/source.desc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +be_seeing_you diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subdir/converter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subdir/converter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subdir/converter.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subdir/converter.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import sys +import pathlib + +[ifilename, ofilename] = sys.argv[1:3] + +ftempl = '''int %s(void) { + return 6; +} +''' + +d = pathlib.Path(ifilename).read_text().split('\n')[0].strip() + +pathlib.Path(ofilename).write_text(ftempl % d) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subdir/gencodegen.py.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subdir/gencodegen.py.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subdir/gencodegen.py.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subdir/gencodegen.py.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import sys +import pathlib + +[ifilename, ofilename] = sys.argv[1:3] + +ftempl = '''int %s(void) { + return @NUMBER@; +} +''' + +d = pathlib.Path(ifilename).read_text().split('\n')[0].strip() + +pathlib.Path(ofilename).write_text(ftempl % d) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +x = find_program('converter.py') + +meson.override_find_program('codegen', x) + +# Override a command with a generated script + +cdata = configuration_data() + +cdata.set('NUMBER', 100) +numprog = configure_file(input : 'gencodegen.py.in', + output : 'gencodegen.py', + configuration : cdata) + +meson.override_find_program('gencodegen', numprog) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('tools') + +exe = find_program('gencodegen') +meson.override_find_program('sometool', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subprojects/sub.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subprojects/sub.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 find override/subprojects/sub.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 find override/subprojects/sub.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +[wrap-file] +directory = sub + +[provide] +program_names = sometool diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 subdir_done/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 subdir_done/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/182 subdir_done/meson.build" 2020-01-07 21:09:14.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/182 subdir_done/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -# Should run, even though main.cpp does not exist and we call error in the last line. -# subdir_done jumps to end, so both lines are not executed. - -project('example exit', 'cpp') - -if true - subdir_done() -endif - -executable('main', 'main.cpp') -error('Unreachable') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 bothlibraries/libfile.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 bothlibraries/libfile.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 bothlibraries/libfile.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 bothlibraries/libfile.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include "mylib.h" - -DO_EXPORT int retval = 42; - -DO_EXPORT int func(void) { - return retval; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 bothlibraries/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 bothlibraries/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 bothlibraries/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 bothlibraries/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "mylib.h" - -DO_IMPORT int func(void); -DO_IMPORT int retval; - -int main(void) { - return func() == retval ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 bothlibraries/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 bothlibraries/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 bothlibraries/meson.build" 2020-01-07 21:09:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 bothlibraries/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -project('both libraries linking test', 'c') - -both_libs = both_libraries('mylib', 'libfile.c') -exe_shared = executable('prog-shared', 'main.c', link_with : both_libs.get_shared_lib()) -exe_static = executable('prog-static', 'main.c', - c_args : ['-DSTATIC_COMPILATION'], - link_with : both_libs.get_static_lib()) -exe_both = executable('prog-both', 'main.c', link_with : both_libs) - -test('runtest-shared', exe_shared) -test('runtest-static', exe_static) -test('runtest-both', exe_both) - -# Same as above, but using build_target() -both_libs2 = build_target('mylib2', 'libfile.c', target_type: 'both_libraries') -exe_shared2 = executable('prog-shared2', 'main.c', - link_with : both_libs2.get_shared_lib()) -exe_static2 = executable('prog-static2', 'main.c', - c_args : ['-DSTATIC_COMPILATION'], - link_with : both_libs2.get_static_lib()) -exe_both2 = executable('prog-both2', 'main.c', link_with : both_libs2) - -test('runtest-shared-2', exe_shared2) -test('runtest-static-2', exe_static2) -test('runtest-both-2', exe_both2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 bothlibraries/mylib.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 bothlibraries/mylib.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 bothlibraries/mylib.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 bothlibraries/mylib.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#pragma once - -#ifdef _WIN32 - #ifdef STATIC_COMPILATION - #define DO_IMPORT extern - #else - #define DO_IMPORT __declspec(dllimport) - #endif - #define DO_EXPORT __declspec(dllexport) -#else - #define DO_IMPORT extern - #define DO_EXPORT -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/headers/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/headers/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/headers/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/headers/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#error "Included C sources that shouldn't be." diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/headers/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/headers/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/headers/foo.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/headers/foo.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +int foo(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,25 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#include "foo.h" + +int main(void) { + int a = foo(); + if (a == 1) { + return 0; + } else { + return 1; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,32 @@ +# Copyright © 2018 Intel Corporation +# +# 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. + +dec_sub_dep = declare_dependency( + include_directories : include_directories('headers'), +) + +dec_dep = declare_dependency( + sources : files('headers/foo.c'), + dependencies : dec_sub_dep, +) + +sub_dep = dec_dep.partial_dependency(includes : true) + +dec_exe = executable( + 'declare_dep', + files('main.c', 'other.c'), + dependencies : sub_dep, +) + +test('Declare Dependency', dec_exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/other.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/other.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/declare_dependency/other.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/declare_dependency/other.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#include "foo.h" + +int foo(void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/183 partial dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/183 partial dependency/meson.build" 2021-10-23 16:50:01.000000000 +0000 @@ -0,0 +1,17 @@ +# Copyright © 2018 Intel Corporation +# +# 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. + +project('partial dependency', ['c', 'cpp']) + +subdir('declare_dependency') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/file.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/file.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/file.c.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/file.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include -const char* does_it_work(void) { - printf("{NAME}\n"); - return "yes it does"; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/file.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/file.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/file.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/file.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os - -with open(sys.argv[1]) as fh: - content = fh.read().replace("{NAME}", sys.argv[2]) - -with open(os.path.join(sys.argv[3]), 'w', errors='replace') as fh: - fh.write(content) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/find.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/find.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/find.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/find.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -for fh in os.listdir('.'): - if os.path.isfile(fh): - if fh.endswith('.c'): - sys.stdout.write(fh + '\0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/fun.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/fun.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/fun.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/fun.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int a_fun(void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#include - -const char* does_it_work(void); - -int a_fun(void); - -int main(void) { - if(strcmp(does_it_work(), "yes it does") != 0) { - return -a_fun(); - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 escape and unicode/meson.build" 2020-01-07 21:09:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 escape and unicode/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -project('180 escape', 'c') - -gen = generator(find_program('file.py'), arguments:['@INPUT@', 'erd\u0151', '@OUTPUT@'], output: '@BASENAME@') - -gen_file = gen.process('file.c.in') - -find_file_list = run_command(find_program('find.py')) -assert(find_file_list.returncode() == 0, 'Didn\'t find any files.') - -# Strings should support both octal \ooo and hex \xhh encodings - -found_files_oct = [] -foreach l : find_file_list.stdout().strip('\0').split('\000') - found_files_oct += [files(l)] -endforeach - -test('first', executable('first', found_files_oct + [gen_file])) - -found_files_hex = [] -foreach l : find_file_list.stdout().strip('\x00').split('\x00') - found_files_hex += [files(l)] -endforeach - -test('second', executable('second', found_files_hex + [gen_file])) - -# Unrecognized and malformed escape sequences are literal - -malformed = [ - [ '\c', 'c' ], - [ '\Uabcdefghi', 'Uabcdefghi'], - [ '\u123 ', 'u123 '], - [ '\xqr', 'xqr'], -] - -foreach m : malformed - assert(m[0].endswith(m[1]), 'bad escape sequence had unexpected end') - assert(m[0].startswith('\\'), 'bad escape sequence had unexpected start') -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 openmp/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 openmp/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 openmp/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 openmp/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include +#include + +int main(void) { +#ifdef _OPENMP + if (omp_get_max_threads() == 2) { + return 0; + } else { + printf("Max threads is %d not 2.\n", omp_get_max_threads()); + return 1; + } +#else + printf("_OPENMP is not defined; is OpenMP compilation working?\n"); + return 1; +#endif +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 openmp/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 openmp/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 openmp/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 openmp/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include +#include + +int main(void) { +#ifdef _OPENMP + if (omp_get_max_threads() == 2) { + return 0; + } else { + std::cout << "Max threads is " << omp_get_max_threads() << " not 2." << std::endl; + return 1; + } +#else + printf("_OPENMP is not defined; is OpenMP compilation working?\n"); + return 1; +#endif +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 openmp/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 openmp/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 openmp/main.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 openmp/main.f90" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +use, intrinsic :: iso_fortran_env, only: stderr=>error_unit +use omp_lib + +if (omp_get_max_threads() /= 2) then + write(stderr, *) 'Max Fortran threads is', omp_get_max_threads(), 'not 2.' + stop 1 +endif + +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 openmp/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 openmp/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/184 openmp/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/184 openmp/meson.build" 2021-10-23 16:50:04.000000000 +0000 @@ -0,0 +1,58 @@ +project('openmp', 'c') + +cc = meson.get_compiler('c') +if cc.get_id() == 'gcc' and cc.version().version_compare('<4.2.0') + error('MESON_SKIP_TEST gcc is too old to support OpenMP.') +endif +if cc.get_id() == 'clang' and cc.version().version_compare('<3.7.0') + error('MESON_SKIP_TEST clang is too old to support OpenMP.') +endif +if cc.get_id() == 'msvc' and cc.version().version_compare('<17') + error('MESON_SKIP_TEST msvc is too old to support OpenMP.') +endif +if cc.get_id() == 'clang-cl' + error('MESON_SKIP_TEST clang-cl does not support OpenMP.') +endif +if cc.get_id() == 'clang' and host_machine.system() == 'windows' + error('MESON_SKIP_TEST Windows clang does not support OpenMP.') +endif +if host_machine.system() == 'darwin' + error('MESON_SKIP_TEST macOS does not support OpenMP.') +endif + +openmp = dependency('openmp') +env = environment() +env.set('OMP_NUM_THREADS', '2') + +exec = executable('exec', + 'main.c', + dependencies : [openmp]) +test('OpenMP C', exec, env : env) + +if not(build_machine.system() == 'windows' and cc.get_id() == 'pgi') + if add_languages('cpp', required : false) + execpp = executable('execpp', + 'main.cpp', + dependencies : [openmp]) + test('OpenMP C++', execpp, env : env) + endif +endif + +if add_languages('fortran', required : false) + # Mixing compilers (msvc/clang with gfortran) does not seem to work on Windows. + if build_machine.system() != 'windows' or cc.get_id() == 'gnu' + exef = executable('exef', + 'main.f90', + dependencies : [openmp]) + test('OpenMP Fortran', exef, env : env) + + openmp_f = dependency('openmp', language : 'fortran') + exe_f = executable('exe_f', + 'main.f90', + dependencies : [openmp_f]) + test('OpenMP Fortran-specific', exe_f, env : env) + endif +endif + +# Check we can apply a version constraint +dependency('openmp', version: '>=@0@'.format(openmp.version())) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 has link arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 has link arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 has link arg/meson.build" 2020-01-07 21:09:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 has link arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -project('has link arg', 'c', 'cpp') - -cc = meson.get_compiler('c') -cpp = meson.get_compiler('cpp') - -if cc.get_argument_syntax() == 'msvc' - is_arg = '/OPT:REF' - useless = '/DEBUG' - isnt_arg = '/iambroken' -else - is_arg = '-Wl,-L/tmp' - useless = '-Wl,-L/usr' - isnt_arg = '-Wl,-iambroken' -endif - -assert(cc.has_link_argument(is_arg), 'Arg that should have worked does not work.') -assert(cpp.has_link_argument(is_arg), 'Arg that should have worked does not work.') - -if cc.get_id() != 'pgi' -assert(not cc.has_link_argument(isnt_arg), 'Arg that should be broken is not.') -assert(not cpp.has_link_argument(isnt_arg), 'Arg that should be broken is not.') - -assert(cc.get_supported_link_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') -assert(cpp.get_supported_link_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') - -# Have useless at the end to ensure that the search goes from front to back. -l1 = cc.first_supported_link_argument([isnt_arg, is_arg, isnt_arg, useless]) -l2 = cc.first_supported_link_argument(isnt_arg, isnt_arg, isnt_arg) - -assert(l1.length() == 1, 'First supported returned wrong result.') -assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') -assert(l2.length() == 0, 'First supported did not return empty array.') - -l1 = cpp.first_supported_link_argument([isnt_arg, is_arg, isnt_arg, useless]) -l2 = cpp.first_supported_link_argument(isnt_arg, isnt_arg, isnt_arg) - -assert(l1.length() == 1, 'First supported returned wrong result.') -assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') -assert(l2.length() == 0, 'First supported did not return empty array.') - -assert(not cc.has_multi_link_arguments([isnt_arg, is_arg]), 'Arg that should be broken is not.') - -assert(not cc.has_link_argument('-Wl,-z,nodelete42'), 'Did not detect wrong -z linker argument') -endif - -assert(cc.has_multi_link_arguments(is_arg), 'Arg that should have worked does not work.') -assert(cc.has_multi_link_arguments([useless, is_arg]), 'Arg that should have worked does not work.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 same target name/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 same target name/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 same target name/file.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 same target name/file.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 same target name/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 same target name/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 same target name/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 same target name/meson.build" 2021-10-23 16:50:01.000000000 +0000 @@ -0,0 +1,4 @@ +project('same name', 'c') + +static_library('foo', 'file.c') +subdir('sub') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 same target name/sub/file2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 same target name/sub/file2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 same target name/sub/file2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 same target name/sub/file2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 5; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 same target name/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 same target name/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/185 same target name/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/185 same target name/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +static_library('foo', 'file2.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/foo.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int meson_test_main_foo(void) { return 10; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/main.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include - -int meson_test_main_foo(void); -int meson_test_subproj_foo(void); - -int main(void) { - if (meson_test_main_foo() != 10) { - printf("Failed meson_test_main_foo\n"); - return 1; - } - if (meson_test_subproj_foo() != 20) { - printf("Failed meson_test_subproj_foo\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/meson.build" 2020-01-07 21:09:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('subdir targets', 'c') - -# Idea behind this test is to create targets with identical name -# but different output files. We can do this by choosing different -# name_prefix of libraries. Target id does not depend on name_prefix. - -main_foo = static_library('foo', 'foo.c', name_prefix : 'main') -subdir('subdir') # defines subdir_foo - -exe = executable('prog', 'main.c', link_with : [main_foo, subdir_foo]) -test('main test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/subdir/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/subdir/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/subdir/foo.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/subdir/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int meson_test_subproj_foo(void) { return 20; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 same target name flat layout/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 same target name flat layout/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -subdir_foo = static_library('foo', 'foo.c', name_prefix : 'subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 test depends/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 test depends/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 test depends/gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 test depends/gen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import sys + + +def main(): + with open(sys.argv[1], 'w') as out: + out.write(sys.argv[2]) + out.write('\n') + + +if __name__ == '__main__': + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 test depends/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 test depends/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 test depends/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 test depends/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 test depends/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 test depends/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 test depends/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 test depends/meson.build" 2021-10-23 16:50:03.000000000 +0000 @@ -0,0 +1,26 @@ +project('test depends', 'c') + +gen = find_program('gen.py') + +custom_dep = custom_target('custom_dep', + build_by_default : false, + output : 'custom_dep.txt', + command : [gen, '@OUTPUT@', 'custom_dep'], +) + +exe_dep = executable('exe_dep', 'main.c', + build_by_default : false, +) + +test_prog = find_program('test.py') +test('string dependencies', test_prog, + args : [ + # This is declared for convenience, + # real use case might have some obscure method + # to find these dependencies, e.g. automatic plugin loading. + 'custom_dep.txt', + exe_dep.full_path(), + ], + depends : [custom_dep, exe_dep], + workdir : meson.current_build_dir(), +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 test depends/test.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 test depends/test.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/186 test depends/test.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/186 test depends/test.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +import os +import os.path +import sys + + +def main(): + print('Looking in:', os.getcwd()) + not_found = list() + for f in sys.argv[1:]: + if not os.path.exists(f): + not_found.append(f) + if not_found: + print('Not found:', ', '.join(not_found)) + sys.exit(1) + + +if __name__ == '__main__': + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 args flattening/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 args flattening/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 args flattening/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 args flattening/meson.build" 2021-10-23 16:50:03.000000000 +0000 @@ -0,0 +1,31 @@ +project('args flattening') + +arr = get_variable('does-not-exist', ['bar', 'baz']) +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') + +arr = meson.get_external_property('does-not-exist', ['bar', 'baz']) +assert(arr == ['bar', 'baz'], 'meson.get_external_property with array fallback is broken') + +arr = meson.get_external_property('does-not-exist', ['bar', 'baz'], native: true) +assert(arr == ['bar', 'baz'], 'meson.get_external_property native:true with array fallback is broken') + +arr = meson.get_external_property('does-not-exist', ['bar', 'baz'], native: false) +assert(arr == ['bar', 'baz'], 'meson.get_external_property native:false with array fallback is broken') + +# Test deprecated behaviour + +conf.set(['foo', 'bar']) +message(conf.get('foo')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/meson.build" 2020-01-07 21:09:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -project('find program override', 'c') - -gencodegen = find_program('gencodegen', required : false) - -assert(not gencodegen.found(), 'gencodegen is an internal program, should not be found') - -# Test the check-if-found-else-override workflow -if not gencodegen.found() - subdir('subdir') -endif - -subdir('otherdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/main2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/main2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/main2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/main2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int number_returner(void); - -int main(void) { - return number_returner() == 100 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int be_seeing_you(void); - -int main(void) { - return be_seeing_you() == 6 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/meson.build" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -gen = find_program('codegen') # Should use overridden value set in "subdir". - -src = custom_target('arrival', - input : 'source.desc', - output : 'file.c', - command : [gen, '@INPUT@', '@OUTPUT@'] - ) - -e = executable('six', 'main.c', src) - -test('six', e) - -# The same again, but this time with a program that was generated -# with configure_file. - -gen = find_program('gencodegen') - -src = custom_target('hundred', - input : 'source2.desc', - output : 'file2.c', - command : [gen, '@INPUT@', '@OUTPUT@'] - ) - -e = executable('hundred', 'main2.c', src) - -test('hundred', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/source2.desc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/source2.desc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/source2.desc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/source2.desc" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -number_returner diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/source.desc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/source.desc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/otherdir/source.desc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/otherdir/source.desc" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -be_seeing_you diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/subdir/converter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/subdir/converter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/subdir/converter.py" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/subdir/converter.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import pathlib - -[ifilename, ofilename] = sys.argv[1:3] - -ftempl = '''int %s(void) { - return 6; -} -''' - -d = pathlib.Path(ifilename).read_text().split('\n')[0].strip() - -pathlib.Path(ofilename).write_text(ftempl % d) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/subdir/gencodegen.py.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/subdir/gencodegen.py.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/subdir/gencodegen.py.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/subdir/gencodegen.py.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import pathlib - -[ifilename, ofilename] = sys.argv[1:3] - -ftempl = '''int %s(void) { - return @NUMBER@; -} -''' - -d = pathlib.Path(ifilename).read_text().split('\n')[0].strip() - -pathlib.Path(ofilename).write_text(ftempl % d) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/187 find override/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/187 find override/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -x = find_program('converter.py') - -meson.override_find_program('codegen', x) - -# Override a command with a generated script - -cdata = configuration_data() - -cdata.set('NUMBER', 100) -numprog = configure_file(input : 'gencodegen.py.in', - output : 'gencodegen.py', - configuration : cdata) - -meson.override_find_program('gencodegen', numprog) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 dict/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 dict/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 dict/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 dict/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,82 @@ +project('dict test', 'c') + +dict = {'foo' : 'bar', + 'baz' : 'foo', + 'foo bar': 'baz'} + +exe = executable('prog', sources : ['prog.c']) + +i = 0 + +foreach key, value : dict + test('dict test @0@'.format(key), exe, + args : [dict[key], value]) + i += 1 +endforeach + +assert(i == 3, 'There should be three elements in that dictionary') + +empty_dict = {} + +foreach key, value : empty_dict + assert(false, 'This dict should be empty') +endforeach + +d1 = empty_dict + {'a' : 'b'} +assert(d1 == {'a' : 'b'}, 'dict addition is not working') + +d2 = d1 + {'a' : 'b2', 'c' : 'd'} +assert(d2 == {'a' : 'b2', 'c' : 'd'}, 'dict addition is not working') +assert(d1 == {'a' : 'b'}, 'dict should be immutable') + +d3 = d2 +d3 += {'e' : 'f'} +assert(d3 == {'a' : 'b2', 'c' : 'd', 'e' : 'f'}, 'dict plusassign is not working') +assert(d2 == {'a' : 'b2', 'c' : 'd'}, 'dict should be immutable') + +dict1 = {} + +# A variable to be used as a key +testkey1 = 'myKey1' +testkey2 = 'myKey2' + +# Add new entry using the variable +dict1 += {testkey1 : 'myValue'} +dict1 += {testkey2 : 42} + +# Test that the stored values are correct +assert(dict1[testkey1] == 'myValue', + 'Incorrect string value retrieved from dictionary - variable key') +assert(dict1['myKey1'] == 'myValue', + 'Incorrect string value retrieved from dictionary - literal key') +assert(dict1[testkey2] == 42, + 'Incorrect int value retrieved from dictionary - variable key') +assert(dict1['myKey2'] == 42, + 'Incorrect int value retrieved from dictionary - literal key') + +d = {testkey1 : 1} +assert(d[testkey1] == 1, + 'Incorrect int value retrieved from dictionary - variable key') +assert(d['myKey1'] == 1, + 'Incorrect int value retrieved from dictionary - literal key') + +d = {'1' / '2' : 1, join_paths('a', 'b') : 2} +k1 = '1' / '2' +k2 = join_paths('a', 'b') +assert(d[k1] == 1, 'Incorrect expression evaluation in dictionary key') +assert(d[k2] == 2, 'Incorrect expression evaluation in dictionary key') + +d = {'a' + 'b' : 1} +assert(d['a' + 'b'] == 1, 'Incorrect expression evaluation in dictionary key') +assert(d['ab'] == 1, 'Incorrect expression evaluation in dictionary key') + +# Complex types +d = { + 'sanity': 1, + 'host': host_machine, + 'meson': meson, +} + +assert(d['sanity'] == 1) +assert(not is_disabler(d['meson'])) +assert(not is_disabler(d['host'])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 dict/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 dict/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 dict/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 dict/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +int main(int argc, char **argv) { + if (argc != 3) + return 1; + + return strcmp(argv[1], argv[2]); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/headers/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/headers/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/headers/foo.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/headers/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -/* Copyright © 2018 Intel Corporation - * - * 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. - */ - -#error "Included C sources that shouldn't be." diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/headers/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/headers/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/headers/foo.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/headers/foo.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -/* Copyright © 2018 Intel Corporation - * - * 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. - */ - -int foo(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -/* Copyright © 2018 Intel Corporation - * - * 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. - */ - -#include "foo.h" - -int main(void) { - int a = foo(); - if (a == 1) { - return 0; - } else { - return 1; - } -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -# Copyright © 2018 Intel Corporation -# -# 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. - -dec_sub_dep = declare_dependency( - include_directories : include_directories('headers'), -) - -dec_dep = declare_dependency( - sources : files('headers/foo.c'), - dependencies : dec_sub_dep, -) - -sub_dep = dec_dep.partial_dependency(includes : true) - -dec_exe = executable( - 'declare_dep', - files('main.c', 'other.c'), - dependencies : sub_dep, -) - -test('Declare Dependency', dec_exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/other.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/other.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/declare_dependency/other.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/declare_dependency/other.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -/* Copyright © 2018 Intel Corporation - * - * 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. - */ - -#include "foo.h" - -int foo(void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/188 partial dependency/meson.build" 2020-01-07 21:09:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/188 partial dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -# Copyright © 2018 Intel Corporation -# -# 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. - -project('partial dependency', ['c', 'cpp']) - -subdir('declare_dependency') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 check header/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 check header/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 check header/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 check header/meson.build" 2021-10-23 16:50:06.000000000 +0000 @@ -0,0 +1,48 @@ +project('check header', 'c', 'cpp') + +host_system = host_machine.system() + +non_existent_header = 'ouagadougou.h' + +# Copy it into the builddir to ensure that it isn't found even if it's there +configure_file(input : non_existent_header, + output : non_existent_header, + copy: true) + +fallback = '' + +foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')] + assert(comp.check_header('stdio.h', prefix : fallback), 'Stdio missing.') + + # stdio.h doesn't actually need stdlib.h, but just test that setting the + # prefix does not result in an error. + assert(comp.check_header('stdio.h', prefix : '#include ' + fallback), + 'Stdio missing.') + + # Test that check_header behaves differently than has_header. The second + # check without windows.h will fail with check_header. + # We only do this check on MSVC because MinGW often defines its own wrappers + # that pre-include windows.h + if comp.get_id() == 'msvc' + assert(comp.check_header('XInput.h', prefix : '#include ' + fallback), + 'XInput.h should not be missing on Windows') + assert(not comp.check_header('XInput.h'), 'XInput.h needs windows.h') + endif + + # Test that the following GCC bug doesn't happen: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005 + # https://github.com/mesonbuild/meson/issues/1458 + if host_system == 'linux' + assert(comp.check_header('linux/socket.h', prefix : fallback), + 'Could not find ') + if comp.has_header('intrin.h', prefix : fallback) + assert(not comp.check_header('intrin.h'), + 'intrin.h should not be usable on linux') + endif + endif + + # This header exists in the source and the builddir, but we still must not + # find it since we are looking in the system directories. + assert(not comp.check_header(non_existent_header, prefix : fallback), + 'Found non-existent header.') +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 check header/ouagadougou.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 check header/ouagadougou.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 check header/ouagadougou.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 check header/ouagadougou.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#define OMG_THIS_SHOULDNT_BE_FOUND diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 openmp/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 openmp/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 openmp/main.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 openmp/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include -#include - -int main(void) { -#ifdef _OPENMP - if (omp_get_max_threads() == 2) { - return 0; - } else { - printf("Max threads is %d not 2.\n", omp_get_max_threads()); - return 1; - } -#else - printf("_OPENMP is not defined; is OpenMP compilation working?\n"); - return 1; -#endif -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 openmp/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 openmp/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 openmp/main.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 openmp/main.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include -#include - -int main(void) { -#ifdef _OPENMP - if (omp_get_max_threads() == 2) { - return 0; - } else { - std::cout << "Max threads is " << omp_get_max_threads() << " not 2." << std::endl; - return 1; - } -#else - printf("_OPENMP is not defined; is OpenMP compilation working?\n"); - return 1; -#endif -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 openmp/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 openmp/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 openmp/main.f90" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 openmp/main.f90" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -use, intrinsic :: iso_fortran_env, only: stderr=>error_unit -use omp_lib - -if (omp_get_max_threads() /= 2) then - write(stderr, *) 'Max Fortran threads is', omp_get_max_threads(), 'not 2.' - stop 1 -endif - -end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 openmp/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 openmp/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/189 openmp/meson.build" 2020-01-07 21:09:23.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/189 openmp/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -project('openmp', 'c') - -cc = meson.get_compiler('c') -if cc.get_id() == 'gcc' and cc.version().version_compare('<4.2.0') - error('MESON_SKIP_TEST gcc is too old to support OpenMP.') -endif -if cc.get_id() == 'clang' and cc.version().version_compare('<3.7.0') - error('MESON_SKIP_TEST clang is too old to support OpenMP.') -endif -if cc.get_id() == 'msvc' and cc.version().version_compare('<17') - error('MESON_SKIP_TEST msvc is too old to support OpenMP.') -endif -if cc.get_id() == 'clang-cl' - error('MESON_SKIP_TEST clang-cl does not support OpenMP.') -endif -if cc.get_id() == 'clang' and host_machine.system() == 'windows' - error('MESON_SKIP_TEST Windows clang does not support OpenMP.') -endif -if host_machine.system() == 'darwin' - error('MESON_SKIP_TEST macOS does not support OpenMP.') -endif - -openmp = dependency('openmp') -env = environment() -env.set('OMP_NUM_THREADS', '2') - -exec = executable('exec', - 'main.c', - dependencies : [openmp]) -test('OpenMP C', exec, env : env) - -if not(build_machine.system() == 'windows' and cc.get_id() == 'pgi') - if add_languages('cpp', required : false) - execpp = executable('execpp', - 'main.cpp', - dependencies : [openmp]) - test('OpenMP C++', execpp, env : env) - endif -endif - -if add_languages('fortran', required : false) - # Mixing compilers (msvc/clang with gfortran) does not seem to work on Windows. - if build_machine.system() != 'windows' or cc.get_id() == 'gnu' - exef = executable('exef', - 'main.f90', - dependencies : [openmp]) - test('OpenMP Fortran', exef, env : env) - - openmp_f = dependency('openmp', language : 'fortran') - exe_f = executable('exe_f', - 'main.f90', - dependencies : [openmp_f]) - test('OpenMP Fortran-specific', exe_f, env : env) - endif -endif - -# Check we can apply a version constraint -dependency('openmp', version: '>=@0@'.format(openmp.version())) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 array/func.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 array/func.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 array/func.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 array/func.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int func(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 array/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 array/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 array/meson.build" 2020-01-07 21:06:26.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 array/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('array test', 'c') - -arr = [ - 'func.c', - 'prog.c'] - -exe = executable('prog', sources : arr) -test('arr test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 array/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 array/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 array/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 array/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -extern int func(void); - -int main(void) { return func(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/include/func.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/include/func.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/include/func.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/include/func.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef FUNC_H__ +#define FUNC_H__ + +int func(void); + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/meson.build" 2021-10-23 16:47:54.000000000 +0000 @@ -0,0 +1,4 @@ +project('include dir test', 'c') + +inc = include_directories('include') +subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/src/func.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/src/func.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/src/func.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/src/func.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "func.h" + +int func(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +exe = executable('prog', 'prog.c', 'func.c', include_directories : inc) +test('inc test', exe) + +exe2 = executable('prog2', 'prog.c', 'func.c', include_directories : [['../include']]) +test('inc test 2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/src/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/src/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/18 includedir/src/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/18 includedir/src/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "func.h" + +int main(void) { + return func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/config.h.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/config.h.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#define MESSAGE "@var@" +#define OTHER "@other@" "@second@" "@empty@" + +#mesondefine BE_TRUE +#mesondefine SHOULD_BE_UNDEF diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/data_source.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/foo.1" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/foo.1" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/foo.1" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/foo.1" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +this is a man page of foo.1 its contents are irrelevant diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/meson.build" 2021-10-23 16:50:06.000000000 +0000 @@ -0,0 +1,59 @@ +project('install_mode test', 'c', + default_options : ['install_umask=027', 'libdir=libtest']) + +if build_machine.system() == 'windows' + error('MESON_SKIP_TEST: install_mode test requires a Unix-like OS') +endif + +# confirm no regressions in install_data +install_data('runscript.sh', + install_dir : get_option('bindir'), + install_mode : ['rwxr-sr-x', 'root', 0]) + +# confirm no regressions in install_subdir +install_subdir('sub1', + install_dir : 'share', + install_mode : ['rwxr-x--t', 'root']) + +install_subdir('sub2', + install_dir : 'share') + +# test install_mode in configure_file +conf = configuration_data() +conf.set('var', 'mystring') +conf.set('other', 'string 2') +conf.set('second', ' bonus') +conf.set('BE_TRUE', true) +configure_file(input : 'config.h.in', + output : 'config.h', + configuration : conf, + install_dir : 'include', + install_mode : 'rw-rwSr--') + +# test install_mode in custom_target +custom_target('bindat', + output : 'data.dat', + input : 'data_source.txt', + command : ['cp', '@INPUT@', '@OUTPUT@'], + install : true, + install_dir : 'subdir', + install_mode : 'rw-rwSr--') + +# test install_mode in install_headers +install_headers('rootdir.h', + install_mode : 'r--r--r-T') + +# test install_mode in install_man +install_man('foo.1', + install_mode : 'r--r--r-T') + +# test install_mode in executable +executable('trivialprog', + sources : 'trivial.c', + install : true, + install_mode : ['rwxr-sr-x', 'root', 'root']) + +# test install_mode in static_library +static_library('stat', 'stat.c', + install : true, + install_mode : ['rw---Sr--']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/rootdir.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/rootdir.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/rootdir.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/rootdir.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +/* This header goes to include dir root. */ + +int root_func(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/runscript.sh" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/runscript.sh" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/runscript.sh" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/runscript.sh" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "Runscript" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/stat.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/stat.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/stat.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/stat.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int func(void) { return 933; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/sub1/second.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/sub1/second.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/sub1/second.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/sub1/second.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Test that multiple install_subdirs meld their results. \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/runscript.sh"}, + {"type": "exe", "file": "usr/bin/trivialprog"}, + {"type": "pdb", "file": "usr/bin/trivialprog"}, + {"type": "file", "file": "usr/include/config.h"}, + {"type": "file", "file": "usr/include/rootdir.h"}, + {"type": "file", "file": "usr/libtest/libstat.a"}, + {"type": "file", "file": "usr/share/man/man1/foo.1"}, + {"type": "file", "file": "usr/share/sub1/second.dat"}, + {"type": "file", "file": "usr/share/sub2/stub"}, + {"type": "file", "file": "usr/subdir/data.dat"} + ], + "do_not_set_opts": ["libdir"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/trivial.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/trivial.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 install_mode/trivial.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 install_mode/trivial.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("Trivial test is working.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 same target name/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 same target name/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 same target name/file.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 same target name/file.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 same target name/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 same target name/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 same target name/meson.build" 2020-01-07 21:09:24.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 same target name/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('same name', 'c') - -static_library('foo', 'file.c') -subdir('sub') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 same target name/sub/file2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 same target name/sub/file2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 same target name/sub/file2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 same target name/sub/file2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 5; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 same target name/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 same target name/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/190 same target name/sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/190 same target name/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -static_library('foo', 'file2.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 subproject array version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 subproject array version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 subproject array version/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 subproject array version/meson.build" 2021-10-23 16:50:05.000000000 +0000 @@ -0,0 +1,3 @@ +project('master', 'c') + +x = subproject('foo', version : ['>=1.0.0', '<2.0']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 subproject array version/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 subproject array version/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 subproject array version/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 subproject array version/subprojects/foo/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +project('foo', 'c', version : '1.0.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 test depends/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 test depends/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 test depends/gen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 test depends/gen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -import sys - - -def main(): - with open(sys.argv[1], 'w') as out: - out.write(sys.argv[2]) - out.write('\n') - - -if __name__ == '__main__': - main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 test depends/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 test depends/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 test depends/main.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 test depends/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 test depends/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 test depends/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 test depends/meson.build" 2020-01-07 21:09:24.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 test depends/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -project('test depends', 'c') - -gen = find_program('gen.py') - -custom_dep = custom_target('custom_dep', - build_by_default : false, - output : 'custom_dep.txt', - command : [gen, '@OUTPUT@', 'custom_dep'], -) - -exe_dep = executable('exe_dep', 'main.c', - build_by_default : false, -) - -test_prog = find_program('test.py') -test('string dependencies', test_prog, - args : [ - # This is declared for convenience, - # real use case might have some obscure method - # to find these dependencies, e.g. automatic plugin loading. - 'custom_dep.txt', - exe_dep.full_path(), - ], - depends : [custom_dep, exe_dep], - workdir : meson.current_build_dir(), -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 test depends/test.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 test depends/test.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/191 test depends/test.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/191 test depends/test.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#!/usr/bin/env python3 - -import os -import os.path -import sys - - -def main(): - print('Looking in:', os.getcwd()) - not_found = list() - for f in sys.argv[1:]: - if not os.path.exists(f): - not_found.append(f) - if not_found: - print('Not found:', ', '.join(not_found)) - sys.exit(1) - - -if __name__ == '__main__': - main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/192 args flattening/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/192 args flattening/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/192 args flattening/meson.build" 2020-01-07 21:09:25.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/192 args flattening/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -project('args flattening') - -arr = get_variable('does-not-exist', ['bar', 'baz']) - -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') - -# Test deprecated behaviour - -conf.set(['foo', 'bar']) - -message(conf.get('foo')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/192 feature option/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/192 feature option/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/192 feature option/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/192 feature option/meson.build" 2021-10-23 16:50:07.000000000 +0000 @@ -0,0 +1,62 @@ +project('feature user option', 'c') + +feature_opts = get_option('auto_features') +required_opt = get_option('required') +optional_opt = get_option('optional') +disabled_opt = get_option('disabled') + +assert(not feature_opts.enabled(), 'Should be auto option') +assert(not feature_opts.disabled(), 'Should be auto option') +assert(feature_opts.auto(), 'Should be auto option') +assert(feature_opts.allowed(), 'Should be auto option') + +assert(required_opt.enabled(), 'Should be enabled option') +assert(not required_opt.disabled(), 'Should be enabled option') +assert(not required_opt.auto(), 'Should be enabled option') +assert(required_opt.allowed(), 'Should be enabled option') +assert(required_opt.require(true, error_message: 'xyz').enabled(), 'Should be enabled option') +assert(required_opt.disable_auto_if(true).enabled(), 'Should be enabled option') +assert(required_opt.disable_auto_if(false).enabled(), 'Should be enabled option') + +assert(not optional_opt.enabled(), 'Should be auto option') +assert(not optional_opt.disabled(), 'Should be auto option') +assert(optional_opt.auto(), 'Should be auto option') +assert(optional_opt.allowed(), 'Should be auto option') +assert(optional_opt.require(true).auto(), 'Should be auto option') +assert(optional_opt.require(false, error_message: 'xyz').disabled(), 'Should be disabled auto option') +assert(optional_opt.disable_auto_if(true).disabled(), 'Should be disabled auto option') +assert(optional_opt.disable_auto_if(false).auto(), 'Should be auto option') + +assert(not disabled_opt.enabled(), 'Should be disabled option') +assert(disabled_opt.disabled(), 'Should be disabled option') +assert(not disabled_opt.auto(), 'Should be disabled option') +assert(not disabled_opt.allowed(), 'Should be disabled option') +assert(disabled_opt.require(true).disabled(), 'Should be disabled option') +assert(disabled_opt.require(false, error_message: 'xyz').disabled(), 'Should be disabled option') +assert(disabled_opt.disable_auto_if(true).disabled(), 'Should be disabled option') +assert(disabled_opt.disable_auto_if(false).disabled(), 'Should be disabled option') + +dep = dependency('threads', required : required_opt) +assert(dep.found(), 'Should find required "threads" dep') + +dep = dependency('threads', required : optional_opt) +assert(dep.found(), 'Should find optional "threads" dep') + +dep = dependency('threads', required : disabled_opt) +assert(not dep.found(), 'Should not find disabled "threads" dep') + +dep = dependency('notfounddep', required : optional_opt) +assert(not dep.found(), 'Should not find optional "notfounddep" dep') + +dep = dependency('notfounddep', required : disabled_opt) +assert(not dep.found(), 'Should not find disabled "notfounddep" dep') + +cc = meson.get_compiler('c') +lib = cc.find_library('m', required : disabled_opt) +assert(not lib.found(), 'Should not find "m" library') + +cp = find_program('cp', required : disabled_opt) +assert(not cp.found(), 'Should not find "cp" program') + +found = add_languages('cpp', required : disabled_opt) +assert(not found, 'Should not find "cpp" language') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/192 feature option/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/192 feature option/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/192 feature option/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/192 feature option/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +option('required', type : 'feature', value : 'enabled', description : 'An required feature') +option('optional', type : 'feature', value : 'auto', description : 'An optional feature') +option('disabled', type : 'feature', value : 'disabled', description : 'A disabled feature') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/193 dict/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/193 dict/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/193 dict/meson.build" 2020-01-07 21:09:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/193 dict/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -project('dict test', 'c') - -dict = {'foo' : 'bar', - 'baz' : 'foo', - 'foo bar': 'baz'} - -exe = executable('prog', sources : ['prog.c']) - -i = 0 - -foreach key, value : dict - test('dict test @0@'.format(key), exe, - args : [dict[key], value]) - i += 1 -endforeach - -assert(i == 3, 'There should be three elements in that dictionary') - -empty_dict = {} - -foreach key, value : empty_dict - assert(false, 'This dict should be empty') -endforeach - -d1 = empty_dict + {'a' : 'b'} -assert(d1 == {'a' : 'b'}, 'dict addition is not working') - -d2 = d1 + {'a' : 'b2', 'c' : 'd'} -assert(d2 == {'a' : 'b2', 'c' : 'd'}, 'dict addition is not working') -assert(d1 == {'a' : 'b'}, 'dict should be immutable') - -d3 = d2 -d3 += {'e' : 'f'} -assert(d3 == {'a' : 'b2', 'c' : 'd', 'e' : 'f'}, 'dict plusassign is not working') -assert(d2 == {'a' : 'b2', 'c' : 'd'}, 'dict should be immutable') - -dict1 = {} - -# A variable to be used as a key -testkey1 = 'myKey1' -testkey2 = 'myKey2' - -# Add new entry using the variable -dict1 += {testkey1 : 'myValue'} -dict1 += {testkey2 : 42} - -# Test that the stored values are correct -assert(dict1[testkey1] == 'myValue', - 'Incorrect string value retrieved from dictionary - variable key') -assert(dict1['myKey1'] == 'myValue', - 'Incorrect string value retrieved from dictionary - literal key') -assert(dict1[testkey2] == 42, - 'Incorrect int value retrieved from dictionary - variable key') -assert(dict1['myKey2'] == 42, - 'Incorrect int value retrieved from dictionary - literal key') - -d = {testkey1 : 1} -assert(d[testkey1] == 1, - 'Incorrect int value retrieved from dictionary - variable key') -assert(d['myKey1'] == 1, - 'Incorrect int value retrieved from dictionary - literal key') - -d = {'1' / '2' : 1, join_paths('a', 'b') : 2} -k1 = '1' / '2' -k2 = join_paths('a', 'b') -assert(d[k1] == 1, 'Incorrect expression evaluation in dictionary key') -assert(d[k2] == 2, 'Incorrect expression evaluation in dictionary key') - -d = {'a' + 'b' : 1} -assert(d['a' + 'b'] == 1, 'Incorrect expression evaluation in dictionary key') -assert(d['ab'] == 1, 'Incorrect expression evaluation in dictionary key') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/193 dict/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/193 dict/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/193 dict/prog.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/193 dict/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include - -int main(int argc, char **argv) { - if (argc != 3) - return 1; - - return strcmp(argv[1], argv[2]); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/193 feature option disabled/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/193 feature option disabled/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/193 feature option disabled/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/193 feature option disabled/meson.build" 2021-10-23 16:50:06.000000000 +0000 @@ -0,0 +1,23 @@ +project('feature user option', 'c', + default_options : ['auto_features=disabled']) + +feature_opts = get_option('auto_features') +required_opt = get_option('required') +optional_opt = get_option('optional') +disabled_opt = get_option('disabled') + +assert(not feature_opts.enabled(), 'Should be disabled option') +assert(feature_opts.disabled(), 'Should be disabled option') +assert(not feature_opts.auto(), 'Should be disabled option') + +assert(required_opt.enabled(), 'Should be enabled option') +assert(not required_opt.disabled(), 'Should be enabled option') +assert(not required_opt.auto(), 'Should be enabled option') + +assert(not optional_opt.enabled(), 'Auto feature should be disabled') +assert(optional_opt.disabled(), 'Auto feature should be disabled') +assert(not optional_opt.auto(), 'Auto feature should be disabled') + +assert(not disabled_opt.enabled(), 'Should be disabled option') +assert(disabled_opt.disabled(), 'Should be disabled option') +assert(not disabled_opt.auto(), 'Should be disabled option') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/193 feature option disabled/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/193 feature option disabled/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/193 feature option disabled/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/193 feature option disabled/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +option('required', type : 'feature', value : 'enabled', description : 'An required feature') +option('optional', type : 'feature', value : 'auto', description : 'An optional feature') +option('disabled', type : 'feature', value : 'disabled', description : 'A disabled feature') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 check header/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 check header/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 check header/meson.build" 2020-01-07 21:09:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 check header/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -project('check header', 'c', 'cpp') - -host_system = host_machine.system() - -non_existent_header = 'ouagadougou.h' - -# Copy it into the builddir to ensure that it isn't found even if it's there -configure_file(input : non_existent_header, - output : non_existent_header, - copy: true) - -fallback = '' - -foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')] - assert(comp.check_header('stdio.h', prefix : fallback), 'Stdio missing.') - - # stdio.h doesn't actually need stdlib.h, but just test that setting the - # prefix does not result in an error. - assert(comp.check_header('stdio.h', prefix : '#include ' + fallback), - 'Stdio missing.') - - # Test that check_header behaves differently than has_header. The second - # check without windows.h will fail with check_header. - # We only do this check on MSVC because MinGW often defines its own wrappers - # that pre-include windows.h - if comp.get_id() == 'msvc' - assert(comp.check_header('XInput.h', prefix : '#include ' + fallback), - 'XInput.h should not be missing on Windows') - assert(not comp.check_header('XInput.h'), 'XInput.h needs windows.h') - endif - - # Test that the following GCC bug doesn't happen: - # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005 - # https://github.com/mesonbuild/meson/issues/1458 - if host_system == 'linux' - assert(comp.check_header('linux/socket.h', prefix : fallback), - 'Could not find ') - if comp.has_header('intrin.h', prefix : fallback) - assert(not comp.check_header('intrin.h'), - 'intrin.h should not be usable on linux') - endif - endif - - # This header exists in the source and the builddir, but we still must not - # find it since we are looking in the system directories. - assert(not comp.check_header(non_existent_header, prefix : fallback), - 'Found non-existent header.') -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 check header/ouagadougou.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 check header/ouagadougou.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 check header/ouagadougou.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 check header/ouagadougou.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#define OMG_THIS_SHOULDNT_BE_FOUND diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 static threads/lib1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 static threads/lib1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 static threads/lib1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 static threads/lib1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#if defined _WIN32 +#include +#else +#include +#endif + +void *f(void) { +#if defined _WIN32 + return CreateThread; +#else + return pthread_create; +#endif +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 static threads/lib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 static threads/lib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 static threads/lib2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 static threads/lib2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +extern void *f(void); + +void *g(void) { + return f(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 static threads/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 static threads/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 static threads/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 static threads/meson.build" 2021-10-23 16:50:08.000000000 +0000 @@ -0,0 +1,13 @@ +project('threads', 'c') + +thread_dep = dependency('threads') + + +lib1 = static_library('lib1', 'lib1.c', + dependencies : thread_dep) + +lib2 = static_library('lib2', 'lib2.c', + link_with : lib1) + +executable('prog', 'prog.c', + link_with : lib2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 static threads/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 static threads/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/194 static threads/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/194 static threads/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +extern void *g(void); + +int main(void) { + g(); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/com/mesonbuild/genprog.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/com/mesonbuild/genprog.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/com/mesonbuild/genprog.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/com/mesonbuild/genprog.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +import os, sys, argparse + +h_templ = '''#pragma once + +int %s(void); +''' + +c_templ = '''#include"%s.h" + +int %s(void) { + return 0; +} +''' + +parser = argparse.ArgumentParser() +parser.add_argument('--searchdir', required=True) +parser.add_argument('--outdir', required=True) +parser.add_argument('ifiles', nargs='+') + +options = parser.parse_args() + +searchdir = options.searchdir +outdir = options.outdir +ifiles = options.ifiles + +rel_ofiles = [] + +for ifile in ifiles: + if not ifile.startswith(options.searchdir): + sys.exit(f'Input file {ifile} does not start with search dir {searchdir}.') + rel_ofile = ifile[len(searchdir):] + if rel_ofile[0] == '/' or rel_ofile[0] == '\\': + rel_ofile = rel_ofile[1:] + rel_ofiles.append(os.path.splitext(rel_ofile)[0]) + +ofile_bases = [os.path.join(outdir, i) for i in rel_ofiles] + +for i, ifile_name in enumerate(ifiles): + proto_name = open(ifile_name).readline().strip() + h_out = ofile_bases[i] + '.h' + c_out = ofile_bases[i] + '.c' + os.makedirs(os.path.split(ofile_bases[i])[0], exist_ok=True) + open(h_out, 'w').write(h_templ % (proto_name)) + open(c_out, 'w').write(c_templ % (proto_name, proto_name)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/com/mesonbuild/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/com/mesonbuild/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/com/mesonbuild/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/com/mesonbuild/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +gprog = find_program('genprog.py') + +gen = generator(gprog, \ + output : ['@BASENAME@.c', '@BASENAME@.h'], + arguments : ['--searchdir=@CURRENT_SOURCE_DIR@', '--outdir=@BUILD_DIR@', '@INPUT@']) + +generated = gen.process('subbie.inp') + +e = executable('testprog', 'testprog.c', generated) +test('testprog', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/com/mesonbuild/subbie.inp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/com/mesonbuild/subbie.inp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/com/mesonbuild/subbie.inp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/com/mesonbuild/subbie.inp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +subbie diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/com/mesonbuild/testprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/com/mesonbuild/testprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/com/mesonbuild/testprog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/com/mesonbuild/testprog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"subbie.h" + +int main(void) { + return subbie(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 generator in subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 generator in subdir/meson.build" 2021-10-23 16:50:09.000000000 +0000 @@ -0,0 +1,3 @@ +project('generator in subdir', 'c') + +subdir('com/mesonbuild') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/config.h.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/config.h.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#define MESSAGE "@var@" -#define OTHER "@other@" "@second@" "@empty@" - -#mesondefine BE_TRUE -#mesondefine SHOULD_BE_UNDEF diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/data_source.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/foo.1" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/foo.1" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/foo.1" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/foo.1" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -this is a man page of foo.1 its contents are irrelevant diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -usr/bin/runscript.sh -usr/bin/trivialprog?exe -?msvc:usr/bin/trivialprog.pdb -usr/include/config.h -usr/include/rootdir.h -usr/libtest/libstat.a -usr/share/man/man1/foo.1 -usr/share/sub1/second.dat -usr/share/sub2/stub -usr/subdir/data.dat diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/meson.build" 2020-01-07 21:09:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -project('install_mode test', 'c', - default_options : ['install_umask=027', 'libdir=libtest']) - -if build_machine.system() == 'windows' - error('MESON_SKIP_TEST: install_mode test requires a Unix-like OS') -endif - -# confirm no regressions in install_data -install_data('runscript.sh', - install_dir : get_option('bindir'), - install_mode : ['rwxr-sr-x', 'root', 0]) - -# confirm no regressions in install_subdir -install_subdir('sub1', - install_dir : 'share', - install_mode : ['rwxr-x--t', 'root']) - -install_subdir('sub2', - install_dir : 'share') - -# test install_mode in configure_file -conf = configuration_data() -conf.set('var', 'mystring') -conf.set('other', 'string 2') -conf.set('second', ' bonus') -conf.set('BE_TRUE', true) -configure_file(input : 'config.h.in', - output : 'config.h', - configuration : conf, - install_dir : 'include', - install_mode : 'rw-rwSr--') - -# test install_mode in custom_target -custom_target('bindat', - output : 'data.dat', - input : 'data_source.txt', - command : ['cp', '@INPUT@', '@OUTPUT@'], - install : true, - install_dir : 'subdir', - install_mode : 'rw-rwSr--') - -# test install_mode in install_headers -install_headers('rootdir.h', - install_mode : 'r--r--r-T') - -# test install_mode in install_man -install_man('foo.1', - install_mode : 'r--r--r-T') - -# test install_mode in executable -executable('trivialprog', - sources : 'trivial.c', - install : true, - install_mode : ['rwxr-sr-x', 'root', 'root']) - -# test install_mode in static_library -static_library('stat', 'stat.c', - install : true, - install_mode : ['rw---Sr--']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/rootdir.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/rootdir.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/rootdir.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/rootdir.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -/* This header goes to include dir root. */ - -int root_func(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/runscript.sh" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/runscript.sh" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/runscript.sh" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/runscript.sh" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/sh - -echo "Runscript" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/stat.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/stat.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/stat.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/stat.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int func(void) { return 933; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/sub1/second.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/sub1/second.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/sub1/second.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/sub1/second.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Test that multiple install_subdirs meld their results. \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/trivial.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/trivial.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/195 install_mode/trivial.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/195 install_mode/trivial.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("Trivial test is working.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject array version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject array version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject array version/meson.build" 2020-01-07 21:09:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject array version/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('master', 'c') - -x = subproject('foo', version : ['>=1.0.0', '<2.0']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject array version/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject array version/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject array version/subprojects/foo/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject array version/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -project('foo', 'c', version : '1.0.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/meson.build" 2021-10-23 16:50:11.000000000 +0000 @@ -0,0 +1,17 @@ +project('proj', 'c') + +auto_subproj = subproject('sub', required: get_option('use-subproject')) +assert(auto_subproj.found(), 'Subproject should always be buildable and thus found') + +auto_dep = dependency('', fallback: ['sub', 'libSub'], required: true) +assert(auto_dep.found() == true, 'Subproject is required and foundable, dependency should be found.') + +disabled_subproj = subproject('disabled_sub', required: get_option('disabled-subproject')) +assert(disabled_subproj.found() == false, 'Disabled subproject should be NOT found') + +disabled_dep = dependency('', fallback: ['disabled_sub', 'libSub'], required: false) +assert(disabled_dep.found() == false, 'Subprojetc was disabled, it should never be built.') +nothing = executable('nothing', 'nothing.c', dependencies: [disabled_dep]) + +subproj_with_missing_dep = subproject('auto_sub_with_missing_dep', required: get_option('auto-sub-with-missing-dep')) +assert(subproj_with_missing_dep.found() == false, 'Subproject with required=auto and missing dependency should be NOT found') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +option('use-subproject', type : 'feature', value : 'auto') +option('disabled-subproject', type : 'feature', value : 'disabled') +option('auto-sub-with-missing-dep', type : 'feature', value : 'auto') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/nothing.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/nothing.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/nothing.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/nothing.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('sub', 'c') + +dependency('no_way_this_exists', required: true) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +lib = static_library('sub', 'sub.c') + +libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "sub.h" + +int sub(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef SUB_H +#define SUB_H + +int sub(); + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/disabled_sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/disabled_sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/disabled_sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/disabled_sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('disabled_sub', 'c') + +subdir('lib') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/sub/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/sub/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/sub/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/sub/lib/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +lib = static_library('sub', 'sub.c') +libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/sub/lib/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/sub/lib/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/sub/lib/sub.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/sub/lib/sub.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "sub.h" + +int sub(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/sub/lib/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/sub/lib/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/sub/lib/sub.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/sub/lib/sub.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef SUB_H +#define SUB_H + +int sub(void); + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/196 subproject with features/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/196 subproject with features/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('sub', 'c') + +subdir('lib') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 feature option/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 feature option/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 feature option/meson.build" 2020-01-07 21:09:30.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 feature option/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -project('feature user option', 'c') - -feature_opts = get_option('auto_features') -required_opt = get_option('required') -optional_opt = get_option('optional') -disabled_opt = get_option('disabled') - -assert(not feature_opts.enabled(), 'Should be auto option') -assert(not feature_opts.disabled(), 'Should be auto option') -assert(feature_opts.auto(), 'Should be auto option') - -assert(required_opt.enabled(), 'Should be enabled option') -assert(not required_opt.disabled(), 'Should be enabled option') -assert(not required_opt.auto(), 'Should be enabled option') - -assert(not optional_opt.enabled(), 'Should be auto option') -assert(not optional_opt.disabled(), 'Should be auto option') -assert(optional_opt.auto(), 'Should be auto option') - -assert(not disabled_opt.enabled(), 'Should be disabled option') -assert(disabled_opt.disabled(), 'Should be disabled option') -assert(not disabled_opt.auto(), 'Should be disabled option') - -dep = dependency('threads', required : required_opt) -assert(dep.found(), 'Should find required "threads" dep') - -dep = dependency('threads', required : optional_opt) -assert(dep.found(), 'Should find optional "threads" dep') - -dep = dependency('threads', required : disabled_opt) -assert(not dep.found(), 'Should not find disabled "threads" dep') - -dep = dependency('notfounddep', required : optional_opt) -assert(not dep.found(), 'Should not find optional "notfounddep" dep') - -dep = dependency('notfounddep', required : disabled_opt) -assert(not dep.found(), 'Should not find disabled "notfounddep" dep') - -cc = meson.get_compiler('c') -lib = cc.find_library('m', required : disabled_opt) -assert(not lib.found(), 'Should not find "m" library') - -cp = find_program('cp', required : disabled_opt) -assert(not cp.found(), 'Should not find "cp" program') - -found = add_languages('cpp', required : disabled_opt) -assert(not found, 'Should not find "cpp" language') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 feature option/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 feature option/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 feature option/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 feature option/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -option('required', type : 'feature', value : 'enabled', description : 'An required feature') -option('optional', type : 'feature', value : 'auto', description : 'An optional feature') -option('disabled', type : 'feature', value : 'disabled', description : 'A disabled feature') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 function attributes/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 function attributes/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 function attributes/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 function attributes/meson.build" 2021-10-23 16:50:17.000000000 +0000 @@ -0,0 +1,111 @@ +# Copyright © 2017-2018 Intel Corporation +# +# 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. + +project('gcc func attributes', ['c', 'cpp']) + +# For msvc these will fail because msvc doesn't support __attribute__, for +# Clang and GCC, they should pass. +c = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') + +if c.get_id() == 'pgi' + error('MESON_SKIP_TEST: PGI supports its own set of features, will need a separate list for PGI to test it.') +endif + +expected_result = not ['msvc', 'clang-cl', 'intel-cl'].contains(c.get_id()) + +# Q: Why is ifunc not in this list or any of the below lists? +# A: It's too damn hard to figure out if you actually support it, since it +# requires both compiler and libc support, and there isn't a good way to +# figure that out except by running the code we're trying to test. +attributes = [ + 'aligned', + 'always_inline', + 'cold', + 'const', + 'constructor', + 'constructor_priority', + 'deprecated', + 'destructor', + 'flatten', + 'format', + 'format_arg', + 'gnu_inline', + 'hot', + 'malloc', + 'noinline', + 'nonnull', + 'noreturn', + 'nothrow', + 'pure', + 'unused', + 'used', + 'warn_unused_result', + 'weak', +] + +if c.get_id() != 'intel' + # not supported by icc as of 19.0.0 + attributes += 'weakref' +endif + +# These are unsupported on darwin with apple clang 9.1.0 +if host_machine.system() != 'darwin' + attributes += 'alias' + attributes += 'visibility' + attributes += 'alloc_size' +endif + +if ['gcc', 'intel'].contains(c.get_id()) + # not supported by clang as of 5.0.0 (at least up to 6.0.1) + attributes += 'artificial' + attributes += 'error' + attributes += 'externally_visible' + attributes += 'leaf' + attributes += 'noclone' + attributes += 'optimize' + attributes += 'warning' + + if c.get_id() == 'gcc' and c.version().version_compare('>= 7.0.0') + attributes += 'fallthrough' + endif +endif + +if get_option('mode') == 'single' + foreach a : attributes + x = c.has_function_attribute(a) + assert(x == expected_result, '@0@: @1@'.format(c.get_id(), a)) + x = cpp.has_function_attribute(a) + assert(x == expected_result, '@0@: @1@'.format(cpp.get_id(), a)) + endforeach + + win_expect = ['windows', 'cygwin'].contains(host_machine.system()) + foreach a : ['dllexport', 'dllimport'] + assert(c.has_function_attribute(a) == win_expect, + '@0@: @1@'.format(c.get_id(), a)) + assert(cpp.has_function_attribute(a) == win_expect, + '@0@: @1@'.format(cpp.get_id(), a)) + endforeach +else + if not ['msvc', 'clang-cl', 'intel-cl'].contains(c.get_id()) + multi_expected = attributes + else + multi_expected = [] + endif + + multi_check = c.get_supported_function_attributes(attributes) + assert(multi_check == multi_expected, 'get_supported_function_arguments works (C)') + multi_check = cpp.get_supported_function_attributes(attributes) + assert(multi_check == multi_expected, 'get_supported_function_arguments works (C++)') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 function attributes/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 function attributes/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 function attributes/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 function attributes/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +option( + 'mode', + type : 'combo', + choices : ['single', 'parallel'], + value : 'single', + description : 'Test the one at a time function or many at a time function.' +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 function attributes/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 function attributes/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/197 function attributes/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/197 function attributes/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "matrix": { + "options": { + "mode": [ + { "val": "single" }, + { "val": "parallel" } + ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 broken subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 broken subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 broken subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 broken subproject/meson.build" 2021-10-23 16:50:10.000000000 +0000 @@ -0,0 +1,2 @@ +project('test broken subproject') +subproject('broken', required : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 broken subproject/subprojects/broken/broken.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 broken subproject/subprojects/broken/broken.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 broken subproject/subprojects/broken/broken.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 broken subproject/subprojects/broken/broken.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#error This must not compile diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 broken subproject/subprojects/broken/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 broken subproject/subprojects/broken/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 broken subproject/subprojects/broken/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 broken subproject/subprojects/broken/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('broken', 'c') + +executable('app', 'broken.c') +assert(false, 'This subproject must fail') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 feature option disabled/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 feature option disabled/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 feature option disabled/meson.build" 2020-01-07 21:09:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 feature option disabled/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -project('feature user option', 'c', - default_options : ['auto_features=disabled']) - -feature_opts = get_option('auto_features') -required_opt = get_option('required') -optional_opt = get_option('optional') -disabled_opt = get_option('disabled') - -assert(not feature_opts.enabled(), 'Should be disabled option') -assert(feature_opts.disabled(), 'Should be disabled option') -assert(not feature_opts.auto(), 'Should be disabled option') - -assert(required_opt.enabled(), 'Should be enabled option') -assert(not required_opt.disabled(), 'Should be enabled option') -assert(not required_opt.auto(), 'Should be enabled option') - -assert(not optional_opt.enabled(), 'Auto feature should be disabled') -assert(optional_opt.disabled(), 'Auto feature should be disabled') -assert(not optional_opt.auto(), 'Auto feature should be disabled') - -assert(not disabled_opt.enabled(), 'Should be disabled option') -assert(disabled_opt.disabled(), 'Should be disabled option') -assert(not disabled_opt.auto(), 'Should be disabled option') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 feature option disabled/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 feature option disabled/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/198 feature option disabled/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/198 feature option disabled/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -option('required', type : 'feature', value : 'enabled', description : 'An required feature') -option('optional', type : 'feature', value : 'auto', description : 'An optional feature') -option('disabled', type : 'feature', value : 'disabled', description : 'A disabled feature') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 argument syntax/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 argument syntax/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 argument syntax/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 argument syntax/meson.build" 2021-10-23 16:50:11.000000000 +0000 @@ -0,0 +1,19 @@ +project( + 'argument syntax', + ['c'], +) + +cc = meson.get_compiler('c') + +if ['gcc', 'lcc', 'clang', 'intel'].contains(cc.get_id()) + expected = 'gcc' +elif ['msvc', 'clang-cl', 'intel-cl'].contains(cc.get_id()) + expected = 'msvc' +else + # It's possible that other compilers end up here that shouldn't + expected = 'other' +endif + +assert(cc.get_argument_syntax() == expected, + 'Wrong output for compiler @0@. expected @1@ but got @2@'.format( + cc.get_id(), expected, cc.get_argument_syntax())) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 static threads/lib1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 static threads/lib1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 static threads/lib1.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 static threads/lib1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#if defined _WIN32 -#include -#else -#include -#endif - -void *f(void) { -#if defined _WIN32 - return CreateThread; -#else - return pthread_create; -#endif -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 static threads/lib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 static threads/lib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 static threads/lib2.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 static threads/lib2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -extern void *f(void); - -void *g(void) { - return f(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 static threads/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 static threads/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 static threads/meson.build" 2020-01-07 21:09:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 static threads/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('threads', 'c') - -thread_dep = dependency('threads') - - -lib1 = static_library('lib1', 'lib1.c', - dependencies : thread_dep) - -lib2 = static_library('lib2', 'lib2.c', - link_with : lib1) - -executable('prog', 'prog.c', - link_with : lib2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 static threads/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 static threads/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/199 static threads/prog.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/199 static threads/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -extern void *g(void); - -int main(void) { - g(); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 header in file list/header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 header in file list/header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 header in file list/header.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 header in file list/header.h" 2021-10-23 16:43:18.000000000 +0000 @@ -0,0 +1 @@ +#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 header in file list/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 header in file list/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 header in file list/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 header in file list/meson.build" 2021-10-23 16:47:56.000000000 +0000 @@ -0,0 +1,14 @@ +project('header in file list', 'c') + +cc_id = meson.get_compiler('c').get_id() +cc_ver = meson.get_compiler('c').version() + +if cc_id == 'intel' or (cc_id == 'lcc' and cc_ver.version_compare('<=1.23.08')) + # ICC and LCC <= 1.23.08 do not escape spaces in paths in the dependency file, so Ninja + # (correctly) thinks that the rule has multiple outputs and errors out: + # 'depfile has multiple output paths' + error('MESON_SKIP_TEST: Skipping test because your compiler is known to generate broken dependency files') +endif + +exe = executable('prog', 'prog.c', 'header.h') +test('basic', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 header in file list/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 header in file list/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 header in file list/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 header in file list/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#include "header.h" + +int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/include/func.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/include/func.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/include/func.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/include/func.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef FUNC_H__ -#define FUNC_H__ - -int func(void); - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/meson.build" 2020-01-07 21:06:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('include dir test', 'c') - -inc = include_directories('include') -subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/src/func.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/src/func.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/src/func.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/src/func.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "func.h" - -int func(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/src/meson.build" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -exe = executable('prog', 'prog.c', 'func.c', include_directories : inc) -test('inc test', exe) - -exe2 = executable('prog2', 'prog.c', 'func.c', include_directories : [['../include']]) -test('inc test 2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/src/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/src/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/19 includedir/src/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/19 includedir/src/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "func.h" - -int main(void) { - return func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/1 trivial/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/1 trivial/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/1 trivial/meson.build" 2020-01-07 21:06:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/1 trivial/meson.build" 2021-10-23 16:47:41.000000000 +0000 @@ -1,7 +1,7 @@ # Comment on the first line project('trivial test', # Comment inside a function call + array for language list - ['c'], + ['c'], default_options: ['buildtype=debug'], meson_version : '>=0.52.0') #this is a comment sources = 'trivial.c' @@ -14,13 +14,8 @@ add_project_arguments('/Qdiag-error:10159', language : 'c') endif -if meson.is_cross_build() - native_exe = executable('native-trivialprog', sources : sources, native : true) - test('native exe in cross build', native_exe) -endif - exe = executable('trivialprog', sources : sources) - +assert(exe.name() == 'trivialprog') test('runtest', exe) # This is a comment has_not_changed = false diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/com/mesonbuild/genprog.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/com/mesonbuild/genprog.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/com/mesonbuild/genprog.py" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/com/mesonbuild/genprog.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 - -import os, sys, argparse - -h_templ = '''#pragma once - -int %s(void); -''' - -c_templ = '''#include"%s.h" - -int %s(void) { - return 0; -} -''' - -parser = argparse.ArgumentParser() -parser.add_argument('--searchdir', required=True) -parser.add_argument('--outdir', required=True) -parser.add_argument('ifiles', nargs='+') - -options = parser.parse_args() - -searchdir = options.searchdir -outdir = options.outdir -ifiles = options.ifiles - -rel_ofiles = [] - -for ifile in ifiles: - if not ifile.startswith(options.searchdir): - sys.exit('Input file %s does not start with search dir %s.' % (ifile, searchdir)) - rel_ofile = ifile[len(searchdir):] - if rel_ofile[0] == '/' or rel_ofile[0] == '\\': - rel_ofile = rel_ofile[1:] - rel_ofiles.append(os.path.splitext(rel_ofile)[0]) - -ofile_bases = [os.path.join(outdir, i) for i in rel_ofiles] - -for i, ifile_name in enumerate(ifiles): - proto_name = open(ifile_name).readline().strip() - h_out = ofile_bases[i] + '.h' - c_out = ofile_bases[i] + '.c' - os.makedirs(os.path.split(ofile_bases[i])[0], exist_ok=True) - open(h_out, 'w').write(h_templ % (proto_name)) - open(c_out, 'w').write(c_templ % (proto_name, proto_name)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/com/mesonbuild/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/com/mesonbuild/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/com/mesonbuild/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/com/mesonbuild/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -gprog = find_program('genprog.py') - -gen = generator(gprog, \ - output : ['@BASENAME@.c', '@BASENAME@.h'], - arguments : ['--searchdir=@CURRENT_SOURCE_DIR@', '--outdir=@BUILD_DIR@', '@INPUT@']) - -generated = gen.process('subbie.inp') - -e = executable('testprog', 'testprog.c', generated) -test('testprog', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/com/mesonbuild/subbie.inp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/com/mesonbuild/subbie.inp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/com/mesonbuild/subbie.inp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/com/mesonbuild/subbie.inp" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -subbie diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/com/mesonbuild/testprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/com/mesonbuild/testprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/com/mesonbuild/testprog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/com/mesonbuild/testprog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"subbie.h" - -int main(void) { - return subbie(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 generator in subdir/meson.build" 2020-01-07 21:09:32.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 generator in subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('generator in subdir', 'c') - -subdir('com/mesonbuild') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 install name_prefix name_suffix/libfile.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 install name_prefix name_suffix/libfile.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 install name_prefix name_suffix/libfile.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 install name_prefix name_suffix/libfile.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC func(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 install name_prefix name_suffix/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 install name_prefix name_suffix/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 install name_prefix name_suffix/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 install name_prefix name_suffix/meson.build" 2021-10-23 16:50:12.000000000 +0000 @@ -0,0 +1,13 @@ +project('library with name_prefix name_suffix test', 'c') + +shared_library('foo', 'libfile.c', name_prefix: '', install : true) +static_library('bar', 'libfile.c', name_prefix: '', install : true) + +shared_library('baz', 'libfile.c', name_suffix: 'cheese', install : true) +static_library('qux', 'libfile.c', name_suffix: 'cheese', install : true) + +shared_library('corge', 'libfile.c', name_prefix: 'bow', name_suffix: 'stern', install : true) +static_library('grault', 'libfile.c', name_prefix: 'bow', name_suffix: 'stern', install : true) + +# exercise default name_prefix and name_suffix +shared_library('garply', 'libfile.c', name_prefix: [], name_suffix: [], install : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 install name_prefix name_suffix/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 install name_prefix name_suffix/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/200 install name_prefix name_suffix/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/200 install name_prefix name_suffix/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +{ + "installed": [ + {"type": "pdb", "file": "usr/bin/baz"}, + {"type": "pdb", "file": "usr/bin/bowcorge"}, + {"type": "pdb", "file": "usr/bin/foo"}, + {"type": "expr", "file": "usr/?lib/bowcorge.stern"}, + {"type": "expr", "file": "usr/lib/?libbaz.cheese"}, + {"type": "file", "file": "usr/lib/bar.a"}, + {"type": "implib", "file": "usr/lib/bowcorge"}, + {"type": "file", "file": "usr/lib/bowgrault.stern"}, + {"type": "implib", "file": "usr/lib/foo"}, + {"type": "expr", "file": "usr/lib/foo?so"}, + {"type": "implib", "file": "usr/lib/libbaz"}, + {"type": "file", "file": "usr/lib/libqux.cheese"}, + {"type": "expr", "file": "usr/?lib/libgarply?so"}, + {"type": "implib", "file": "usr/lib/libgarply"}, + {"type": "pdb", "file": "usr/bin/garply"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 kwarg entry/inc/prog.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 kwarg entry/inc/prog.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 kwarg entry/inc/prog.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 kwarg entry/inc/prog.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +#define MESSAGE "Hello there.\n" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 kwarg entry/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 kwarg entry/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 kwarg entry/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 kwarg entry/meson.build" 2021-10-23 16:50:13.000000000 +0000 @@ -0,0 +1,7 @@ +project('kwarg', 'c') + +default_kwargs = {'install': true, + 'include_directories': include_directories('inc')} + +executable('prog', 'prog.c', + kwargs: default_kwargs) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 kwarg entry/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 kwarg entry/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 kwarg entry/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 kwarg entry/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include +#include + +int main(void) { + printf(MESSAGE); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 kwarg entry/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 kwarg entry/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 kwarg entry/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 kwarg entry/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 override with exe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 override with exe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 override with exe/meson.build" 2020-01-07 21:09:34.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 override with exe/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -project('myexe', 'c') -sub = subproject('sub') -prog = find_program('foobar') -custom1 = custom_target('custom1', - build_by_default : true, - input : [], - output : 'main1.c', - command : [prog, '@OUTPUT@']) -gen = generator(prog, - output : '@BASENAME@.c', - arguments : ['@OUTPUT@']) -custom2 = gen.process('main2.input') - -executable('e1', custom1) -executable('e2', custom2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 override with exe/subprojects/sub/foobar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 override with exe/subprojects/sub/foobar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 override with exe/subprojects/sub/foobar.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 override with exe/subprojects/sub/foobar.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include -#include - -int main(int argc, char* argv[]) { - assert(argc == 2); - FILE *f = fopen(argv[1], "w"); - const char msg[] = "int main(void) {return 0;}\n"; - size_t w = fwrite(msg, 1, sizeof(msg) - 1, f); - assert(w == sizeof(msg) - 1); - int r = fclose(f); - assert(r == 0); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 override with exe/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 override with exe/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/201 override with exe/subprojects/sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/201 override with exe/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('sub', 'c') -foobar = executable('foobar', 'foobar.c', native : true) -meson.override_find_program('foobar', foobar) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 custom target build by default/docgen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 custom target build by default/docgen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 custom target build by default/docgen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 custom target build by default/docgen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import os +import sys + +out = sys.argv[1] + +os.mkdir(out) + +for name in ('a', 'b', 'c'): + with open(os.path.join(out, name + '.txt'), 'w') as f: + f.write(name) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 custom target build by default/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 custom target build by default/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 custom target build by default/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 custom target build by default/meson.build" 2021-10-23 16:50:13.000000000 +0000 @@ -0,0 +1,10 @@ +project('custom-target-dir-install', 'c') + +docgen = find_program('docgen.py') + +custom_target('docgen', + output : 'html', + command : [docgen, '@OUTPUT@'], + install : true, + build_by_default : false, + install_dir : join_paths(get_option('datadir'), 'doc/testpkgname')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 custom target build by default/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 custom target build by default/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 custom target build by default/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 custom target build by default/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/meson.build" 2020-01-07 21:09:34.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -project('proj', 'c') - -auto_subproj = subproject('sub', required: get_option('use-subproject')) -assert(auto_subproj.found(), 'Subproject should always be buildable and thus found') - -auto_dep = dependency('', fallback: ['sub', 'libSub'], required: true) -assert(auto_dep.found() == true, 'Subproject is required and foundable, dependency should be found.') - -disabled_subproj = subproject('disabled_sub', required: get_option('disabled-subproject')) -assert(disabled_subproj.found() == false, 'Disabled subproject should be NOT found') - -disabled_dep = dependency('', fallback: ['disabled_sub', 'libSub'], required: false) -assert(disabled_dep.found() == false, 'Subprojetc was disabled, it should never be built.') -nothing = executable('nothing', 'nothing.c', dependencies: [disabled_dep]) - -subproj_with_missing_dep = subproject('auto_sub_with_missing_dep', required: get_option('auto-sub-with-missing-dep')) -assert(subproj_with_missing_dep.found() == false, 'Subproject with required=auto and missing dependency should be NOT found') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -option('use-subproject', type : 'feature', value : 'auto') -option('disabled-subproject', type : 'feature', value : 'disabled') -option('auto-sub-with-missing-dep', type : 'feature', value : 'auto') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/nothing.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/nothing.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/nothing.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/nothing.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int main(void) -{ - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('sub', 'c') - -dependency('no_way_this_exists', required: true) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -lib = static_library('sub', 'sub.c') - -libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "sub.h" - -int sub(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/disabled_sub/lib/sub.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef SUB_H -#define SUB_H - -int sub(); - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/disabled_sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/disabled_sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/disabled_sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/disabled_sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('disabled_sub', 'c') - -subdir('lib') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/sub/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/sub/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/sub/lib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/sub/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -lib = static_library('sub', 'sub.c') -libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/sub/lib/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/sub/lib/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/sub/lib/sub.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/sub/lib/sub.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "sub.h" - -int sub(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/sub/lib/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/sub/lib/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/sub/lib/sub.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/sub/lib/sub.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef SUB_H -#define SUB_H - -int sub(void); - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/202 subproject with features/subprojects/sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/202 subproject with features/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('sub', 'c') - -subdir('lib') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/203 find_library and headers/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/203 find_library and headers/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/203 find_library and headers/foo.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/203 find_library and headers/foo.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#define VAL 42 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/203 find_library and headers/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/203 find_library and headers/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/203 find_library and headers/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/203 find_library and headers/meson.build" 2021-10-23 16:50:15.000000000 +0000 @@ -0,0 +1,23 @@ +project('find library and headers', 'c') + +cc = meson.get_compiler('c') + +if not cc.find_library('z', required : false).found() + error('MESON_SKIP_TEST: zlib not found.') +endif + +lib = cc.find_library('z', + has_headers : 'foo.h', + required : false) +assert(not lib.found(), 'Header should be missing') + +lib = cc.find_library('z', + has_headers : 'foo.h', + header_include_directories : include_directories('.')) +assert(lib.found(), 'Header should be found') + +lib = cc.find_library('z', + has_headers : ['foo.h', 'bar.h'], + header_include_directories : include_directories('.'), + required : false) +assert(not lib.found(), 'One header should be missing') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/203 function attributes/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/203 function attributes/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/203 function attributes/meson.build" 2020-01-07 21:09:40.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/203 function attributes/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,111 +0,0 @@ -# Copyright © 2017-2018 Intel Corporation -# -# 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. - -project('gcc func attributes', ['c', 'cpp']) - -# For msvc these will fail because msvc doesn't support __attribute__, for -# Clang and GCC, they should pass. -c = meson.get_compiler('c') -cpp = meson.get_compiler('cpp') - -if c.get_id() == 'pgi' - error('MESON_SKIP_TEST: PGI supports its own set of features, will need a separate list for PGI to test it.') -endif - -expected_result = not ['msvc', 'clang-cl', 'intel-cl'].contains(c.get_id()) - -# Q: Why is ifunc not in this list or any of the below lists? -# A: It's too damn hard to figure out if you actually support it, since it -# requires both compiler and libc support, and there isn't a good way to -# figure that out except by running the code we're trying to test. -attributes = [ - 'aligned', - 'alloc_size', - 'always_inline', - 'cold', - 'const', - 'constructor', - 'constructor_priority', - 'deprecated', - 'destructor', - 'flatten', - 'format', - 'format_arg', - 'gnu_inline', - 'hot', - 'malloc', - 'noinline', - 'nonnull', - 'noreturn', - 'nothrow', - 'pure', - 'unused', - 'used', - 'warn_unused_result', - 'weak', -] - -if c.get_id() != 'intel' - # not supported by icc as of 19.0.0 - attributes += 'weakref' -endif - -# These are unsupported on darwin with apple clang 9.1.0 -if host_machine.system() != 'darwin' - attributes += 'alias' - attributes += 'visibility' -endif - -if ['gcc', 'intel'].contains(c.get_id()) - # not supported by clang as of 5.0.0 (at least up to 6.0.1) - attributes += 'artificial' - attributes += 'error' - attributes += 'externally_visible' - attributes += 'leaf' - attributes += 'noclone' - attributes += 'optimize' - attributes += 'warning' - - if c.get_id() == 'gcc' and c.version().version_compare('>= 7.0.0') - attributes += 'fallthrough' - endif -endif - - -foreach a : attributes - x = c.has_function_attribute(a) - assert(x == expected_result, '@0@: @1@'.format(c.get_id(), a)) - x = cpp.has_function_attribute(a) - assert(x == expected_result, '@0@: @1@'.format(cpp.get_id(), a)) -endforeach - -win_expect = ['windows', 'cygwin'].contains(host_machine.system()) -foreach a : ['dllexport', 'dllimport'] - assert(c.has_function_attribute(a) == win_expect, - '@0@: @1@'.format(c.get_id(), a)) - assert(cpp.has_function_attribute(a) == win_expect, - '@0@: @1@'.format(cpp.get_id(), a)) -endforeach - -message('checking get_supported_function_attributes') -if not ['msvc', 'clang-cl', 'intel-cl'].contains(c.get_id()) - multi_expected = attributes -else - multi_expected = [] -endif - -multi_check = c.get_supported_function_attributes(attributes) -assert(multi_check == multi_expected, 'get_supported_function_arguments works (C)') -multi_check = cpp.get_supported_function_attributes(attributes) -assert(multi_check == multi_expected, 'get_supported_function_arguments works (C++)') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/204 broken subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/204 broken subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/204 broken subproject/meson.build" 2020-01-07 21:09:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/204 broken subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('test broken subproject') -subproject('broken', required : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/204 broken subproject/subprojects/broken/broken.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/204 broken subproject/subprojects/broken/broken.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/204 broken subproject/subprojects/broken/broken.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/204 broken subproject/subprojects/broken/broken.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#error This must not compile diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/204 broken subproject/subprojects/broken/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/204 broken subproject/subprojects/broken/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/204 broken subproject/subprojects/broken/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/204 broken subproject/subprojects/broken/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('broken', 'c') - -executable('app', 'broken.c') -assert(false, 'This subproject must fail') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/204 line continuation/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/204 line continuation/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/204 line continuation/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/204 line continuation/meson.build" 2021-10-23 16:50:15.000000000 +0000 @@ -0,0 +1,17 @@ +project('line continuation') + +a = 1 +b = 2 + +c = a \ ++b +assert(c == 3, 'Line continuation is not working') + +d = a + \ + b +assert(d == 3, 'Line continuation is not working') + +if a == 1 and \ + b == 3 + error('Line continuation in "if" condition is not working') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 argument syntax/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 argument syntax/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 argument syntax/meson.build" 2020-01-07 21:09:37.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 argument syntax/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -project( - 'argument syntax', - ['c'], -) - -cc = meson.get_compiler('c') - -if ['gcc', 'lcc', 'clang', 'intel'].contains(cc.get_id()) - expected = 'gcc' -elif ['msvc', 'clang-cl', 'intel-cl'].contains(cc.get_id()) - expected = 'msvc' -else - # It's possible that other compilers end up here that shouldn't - expected = 'other' -endif - -assert(cc.get_argument_syntax() == expected, - 'Wrong output for compiler @0@. expected @1@ but got @2@'.format( - cc.get_id(), expected, cc.get_argument_syntax())) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 native file path override/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 native file path override/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 native file path override/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 native file path override/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int main(void) { + std::cout << "Hello world!" << std::endl; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 native file path override/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 native file path override/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 native file path override/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 native file path override/meson.build" 2021-10-23 16:50:18.000000000 +0000 @@ -0,0 +1,7 @@ +project('native file install dir override', 'cpp') + +if meson.is_cross_build() + error('MESON_SKIP_TEST cannot test native build rules in cross build') +endif + +executable('main', 'main.cpp', install : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 native file path override/nativefile.ini" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 native file path override/nativefile.ini" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 native file path override/nativefile.ini" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 native file path override/nativefile.ini" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +[paths] +bindir = 'custom_bindir' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 native file path override/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 native file path override/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/205 native file path override/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/205 native file path override/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/custom_bindir/main"}, + {"type": "pdb", "file": "usr/custom_bindir/main"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 install name_prefix name_suffix/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 install name_prefix name_suffix/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 install name_prefix name_suffix/installed_files.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 install name_prefix name_suffix/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -?msvc:usr/bin/baz.pdb -?msvc:usr/bin/bowcorge.pdb -?msvc:usr/bin/foo.pdb -usr/?lib/bowcorge.stern -usr/lib/?libbaz.cheese -usr/lib/bar.a -usr/lib/bowcorge?implib -usr/lib/bowgrault.stern -usr/lib/foo?implib -usr/lib/foo?so -usr/lib/libbaz?implib -usr/lib/libqux.cheese diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 install name_prefix name_suffix/libfile.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 install name_prefix name_suffix/libfile.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 install name_prefix name_suffix/libfile.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 install name_prefix name_suffix/libfile.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC func(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 install name_prefix name_suffix/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 install name_prefix name_suffix/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 install name_prefix name_suffix/meson.build" 2020-01-07 21:09:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 install name_prefix name_suffix/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('library with name_prefix name_suffix test', 'c') - -shared_library('foo', 'libfile.c', name_prefix: '', install : true) -static_library('bar', 'libfile.c', name_prefix: '', install : true) - -shared_library('baz', 'libfile.c', name_suffix: 'cheese', install : true) -static_library('qux', 'libfile.c', name_suffix: 'cheese', install : true) - -shared_library('corge', 'libfile.c', name_prefix: 'bow', name_suffix: 'stern', install : true) -static_library('grault', 'libfile.c', name_prefix: 'bow', name_suffix: 'stern', install : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 tap tests/cat.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 tap tests/cat.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 tap tests/cat.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 tap tests/cat.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,26 @@ +#include +#include + +int main(int argc, char **argv) { + char buf[1024]; + size_t len; + FILE *fh; + + if (argc != 2) { + fprintf(stderr, "Incorrect number of arguments, got %i\n", argc); + return 1; + } + fh = fopen(argv[1], "r"); + if (fh == NULL) { + fprintf(stderr, "Opening %s: errno=%i\n", argv[1], errno); + return 1; + } + do { + len = fread(buf, 1, sizeof(buf), fh); + if (len > 0) { + fwrite(buf, 1, len, stdout); + } + } while (len > 0); + fclose(fh); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 tap tests/issue7515.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 tap tests/issue7515.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 tap tests/issue7515.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 tap tests/issue7515.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,27 @@ +1..26 +ok 1 Gtk overrides UI template sets up internal and public template children +ok 2 Gtk overrides UI template sets up public template children with the correct widgets +ok 3 Gtk overrides UI template sets up internal template children with the correct widgets +ok 4 Gtk overrides UI template connects template callbacks to the correct handler +ok 5 Gtk overrides UI template binds template callbacks to the correct object +ok 6 Gtk overrides UI template from resource sets up internal and public template children +ok 7 Gtk overrides UI template from resource sets up public template children with the correct widgets +ok 8 Gtk overrides UI template from resource sets up internal template children with the correct widgets +ok 9 Gtk overrides UI template from resource connects template callbacks to the correct handler +ok 10 Gtk overrides UI template from resource binds template callbacks to the correct object +ok 11 Gtk overrides UI template from file sets up internal and public template children +ok 12 Gtk overrides UI template from file sets up public template children with the correct widgets +ok 13 Gtk overrides UI template from file sets up internal template children with the correct widgets +ok 14 Gtk overrides UI template from file connects template callbacks to the correct handler +ok 15 Gtk overrides UI template from file binds template callbacks to the correct object +ok 16 Gtk overrides Class inheriting from template class sets up internal and public template children # SKIP pending +ok 17 Gtk overrides Class inheriting from template class sets up public template children with the correct widgets # SKIP pending +ok 18 Gtk overrides Class inheriting from template class sets up internal template children with the correct widgets # SKIP pending +ok 19 Gtk overrides Class inheriting from template class connects template callbacks to the correct handler # SKIP pending +ok 20 Gtk overrides Class inheriting from template class binds template callbacks to the correct object # SKIP pending +ok 21 Gtk overrides sets CSS names on classes +ok 22 Gtk overrides avoid crashing when GTK vfuncs are called in garbage collection +ok 23 Gtk overrides accepts string in place of GdkAtom +ok 24 Gtk overrides accepts null in place of GdkAtom as GDK_NONE +ok 25 Gtk overrides uses the correct GType for null child properties +ok 26 Gtk overrides can create a Gtk.TreeIter with accessible stamp field diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 tap tests/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 tap tests/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 tap tests/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 tap tests/meson.build" 2021-10-23 16:50:17.000000000 +0000 @@ -0,0 +1,14 @@ +project('test features', 'c') + +tester = executable('tester', 'tester.c') +cat = executable('cat', 'cat.c') +test('pass', tester, args : ['ok'], protocol: 'tap') +test('fail', tester, args : ['not ok'], should_fail: true, protocol: 'tap') +test('xfail', tester, args : ['not ok # todo'], protocol: 'tap') +test('xpass', tester, args : ['ok # todo'], should_fail: true, protocol: 'tap') +test('skip', tester, args : ['ok # skip'], protocol: 'tap') +test('partially skipped', tester, args : ['ok 1\nok 2 # skip'], protocol: 'tap') +test('partially skipped (real-world example)', cat, args : [files('issue7515.txt')], protocol: 'tap') +test('skip comment', tester, args : ['ok # Skipped: with a comment'], protocol: 'tap') +test('skip failure', tester, args : ['not ok # skip'], should_fail: true, protocol: 'tap') +test('no tests', tester, args : ['1..0 # skip'], protocol: 'tap') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 tap tests/tester.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 tap tests/tester.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/206 tap tests/tester.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/206 tap tests/tester.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Incorrect number of arguments, got %i\n", argc); + return 1; + } + puts(argv[1]); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 kwarg entry/inc/prog.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 kwarg entry/inc/prog.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 kwarg entry/inc/prog.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 kwarg entry/inc/prog.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#pragma once - -#define MESSAGE "Hello there.\n" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 kwarg entry/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 kwarg entry/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 kwarg entry/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 kwarg entry/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 kwarg entry/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 kwarg entry/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 kwarg entry/meson.build" 2020-01-07 21:09:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 kwarg entry/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('kwarg', 'c') - -default_kwargs = {'install': true, - 'include_directories': include_directories('inc')} - -executable('prog', 'prog.c', - kwargs: default_kwargs) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 kwarg entry/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 kwarg entry/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 kwarg entry/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 kwarg entry/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include -#include - -int main(void) { - printf(MESSAGE); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 warning level 0/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 warning level 0/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 warning level 0/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 warning level 0/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +#include + +#define PROJECT_NAME "demo" + +int main(int argc, char **argv) { + if(argc != 1) { + std::cout << argv[0] << "takes no arguments.\n"; + return 1; + } + std::cout << "This is project " << PROJECT_NAME << ".\n"; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 warning level 0/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 warning level 0/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/207 warning level 0/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/207 warning level 0/meson.build" 2021-10-23 16:50:19.000000000 +0000 @@ -0,0 +1,3 @@ +project('warning_level', 'cpp', default_options : ['warning_level=0']) + +exe = executable('main', 'main.cpp', install : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 custom target build by default/docgen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 custom target build by default/docgen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 custom target build by default/docgen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 custom target build by default/docgen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -out = sys.argv[1] - -os.mkdir(out) - -for name in ('a', 'b', 'c'): - with open(os.path.join(out, name + '.txt'), 'w') as f: - f.write(name) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 custom target build by default/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 custom target build by default/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 custom target build by default/meson.build" 2020-01-07 21:09:40.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 custom target build by default/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('custom-target-dir-install', 'c') - -docgen = find_program('docgen.py') - -custom_target('docgen', - output : 'html', - command : [docgen, '@OUTPUT@'], - install : true, - build_by_default : false, - install_dir : join_paths(get_option('datadir'), 'doc/testpkgname')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/custom_stlib.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/custom_stlib.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/custom_stlib.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/custom_stlib.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +import shutil, sys, subprocess, argparse, pathlib +import platform + +parser = argparse.ArgumentParser() + +parser.add_argument('--private-dir', required=True) +parser.add_argument('-o', required=True) +parser.add_argument('cmparr', nargs='+') + +contents = '''#include + +void flob(void) { + printf("Now flobbing.\\n"); +} +''' + +def get_pic_args(): + platname = platform.system().lower() + if platname in ['windows', 'darwin'] or sys.platform == 'cygwin': + return [] + return ['-fPIC'] + +def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array): + if shutil.which('ar'): + static_linker = 'ar' + elif shutil.which('llvm-ar'): + static_linker = 'llvm-ar' + elif shutil.which('gcc-ar'): + static_linker = 'gcc-ar' + else: + sys.exit('Could not detect a static linker.') + o_file = c_file.with_suffix('.o') + compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)] + compile_cmd += get_pic_args() + subprocess.check_call(compile_cmd) + out_file = pathlib.Path(outfile) + if out_file.exists(): + out_file.unlink() + link_cmd = [static_linker, 'csr', outfile, str(o_file)] + subprocess.check_call(link_cmd) + return 0 + + +def generate_lib_msvc(outfile, c_file, private_dir, compiler_array): + static_linker = 'lib' + o_file = c_file.with_suffix('.obj') + compile_cmd = compiler_array + ['/MDd', + '/nologo', + '/ZI', + '/Ob0', + '/Od', + '/c', + '/Fo' + str(o_file), + str(c_file)] + subprocess.check_call(compile_cmd) + out_file = pathlib.Path(outfile) + if out_file.exists(): + out_file.unlink() + link_cmd = [static_linker, + '/nologo', + '/OUT:' + str(outfile), + str(o_file)] + subprocess.check_call(link_cmd) + return 0 + +def generate_lib(outfile, private_dir, compiler_array): + private_dir = pathlib.Path(private_dir) + if not private_dir.exists(): + private_dir.mkdir() + c_file = private_dir / 'flob.c' + c_file.write_text(contents) + for i in compiler_array: + if (i.endswith('cl') or i.endswith('cl.exe')) and 'clang-cl' not in i: + return generate_lib_msvc(outfile, c_file, private_dir, compiler_array) + return generate_lib_gnulike(outfile, c_file, private_dir, compiler_array) + +if __name__ == '__main__': + options = parser.parse_args() + sys.exit(generate_lib(options.o, options.private_dir, options.cmparr)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/custom_target.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/custom_target.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/custom_target.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/custom_target.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +void outer_lib_func(void); + +int main(void) { + outer_lib_func(); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/custom_target.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/custom_target.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/custom_target.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/custom_target.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import shutil, sys + +if __name__ == '__main__': + shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/dummy.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/dummy.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/dummy.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/dummy.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +void inner_lib_func(void) {} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +void flob(void); + +int foo(void) +{ + flob(); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/meson.build" 2021-10-23 16:50:19.000000000 +0000 @@ -0,0 +1,86 @@ +project('linkcustom', 'c') + +# This would require passing the static linker to the build script or having +# it detect it by itself. I'm too lazy to implement it now and it is not +# really needed for testing that custom targets work. It is the responsibility +# of the custom target to produce things in the correct format. +assert(not meson.is_cross_build(), + 'MESON_SKIP_TEST cross checking not implemented.') + +cc = meson.get_compiler('c') +genprog = find_program('custom_stlib.py') + +clib = custom_target('linkcustom', + output: 'libflob.a', + command: [genprog, + '-o', '@OUTPUT@', + '--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array()) + +# custom_target tests + +exe = executable('prog', 'prog.c', link_with: clib) +test('linkcustom', exe) + +d = declare_dependency(link_with: clib) + +exe2 = executable('prog2', 'prog.c', dependencies: d) +test('linkcustom2', exe2) + +# Link whole tests + +if meson.backend() == 'xcode' + message('Xcode does not support link whole so skipping.') +else + exe3 = executable('prog3', 'prog.c', link_whole: clib) + test('linkwhole', exe) + + d2 = declare_dependency(link_whole: clib) + + exe4 = executable('prog4', 'prog.c', dependencies: d2) + test('linkwhole2', exe2) +endif + +# custom_target[i] tests + +exe_i = executable('prog_i', 'prog.c', link_with: clib[0]) +test('linkcustom', exe_i) + +d_i = declare_dependency(link_with: clib[0]) + +exe2_i = executable('prog2_i', 'prog.c', dependencies: d_i) +test('linkcustom2_i', exe2_i) + +# Link whole tests + +if meson.backend() == 'xcode' + message('Xcode does not support link whole so skipping.') +else + shared_library('lib1', 'lib.c', link_whole: clib) + + exe3_i = executable('prog3_i', 'prog.c', link_whole: clib[0]) + test('linkwhole', exe) + + d2_i = declare_dependency(link_whole: clib[0]) + + exe4_i = executable('prog4_i', 'prog.c', dependencies: d2_i) + test('linkwhole2_i', exe2_i) +endif + +# Link with custom target + +dummy = static_library('dummy', 'dummy.c') + +custom_prog = find_program('custom_target.py') +t = custom_target('custom', input: dummy, output: 'libcustom.a', command: [custom_prog, '@INPUT@', '@OUTPUT@']) + +dep1 = declare_dependency(link_with: t) +dep2 = declare_dependency(link_with: t[0]) + +lib1 = static_library('lib1', 'outerlib.c', dependencies: dep1) +lib2 = static_library('lib2', 'outerlib.c', dependencies: dep2) + +exe1 = executable('exe1', 'custom_target.c', link_with: lib1) +test('custom_target_1', exe1) + +exe1_2 = executable('exe1_2', 'custom_target.c', link_with: lib2) +test('custom_target_2', exe2) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/outerlib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/outerlib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/outerlib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/outerlib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +void inner_lib_func(void); + +void outer_lib_func(void) { inner_lib_func(); } \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/208 link custom/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/208 link custom/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +void flob(void); + +int main(void) { + flob(); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 find_library and headers/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 find_library and headers/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 find_library and headers/foo.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 find_library and headers/foo.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#define VAL 42 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 find_library and headers/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 find_library and headers/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 find_library and headers/meson.build" 2020-01-07 21:09:41.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 find_library and headers/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -project('find library and headers', 'c') - -cc = meson.get_compiler('c') - -if not cc.find_library('z', required : false).found() - error('MESON_SKIP_TEST: zlib not found.') -endif - -lib = cc.find_library('z', - has_headers : 'foo.h', - required : false) -assert(not lib.found(), 'Header should be missing') - -lib = cc.find_library('z', - has_headers : 'foo.h', - header_include_directories : include_directories('.')) -assert(lib.found(), 'Header should be found') - -lib = cc.find_library('z', - has_headers : ['foo.h', 'bar.h'], - header_include_directories : include_directories('.'), - required : false) -assert(not lib.found(), 'One header should be missing') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 link custom_i single from multiple/generate_conflicting_stlibs.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 link custom_i single from multiple/generate_conflicting_stlibs.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 link custom_i single from multiple/generate_conflicting_stlibs.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 link custom_i single from multiple/generate_conflicting_stlibs.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 + +import shutil, sys, subprocess, argparse, pathlib + +parser = argparse.ArgumentParser() + +parser.add_argument('--private-dir', required=True) +parser.add_argument('-o', nargs='+', required=True) +parser.add_argument('cmparr', nargs='+') + +contents = [''' +int flob() { + return 0; +} +''', ''' +int flob() { + return 1; +} +'''] + +def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array): + if shutil.which('ar'): + static_linker = 'ar' + elif shutil.which('llvm-ar'): + static_linker = 'llvm-ar' + elif shutil.which('gcc-ar'): + static_linker = 'gcc-ar' + else: + sys.exit('Could not detect a static linker.') + o_file = c_file.with_suffix('.o') + compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)] + subprocess.check_call(compile_cmd) + out_file = pathlib.Path(outfile) + if out_file.exists(): + out_file.unlink() + link_cmd = [static_linker, 'csr', outfile, str(o_file)] + subprocess.check_call(link_cmd) + return 0 + + +def generate_lib_msvc(outfile, c_file, private_dir, compiler_array): + static_linker = 'lib' + o_file = c_file.with_suffix('.obj') + compile_cmd = compiler_array + ['/MDd', + '/nologo', + '/ZI', + '/Ob0', + '/Od', + '/c', + '/Fo' + str(o_file), + str(c_file)] + subprocess.check_call(compile_cmd) + out_file = pathlib.Path(outfile) + if out_file.exists(): + out_file.unlink() + link_cmd = [static_linker, + '/nologo', + '/OUT:' + str(outfile), + str(o_file)] + subprocess.check_call(link_cmd) + return 0 + +def generate_lib(outfiles, private_dir, compiler_array): + private_dir = pathlib.Path(private_dir) + if not private_dir.exists(): + private_dir.mkdir() + + for i, content in enumerate(contents): + c_file = private_dir / ('flob_' + str(i + 1) + '.c') + c_file.write_text(content) + outfile = outfiles[i] + + cl_found = False + for cl_arg in compiler_array: + if (cl_arg.endswith('cl') or cl_arg.endswith('cl.exe')) and 'clang-cl' not in cl_arg: + ret = generate_lib_msvc(outfile, c_file, private_dir, compiler_array) + if ret > 0: + return ret + else: + cl_found = True + break + if not cl_found: + ret = generate_lib_gnulike(outfile, c_file, private_dir, compiler_array) + if ret > 0: + return ret + return 0 + +if __name__ == '__main__': + options = parser.parse_args() + sys.exit(generate_lib(options.o, options.private_dir, options.cmparr)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 link custom_i single from multiple/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 link custom_i single from multiple/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 link custom_i single from multiple/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 link custom_i single from multiple/meson.build" 2021-10-23 16:50:20.000000000 +0000 @@ -0,0 +1,42 @@ +project('linkcustom', 'c') + +# This would require passing the static linker to the build script or having +# it detect it by itself. I'm too lazy to implement it now and it is not +# really needed for testing that custom targets work. It is the responsibility +# of the custom target to produce things in the correct format. +assert(not meson.is_cross_build(), + 'MESON_SKIP_TEST cross checking not implemented.') + +cc = meson.get_compiler('c') +genprog = find_program('generate_conflicting_stlibs.py') + +clib = custom_target('linkcustom', + output: ['libflob_1.a', 'libflob_2.a'], + command: [genprog, + '-o', '@OUTPUT@', + '--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array()) + +clib_2 = clib[1] + +exe = executable('prog', 'prog.c', link_with: clib_2) +test('linkcustom', exe) + +d = declare_dependency(link_with: clib_2) + +exe2 = executable('prog2', 'prog.c', dependencies: d) +test('linkcustom2', exe2) + +# Link whole tests + +if meson.backend() == 'xcode' + message('Xcode does not support link whole so skipping.') + subdir_done() +endif + +exe3 = executable('prog3', 'prog.c', link_whole: clib_2) +test('linkwhole', exe) + +d2 = declare_dependency(link_whole: clib_2) + +exe4 = executable('prog4', 'prog.c', dependencies: d2) +test('linkwhole2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 link custom_i single from multiple/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 link custom_i single from multiple/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/209 link custom_i single from multiple/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/209 link custom_i single from multiple/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int flob(void); + +int main(void) { + return (flob() == 1 ? 0 : 1); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 global arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 global arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 global arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 global arg/meson.build" 2021-10-23 16:47:58.000000000 +0000 @@ -0,0 +1,16 @@ +project('global arg test', 'cpp', 'c') + +add_global_arguments('-DMYTHING', language : 'c') +add_global_arguments('-DMYCPPTHING', language : 'cpp') +add_global_arguments('-DGLOBAL_HOST', language : 'c') + +build_c_args = ['-DARG_BUILD'] +c_args = ['-DARG_HOST'] + +add_global_arguments('-DMYCANDCPPTHING', language: ['c', 'cpp']) + +exe2 = executable('prog2', 'prog.c', c_args : c_args) +exe3 = executable('prog3', 'prog.cc') + +test('prog2', exe2) +test('prog3', exe3) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 global arg/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 global arg/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 global arg/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 global arg/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,43 @@ +#ifndef MYTHING + #error "Global argument not set" +#endif + +#ifdef MYCPPTHING + #error "Wrong global argument set" +#endif + +#ifndef MYCANDCPPTHING + #error "Global argument not set" +#endif + +#if !defined(GLOBAL_HOST) && !defined(GLOBAL_BUILD) + #error "Neither global_host nor glogal_build is set." +#endif + +#if defined(GLOBAL_HOST) && defined(GLOBAL_BUILD) + #error "Both global build and global host set." +#endif + +#ifdef GLOBAL_BUILD + #ifndef ARG_BUILD + #error "Global is build but arg_build is not set." + #endif + + #ifdef ARG_HOST + #error "Global is build but arg host is set." + #endif +#endif + +#ifdef GLOBAL_HOST + #ifndef ARG_HOST + #error "Global is host but arg_host is not set." + #endif + + #ifdef ARG_BUILD + #error "Global is host but arg_build is set." + #endif +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 global arg/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 global arg/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 global arg/prog.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 global arg/prog.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#ifdef MYTHING +#error "Wrong global argument set" +#endif + +#ifndef MYCPPTHING +#error "Global argument not set" +#endif + +#ifndef MYCANDCPPTHING +#error "Global argument not set" +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 header in file list/header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 header in file list/header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 header in file list/header.h" 2020-01-07 21:01:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 header in file list/header.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 header in file list/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 header in file list/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 header in file list/meson.build" 2020-01-07 21:06:29.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 header in file list/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('header in file list', 'c') - -cc_id = meson.get_compiler('c').get_id() -cc_ver = meson.get_compiler('c').version() - -if cc_id == 'intel' or (cc_id == 'lcc' and cc_ver.version_compare('<=1.23.08')) - # ICC and LCC <= 1.23.08 do not escape spaces in paths in the dependency file, so Ninja - # (correctly) thinks that the rule has multiple outputs and errors out: - # 'depfile has multiple output paths' - error('MESON_SKIP_TEST: Skipping test because your compiler is known to generate broken dependency files') -endif - -exe = executable('prog', 'prog.c', 'header.h') -test('basic', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 header in file list/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 header in file list/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/20 header in file list/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/20 header in file list/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#include "header.h" - -int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/210 line continuation/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/210 line continuation/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/210 line continuation/meson.build" 2020-01-07 21:09:40.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/210 line continuation/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -project('line continuation') - -a = 1 -b = 2 - -c = a \ -+b -assert(c == 3, 'Line continuation is not working') - -d = a + \ - b -assert(d == 3, 'Line continuation is not working') - -if a == 1 and \ - b == 3 - error('Line continuation in "if" condition is not working') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/210 link custom_i multiple from multiple/generate_stlibs.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/210 link custom_i multiple from multiple/generate_stlibs.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/210 link custom_i multiple from multiple/generate_stlibs.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/210 link custom_i multiple from multiple/generate_stlibs.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +import shutil, sys, subprocess, argparse, pathlib + +parser = argparse.ArgumentParser() + +parser.add_argument('--private-dir', required=True) +parser.add_argument('-o', nargs='+', required=True) +parser.add_argument('cmparr', nargs='+') + +contents = ['''#include + +void flob_1() { + printf("Now flobbing #1.\\n"); +} +''', '''#include + +void flob_2() { + printf("Now flobbing #2.\\n"); +} +'''] + +def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array): + if shutil.which('ar'): + static_linker = 'ar' + elif shutil.which('llvm-ar'): + static_linker = 'llvm-ar' + elif shutil.which('gcc-ar'): + static_linker = 'gcc-ar' + else: + sys.exit('Could not detect a static linker.') + o_file = c_file.with_suffix('.o') + compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)] + subprocess.check_call(compile_cmd) + out_file = pathlib.Path(outfile) + if out_file.exists(): + out_file.unlink() + link_cmd = [static_linker, 'csr', outfile, str(o_file)] + subprocess.check_call(link_cmd) + return 0 + + +def generate_lib_msvc(outfile, c_file, private_dir, compiler_array): + static_linker = 'lib' + o_file = c_file.with_suffix('.obj') + compile_cmd = compiler_array + ['/MDd', + '/nologo', + '/ZI', + '/Ob0', + '/Od', + '/c', + '/Fo' + str(o_file), + str(c_file)] + subprocess.check_call(compile_cmd) + out_file = pathlib.Path(outfile) + if out_file.exists(): + out_file.unlink() + link_cmd = [static_linker, + '/nologo', + '/OUT:' + str(outfile), + str(o_file)] + subprocess.check_call(link_cmd) + return 0 + +def generate_lib(outfiles, private_dir, compiler_array): + private_dir = pathlib.Path(private_dir) + if not private_dir.exists(): + private_dir.mkdir() + + for i, content in enumerate(contents): + c_file = private_dir / ('flob_' + str(i + 1) + '.c') + c_file.write_text(content) + outfile = outfiles[i] + + cl_found = False + for cl_arg in compiler_array: + if (cl_arg.endswith('cl') or cl_arg.endswith('cl.exe')) and 'clang-cl' not in cl_arg: + ret = generate_lib_msvc(outfile, c_file, private_dir, compiler_array) + if ret > 0: + return ret + else: + cl_found = True + break + if not cl_found: + ret = generate_lib_gnulike(outfile, c_file, private_dir, compiler_array) + if ret > 0: + return ret + return 0 + +if __name__ == '__main__': + options = parser.parse_args() + sys.exit(generate_lib(options.o, options.private_dir, options.cmparr)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/210 link custom_i multiple from multiple/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/210 link custom_i multiple from multiple/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/210 link custom_i multiple from multiple/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/210 link custom_i multiple from multiple/meson.build" 2021-10-23 16:50:20.000000000 +0000 @@ -0,0 +1,42 @@ +project('linkcustom', 'c') + +# This would require passing the static linker to the build script or having +# it detect it by itself. I'm too lazy to implement it now and it is not +# really needed for testing that custom targets work. It is the responsibility +# of the custom target to produce things in the correct format. +assert(not meson.is_cross_build(), + 'MESON_SKIP_TEST cross checking not implemented.') + +cc = meson.get_compiler('c') +genprog = find_program('generate_stlibs.py') + +clib = custom_target('linkcustom', + output: ['libflob_1.a', 'libflob_2.a'], + command: [genprog, + '-o', '@OUTPUT@', + '--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array()) + +clibs = [clib[0], clib[1]] + +exe = executable('prog', 'prog.c', link_with: clibs) +test('linkcustom', exe) + +d = declare_dependency(link_with: clibs) + +exe2 = executable('prog2', 'prog.c', dependencies: d) +test('linkcustom2', exe2) + +# Link whole tests + +if meson.backend() == 'xcode' + message('Xcode does not support link whole so skipping.') + subdir_done() +endif + +exe3 = executable('prog3', 'prog.c', link_whole: clibs) +test('linkwhole', exe) + +d2 = declare_dependency(link_whole: clibs) + +exe4 = executable('prog4', 'prog.c', dependencies: d2) +test('linkwhole2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/210 link custom_i multiple from multiple/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/210 link custom_i multiple from multiple/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/210 link custom_i multiple from multiple/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/210 link custom_i multiple from multiple/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +void flob_1(void); +void flob_2(void); + +int main(void) { + flob_1(); + flob_2(); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 cmake module/cmake_project/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 cmake module/cmake_project/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 cmake module/cmake_project/CMakeLists.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 cmake module/cmake_project/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -project(cmakeMeson C) - -find_package(cmakeModule REQUIRED) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 cmake module/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 cmake module/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 cmake module/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 cmake module/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/lib/cmake/cmakeModule/cmakeModuleConfig.cmake -usr/lib/cmake/cmakeModule/cmakeModuleConfigVersion.cmake \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 cmake module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 cmake module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 cmake module/meson.build" 2020-01-07 21:09:46.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 cmake module/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -project('cmakeModule', 'c', version: '1.0.0') - -if build_machine.system() == 'cygwin' - error('MESON_SKIP_TEST CMake is broken on Cygwin.') -endif - -cmake_bin = find_program('cmake', required: false) -if not cmake_bin.found() - error('MESON_SKIP_TEST CMake not installed.') -endif - -cc = meson.get_compiler('c') -if cc.get_id() == 'clang-cl' and meson.backend() == 'ninja' and build_machine.system() == 'windows' - error('MESON_SKIP_TEST CMake installation nor operational for vs2017 clangclx64ninja') -endif - -cmake = import('cmake') - -cmake.write_basic_package_version_file(version: '0.0.1', - name: 'cmakeModule', -) - -conf = configuration_data() -conf.set('MYVAR', 'my variable value') -conf.set_quoted('MYQUOTEDVAR', 'my quoted variable value') - -cmake.configure_package_config_file( - input: 'projectConfig.cmake.in', - name: 'cmakeModule', - configuration: conf, -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 cmake module/projectConfig.cmake.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 cmake module/projectConfig.cmake.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 cmake module/projectConfig.cmake.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 cmake module/projectConfig.cmake.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -@PACKAGE_INIT@ - -set(MYVAR "@MYVAR@") -set(MYQUOTEDVAR @MYQUOTEDVAR@) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 dependency get_variable method/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 dependency get_variable method/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 dependency get_variable method/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 dependency get_variable method/meson.build" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,67 @@ +project( + 'dependency get_variable', + ['c', 'cpp'], +) + +# Just some string that nothing should return +default = 'asufoiqwjtl;adjfbpiuqwoehtl;ajdfl;ghal;sdjg' + +dep = dependency('zlib', method: 'pkg-config', required : false) +if not dep.found() + warning('Skipping pkg-config tests as zlib is not available or is not pkg-config') +else + # Test for regular pkg-config + # We don't know what the value will be, but we know it should be the same + dep = dependency('zlib', method : 'pkg-config') + assert(dep.get_pkgconfig_variable('prefix') == dep.get_variable(pkgconfig : 'prefix'), + 'Got different values from get_pkgconfig_variable and get_variable(pkgconfig: )') + assert(dep.get_variable(pkgconfig : default, default_value : default) == default, + 'pkg-config didn\'t get default when we should have.') + assert(dep.get_variable(pkgconfig : 'prefix', default_value : default) != default, + 'pkg-config got default when we shouldn\'t have.') + assert(dep.get_variable(pkgconfig : 'pkgvarnotfound', default_value : '') == '') +endif + +dep_ct = dependency('llvm', method : 'config-tool', required : false) +if not dep_ct.found() + warning('Skipping config-tool tests as llvm is not available or llvm-config was not found.') +else + assert(dep_ct.get_configtool_variable('has-rtti') == dep_ct.get_variable(configtool : 'has-rtti'), + 'Got different values from get_configtool_variable and get_variable(configtool: )') + assert(dep_ct.get_variable(configtool : default, default_value : default) == default, + 'config-tool didn\'t get default when we should have.') + assert(dep_ct.get_variable(configtool : 'has-rtti', default_value : default) != default, + 'config-tool got default when we shouldn\'t have.') +endif + +dep_cm = dependency('llvm', method : 'cmake', required : false) +if not dep_cm.found() + warning('Skipping cmake tests as llvm is not available via the cmake finder.') +else + if dep_ct.found() + assert((dep_cm.get_variable(cmake : 'LLVM_ENABLE_RTTI') == 'ON') == (dep_ct.get_variable(configtool : 'has-rtti') == 'YES'), + 'RTTI information for cmake and config tools disagree') + endif + assert(dep_cm.get_variable(cmake : default, default_value : default) == default, + 'cmake didn\'t get default when we should have.') + assert(dep_cm.get_variable(cmake : 'LLVM_ENABLE_RTTI', default_value : default) != default, + 'cmake config-tool got default when we shouldn\'t have.') +endif + +idep = declare_dependency(variables : {'foo' : 'value'}) +assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', + internal : 'foo', default_value : default) == 'value', + 'internal got default when it shouldn\'t have.') +assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', + internal : 'bar', default_value : default) == default, + 'internal didn\'t default when it should have.') + +idep = declare_dependency() +assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', + default_value : default) == default, + 'something went wrong with an InternalDependency with no variables.') + +idep = declare_dependency(variables : ['foo=value']) +assert(idep.get_variable(internal: 'foo') == 'value') +assert(idep.get_variable('foo') == 'value') +assert(idep.get_variable('invalid', internal: 'foo') == 'value') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 dependency get_variable method/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 dependency get_variable method/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/211 dependency get_variable method/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/211 dependency get_variable method/test.json" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "stdout": [ + { + "line": ".*pkgvarnotfound.*", + "match": "re", + "count": 0 + } + ] + } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 native file path override/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 native file path override/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 native file path override/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 native file path override/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/custom_bindir/main?exe -?msvc:usr/custom_bindir/main.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 native file path override/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 native file path override/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 native file path override/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 native file path override/main.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -int main(void) { - std::cout << "Hello world!" << std::endl; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 native file path override/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 native file path override/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 native file path override/meson.build" 2020-01-07 21:09:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 native file path override/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('native file install dir override', 'cpp') - -if meson.is_cross_build() - error('MESON_SKIP_TEST cannot test native build rules in cross build') -endif - -executable('main', 'main.cpp', install : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 native file path override/nativefile.ini" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 native file path override/nativefile.ini" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 native file path override/nativefile.ini" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 native file path override/nativefile.ini" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -[paths] -bindir = 'custom_bindir' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/a.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include "all.h" + +int main(void) +{ + if (p) abort(); + f(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/all.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/all.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/all.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/all.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +extern void f(void); +extern void g(void); +extern void h(void); +extern void undefined(void); + +/* Defined in nope.c and f.c, + * value depends on the source set and configuration used. + */ +extern void (*p)(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/f.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/f.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/f.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/f.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include "all.h" + +void (*p)(void) = (void *)0x12AB34CD; + +void f(void) +{ +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/g.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/g.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/g.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/g.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include "all.h" + +void g(void) +{ + h(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/meson.build" 2021-10-23 16:50:24.000000000 +0000 @@ -0,0 +1,54 @@ +project('a', 'c') + +good = declare_dependency(link_with: static_library('good', 'g.c')) +bad = declare_dependency(link_args: 'nonexistent.a') +not_found = dependency('invalid', required: false) + +source_set = import('sourceset') + +sources = source_set.source_set() +sources.add(when: 'YES', if_false: ['nope.c']) +sources.add(when: 'YES1', if_true: files('a.c')) +subdir('subdir') +sources.add(when: 'NO', if_true: 'nope.c', if_false: ['f.c']) +sources.add(when: 'NO', if_true: bad, if_false: ['f.c']) + +sources.add(when: 'YES2', if_true: good) + +# dependencies as conditions +sources.add(when: not_found, if_true: 'nope.c') + +# test add_all +sources2 = source_set.source_set() +sources2.add(when: 'YES1', if_true: 'nope.c') +sources.add_all(when: 'NO', if_true: sources2) + +# test duplicate items +sources.add(when: 'YES1', if_true: files('a.c')) + +conf1 = configuration_data() +conf1.set10('YES', true) +conf1.set10('YES1', true) +conf1.set10('YES2', false) +conf1.set10('NO', false) +result1 = sources.apply(conf1) + +conf2 = configuration_data() +conf2.set10('YES', true) +conf2.set10('YES1', false) +conf2.set10('YES2', true) +conf2.set10('NO', false) +result2 = sources.apply(conf2) + +# Each target will recompile the objects +executable('first', sources: result1.sources(), dependencies: result1.dependencies()) +executable('second', sources: result2.sources(), dependencies: result2.dependencies()) + +# All target will use the same object files +if meson.is_unity() + message('Skipping extraction test because this is a Unity build.') +else + all_objs = static_library('all_objs', sources.all_sources()) + executable('first_via_lib', objects: all_objs.extract_objects(result1.sources()), dependencies: result1.dependencies()) + executable('second_via_lib', objects: all_objs.extract_objects(result2.sources()), dependencies: result2.dependencies()) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/nope.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/nope.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/nope.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/nope.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#include "all.h" + +void (*p)(void) = undefined; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/subdir/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/subdir/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/subdir/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/subdir/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include +#include "all.h" + +void h(void) +{ +} + +int main(void) +{ + if (p) abort(); + f(); + g(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/212 source set configuration_data/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/212 source set configuration_data/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +sources.add(when: ['YES2', good], if_true: [ files('b.c') ]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/a.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include "all.h" + +int main(void) +{ + if (p) abort(); + f(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/all.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/all.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/all.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/all.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +extern void f(void); +extern void g(void); +extern void h(void); +extern void undefined(void); + +/* Defined in nope.c and f.c, + * value depends on the source set and configuration used. + */ +extern void (*p)(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/f.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/f.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/f.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/f.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include "all.h" + +void (*p)(void) = (void *)0x1234ABCD; + +void f(void) +{ +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/g.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/g.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/g.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/g.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include "all.h" + +void g(void) +{ + h(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/meson.build" 2021-10-23 16:50:25.000000000 +0000 @@ -0,0 +1,56 @@ +project('a', 'c') + +good = declare_dependency(link_with: static_library('good', 'g.c')) +bad = declare_dependency(link_args: 'nonexistent.a') +not_found = dependency('invalid', required: false) + +source_set = import('sourceset') + +sources = source_set.source_set() +sources.add(when: 'YES', if_false: ['nope.c']) +sources.add(when: 'YES1', if_true: files('a.c')) +subdir('subdir') +sources.add(when: 'NO', if_true: 'nope.c', if_false: ['f.c']) +sources.add(when: 'NO', if_true: bad, if_false: ['f.c']) + +sources.add(when: 'YES2', if_true: good) + +# dependencies as conditions +sources.add(when: not_found, if_true: 'nope.c') + +# test add_all +sources2 = source_set.source_set() +sources2.add(when: 'YES1', if_true: 'nope.c') +sources.add_all(when: 'NO', if_true: sources2) + +# test duplicate items +sources.add(when: 'YES1', if_true: files('a.c')) + +conf1 = { + 'YES': true, + 'YES1': true, + 'YES2': false, + 'NO': false, +} +result1 = sources.apply(conf1) + +conf2 = { + 'YES': true, + 'YES1': false, + 'YES2': true, + 'NO': false, +} +result2 = sources.apply(conf2) + +# Each target will recompile the objects +executable('first', sources: result1.sources(), dependencies: result1.dependencies()) +executable('second', sources: result2.sources(), dependencies: result2.dependencies()) + +# All target will use the same object files +if meson.is_unity() + message('Skipping extraction test because this is a Unity build.') +else + all_objs = static_library('all_objs', sources.all_sources()) + executable('first_via_lib', objects: all_objs.extract_objects(result1.sources()), dependencies: result1.dependencies()) + executable('second_via_lib', objects: all_objs.extract_objects(result2.sources()), dependencies: result2.dependencies()) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/nope.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/nope.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/nope.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/nope.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#include "all.h" + +void (*p)(void) = undefined; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/subdir/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/subdir/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/subdir/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/subdir/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include +#include "all.h" + +void h(void) +{ +} + +int main(void) +{ + if (p) abort(); + f(); + g(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 source set dictionary/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 source set dictionary/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +sources.add(when: ['YES2', good], if_true: [ files('b.c') ]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 tap tests/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 tap tests/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 tap tests/meson.build" 2020-01-07 21:09:44.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 tap tests/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('test features', 'c') - -tester = executable('tester', 'tester.c') -test('pass', tester, args : ['ok'], protocol: 'tap') -test('fail', tester, args : ['not ok'], should_fail: true, protocol: 'tap') -test('xfail', tester, args : ['not ok # todo'], protocol: 'tap') -test('xpass', tester, args : ['ok # todo'], should_fail: true, protocol: 'tap') -test('skip', tester, args : ['ok # skip'], protocol: 'tap') -test('skip failure', tester, args : ['not ok # skip'], should_fail: true, protocol: 'tap') -test('no tests', tester, args : ['1..0 # skip'], protocol: 'tap') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 tap tests/tester.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 tap tests/tester.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/213 tap tests/tester.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/213 tap tests/tester.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include - -int main(int argc, char **argv) { - if (argc != 2) { - fprintf(stderr, "Incorrect number of arguments, got %i\n", argc); - return 1; - } - puts(argv[1]); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/a.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include "all.h" + +int main(void) +{ + f(); + g(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/all.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/all.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/all.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/all.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +extern void f(void); +extern void g(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/cp.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/cp.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/cp.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/cp.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#! /usr/bin/env python3 + +import sys +from shutil import copyfile +copyfile(*sys.argv[1:]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/f.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/f.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/f.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/f.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "all.h" + +void f(void) +{ +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/g.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/g.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/g.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/g.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "all.h" + +void g(void) +{ +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 source set custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 source set custom target/meson.build" 2021-10-23 16:50:23.000000000 +0000 @@ -0,0 +1,28 @@ +# Try using sourceset with various kinds of generated sources + +project('a', 'c') + +cp = find_program('cp.py') + +source_set = import('sourceset') +sources = source_set.source_set() + +a_c = custom_target('gen-custom-target', + input: 'a.c', output: 'out_a.c', + command: [cp, '@INPUT@', '@OUTPUT@']) +sources.add(when: 'YES', if_true: a_c) +sources.add(when: 'YES', if_true: a_c[0]) + +f_c = configure_file(input: 'f.c', output: 'out_f.c', copy: true) +sources.add(when: 'YES', if_true: f_c) +sources.add(when: 'YES', if_true: f_c) + +gen = generator(cp, output: 'out_@PLAINNAME@', arguments: ['@INPUT@', '@OUTPUT@']) +g_c = gen.process(files('g.c')) +sources.add(when: 'YES', if_true: g_c) +sources.add(when: 'YES', if_true: g_c) + +conf1 = { 'YES': true, } +result1 = sources.apply(conf1) + +executable('first', sources: result1.sources(), dependencies: result1.dependencies()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 warning level 0/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 warning level 0/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 warning level 0/main.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 warning level 0/main.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#include - -#define PROJECT_NAME "demo" - -int main(int argc, char **argv) { - if(argc != 1) { - std::cout << argv[0] << "takes no arguments.\n"; - return 1; - } - std::cout << "This is project " << PROJECT_NAME << ".\n"; - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 warning level 0/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 warning level 0/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/214 warning level 0/meson.build" 2020-01-07 21:09:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/214 warning level 0/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('warning_level', 'cpp', default_options : ['warning_level=0']) - -exe = executable('main', 'main.cpp', install : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 link custom/custom_stlib.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 link custom/custom_stlib.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 link custom/custom_stlib.py" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 link custom/custom_stlib.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -#!/usr/bin/env python3 - -import shutil, sys, subprocess, argparse, pathlib -import platform - -parser = argparse.ArgumentParser() - -parser.add_argument('--private-dir', required=True) -parser.add_argument('-o', required=True) -parser.add_argument('cmparr', nargs='+') - -contents = '''#include - -void flob(void) { - printf("Now flobbing.\\n"); -} -''' - -def get_pic_args(): - platname = platform.system().lower() - if platname in ['windows', 'mingw', 'darwin'] or platname.startswith('cygwin'): - return [] - return ['-fPIC'] - -def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array): - if shutil.which('ar'): - static_linker = 'ar' - elif shutil.which('llvm-ar'): - static_linker = 'llvm-ar' - elif shutil.which('gcc-ar'): - static_linker = 'gcc-ar' - else: - sys.exit('Could not detect a static linker.') - o_file = c_file.with_suffix('.o') - compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)] - compile_cmd += get_pic_args() - subprocess.check_call(compile_cmd) - out_file = pathlib.Path(outfile) - if out_file.exists(): - out_file.unlink() - link_cmd = [static_linker, 'csr', outfile, str(o_file)] - subprocess.check_call(link_cmd) - return 0 - - -def generate_lib_msvc(outfile, c_file, private_dir, compiler_array): - static_linker = 'lib' - o_file = c_file.with_suffix('.obj') - compile_cmd = compiler_array + ['/MDd', - '/nologo', - '/ZI', - '/Ob0', - '/Od', - '/c', - '/Fo' + str(o_file), - str(c_file)] - subprocess.check_call(compile_cmd) - out_file = pathlib.Path(outfile) - if out_file.exists(): - out_file.unlink() - link_cmd = [static_linker, - '/nologo', - '/OUT:' + str(outfile), - str(o_file)] - subprocess.check_call(link_cmd) - return 0 - -def generate_lib(outfile, private_dir, compiler_array): - private_dir = pathlib.Path(private_dir) - if not private_dir.exists(): - private_dir.mkdir() - c_file = private_dir / 'flob.c' - c_file.write_text(contents) - for i in compiler_array: - if (i.endswith('cl') or i.endswith('cl.exe')) and 'clang-cl' not in i: - return generate_lib_msvc(outfile, c_file, private_dir, compiler_array) - return generate_lib_gnulike(outfile, c_file, private_dir, compiler_array) - -if __name__ == '__main__': - options = parser.parse_args() - sys.exit(generate_lib(options.o, options.private_dir, options.cmparr)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 link custom/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 link custom/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 link custom/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 link custom/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -void flob(void); - -int foo(void) -{ - flob(); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 link custom/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 link custom/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 link custom/meson.build" 2020-01-07 21:09:48.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 link custom/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -project('linkcustom', 'c') - -# This would require passing the static linker to the build script or having -# it detect it by itself. I'm too lazy to implement it now and it is not -# really needed for testing that custom targets work. It is the responsibility -# of the custom target to produce things in the correct format. -assert(not meson.is_cross_build(), - 'MESON_SKIP_TEST cross checking not implemented.') - -cc = meson.get_compiler('c') -genprog = find_program('custom_stlib.py') - -clib = custom_target('linkcustom', - output: 'libflob.a', - command: [genprog, - '-o', '@OUTPUT@', - '--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array()) - -# custom_target tests - -exe = executable('prog', 'prog.c', link_with: clib) -test('linkcustom', exe) - -d = declare_dependency(link_with: clib) - -exe2 = executable('prog2', 'prog.c', dependencies: d) -test('linkcustom2', exe2) - -# Link whole tests - -exe3 = executable('prog3', 'prog.c', link_whole: clib) -test('linkwhole', exe) - -d2 = declare_dependency(link_whole: clib) - -exe4 = executable('prog4', 'prog.c', dependencies: d2) -test('linkwhole2', exe2) - -# custom_target[i] tests - -exe_i = executable('prog_i', 'prog.c', link_with: clib[0]) -test('linkcustom', exe_i) - -d_i = declare_dependency(link_with: clib[0]) - -exe2_i = executable('prog2_i', 'prog.c', dependencies: d_i) -test('linkcustom2_i', exe2_i) - -shared_library('lib1', 'lib.c', link_whole: clib) - -# Link whole tests - -exe3_i = executable('prog3_i', 'prog.c', link_whole: clib[0]) -test('linkwhole', exe) - -d2_i = declare_dependency(link_whole: clib[0]) - -exe4_i = executable('prog4_i', 'prog.c', dependencies: d2_i) -test('linkwhole2_i', exe2_i) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 link custom/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 link custom/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 link custom/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 link custom/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -void flob(void); - -int main(void) { - flob(); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/aarch64.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/aarch64.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/aarch64.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/aarch64.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "common.h" +#include + +void initialize_target() +{ + std::cout << ANSI_START << "some " << THE_TARGET + << " initialization" << ANSI_END << std::endl; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/arm32.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/arm32.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/arm32.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/arm32.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "common.h" +#include + +void initialize_target() +{ + std::cout << ANSI_START << "a different " << THE_TARGET + << " initialization" << ANSI_END << std::endl; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/arm.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/arm.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/arm.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/arm.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include "arm.h" + +const char *ARMBoard::target() +{ + return THE_TARGET; +} + +void ARMBoard::some_arm_thing() +{ +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/arm.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/arm.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/arm.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/arm.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +#ifndef ARM_H +#define ARM_H 1 + +#include "common.h" + +struct ARMBoard: Board { + const char *target(); + void some_arm_thing(); +}; + + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/versatilepb.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/versatilepb.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/versatilepb.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/versatilepb.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include +#include "common.h" +#include "arm.h" + +struct VersatilePBBoard: ARMBoard { + void say_hello(); +}; + +void VersatilePBBoard::say_hello() +{ + some_arm_thing(); + std::cout << ANSI_START << "I am the versatilepb board" + << ANSI_END << std::endl; +} + +static VersatilePBBoard versatilepb; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/virt.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/virt.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/virt.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/virt.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include +#include "common.h" +#include "arm.h" + +struct VirtBoard: ARMBoard { + void say_hello(); +}; + +void VirtBoard::say_hello() +{ + some_arm_thing(); + std::cout << ANSI_START << "I am the virt board" + << ANSI_END << std::endl; +} + +static VirtBoard virt; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/xlnx_zcu102.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/xlnx_zcu102.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/arm/xlnx_zcu102.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/arm/xlnx_zcu102.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include +#include "common.h" +#include "arm.h" + +struct XlnxZCU102Board: ARMBoard { + void say_hello(); +}; + +void XlnxZCU102Board::say_hello() +{ + some_arm_thing(); + std::cout << ANSI_START << "I am the xlnx_zcu102 board" + << ANSI_END << std::endl; +} + +static XlnxZCU102Board xlnx_zcu102; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +specific.add(when: 'TARGET_ARM', if_true: files('arm/arm.cc', 'arm/arm32.cc')) +specific.add(when: 'TARGET_AARCH64', if_true: files('arm/arm.cc', 'arm/aarch64.cc')) +specific.add(when: 'CONFIG_VIRT', if_true: files('arm/virt.cc')) +specific.add(when: 'CONFIG_XLNX_ZCU102', if_true: files('arm/xlnx_zcu102.cc')) +specific.add(when: 'CONFIG_VERSATILEPB', if_true: files('arm/versatilepb.cc')) + +specific.add(when: 'TARGET_X86', if_true: files('x86/pc.cc')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/x86/pc.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/x86/pc.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/boards/x86/pc.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/boards/x86/pc.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,26 @@ +#include +#include "common.h" + +struct X86Board: Board { + const char *target(); + void say_hello(); +}; + +const char *X86Board::target() +{ + return THE_TARGET; +} + +void X86Board::say_hello() +{ + std::cout << ANSI_START << "I am a 1996 PC" + << ANSI_END << std::endl; +} + +void initialize_target() +{ + std::cout << ANSI_START << "ready, set, go" + << ANSI_END << std::endl; +} + +static X86Board pc; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/common.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/common.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/common.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/common.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,41 @@ +#ifndef COMMON_H +#define COMMON_H 1 + +/* + * target-specific code will print in yellow, common code will print + * in grey. + */ +#ifdef THE_TARGET +#define ANSI_START "\x1b[33;1m" +#define ANSI_END "\x1b[0m" +#else +#define ANSI_START "" +#define ANSI_END "" +#endif + +void some_random_function(); +void initialize_target(); + +struct Board { + Board *next; + Board(); + virtual ~Board(); + virtual void say_hello() = 0; + virtual const char *target() = 0; +}; + +struct Device { + Device *next; + Device(); + virtual ~Device(); + virtual void say_hello() = 0; +}; + +struct Dependency { + Dependency *next; + Dependency(); + virtual ~Dependency(); + virtual void initialize() = 0; +}; + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/config/aarch64" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/config/aarch64" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/config/aarch64" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/config/aarch64" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +TARGET_AARCH64=y +CONFIG_VIRT=y +CONFIG_XLNX_ZCU102=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_MMIO=y diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/config/arm" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/config/arm" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/config/arm" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/config/arm" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +TARGET_ARM=y +CONFIG_VIRT=y +CONFIG_VERSATILEPB=y diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/config/x86" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/config/x86" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/config/x86" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/config/x86" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +TARGET_X86=y +CONFIG_PC=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_PCI=y diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +specific.add(when: 'CONFIG_VIRTIO', if_true: files('virtio.cc')) +common.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('virtio-pci.cc')) +common.add(when: 'CONFIG_VIRTIO_MMIO', if_true: files('virtio-mmio.cc')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/virtio.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/virtio.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/virtio.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/virtio.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include +#include "common.h" +#include "virtio.h" + +void VirtioDevice::some_virtio_thing() { +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/virtio.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/virtio.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/virtio.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/virtio.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#ifndef VIRTIO_H +#define VIRTIO_H 1 + +#include "common.h" + +struct VirtioDevice: Device { + void some_virtio_thing(); +}; + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/virtio-mmio.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/virtio-mmio.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/virtio-mmio.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/virtio-mmio.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include +#include "common.h" +#include "virtio.h" + +struct VirtioMMIODevice: VirtioDevice { + void say_hello(); +}; + +void VirtioMMIODevice::say_hello() +{ + some_virtio_thing(); + std::cout << ANSI_START << "virtio-mmio is available" + << ANSI_END << std::endl; +} + +static VirtioMMIODevice virtio_mmio; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/virtio-pci.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/virtio-pci.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/devices/virtio-pci.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/devices/virtio-pci.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include +#include "common.h" +#include "virtio.h" + +struct VirtioPCIDevice: VirtioDevice { + void say_hello(); +}; + +void VirtioPCIDevice::say_hello() +{ + some_virtio_thing(); + std::cout << ANSI_START << "virtio-pci is available" + << ANSI_END << std::endl; +} + +static VirtioPCIDevice virtio_pci; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/main.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/main.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/main.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/main.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,32 @@ +#include +#include +#include "common.h" + +Board* boards; +Device* devices; +Dependency* deps; + +Board::Board() { this->next = boards; boards = this; } +Board::~Board() {} + +Device::Device() { this->next = devices; devices = this; } +Device::~Device() {} + +Dependency::Dependency() { this->next = deps; deps = this; } +Dependency::~Dependency() {} + +int main(void) +{ + some_random_function(); + for (auto d = deps; d; d = d->next) + d->initialize(); + + initialize_target(); + for (auto b = boards; b; b = b->next) { + std::cout << ANSI_START << b->target() << " - " << ANSI_END; + b->say_hello(); + } + + for (auto d = devices; d; d = d->next) + d->say_hello(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/meson.build" 2021-10-23 16:50:30.000000000 +0000 @@ -0,0 +1,52 @@ +# a sort-of realistic example that combines the sourceset and keyval +# modules, inspired by QEMU's build system + +project('sourceset-example', 'cpp', default_options: ['cpp_std=c++11']) + +cppid = meson.get_compiler('cpp').get_id() +if cppid == 'pgi' + error('MESON_SKIP_TEST: Even PGI 19.4 that claims C++17 full support, cannot handle auto x = y syntax used in this test.') +endif + +ss = import('sourceset') +keyval = import('keyval') + +zlib = declare_dependency(compile_args: '-DZLIB=1') +another = declare_dependency(compile_args: '-DANOTHER=1') +not_found = dependency('not-found', required: false) + +common = ss.source_set() +specific = ss.source_set() + +common.add(files('main.cc')) +common.add(when: [zlib, another], if_true: files('zlib.cc')) +common.add(when: not_found, + if_true: files('was-found.cc'), + if_false: files('not-found.cc')) + +subdir('boards') +subdir('devices') + +if meson.is_unity() + specific.add_all(common) + common = ss.source_set() +endif + +common_lib = static_library('common', common.all_sources(), + dependencies: common.all_dependencies()) + +targets = [ 'arm', 'aarch64', 'x86' ] +target_dirs = { 'arm' : 'arm', 'aarch64' : 'arm', 'x86': 'x86' } + +foreach x : targets + config = keyval.load('config' / x) + target_specific = specific.apply(config, strict: false) + target_common = common.apply(config, strict: false) + target_deps = target_specific.dependencies() + target_common.dependencies() + executable(x, + objects: common_lib.extract_objects(target_common.sources()), + sources: target_specific.sources(), + dependencies: target_deps, + include_directories: 'boards' / target_dirs[x], + cpp_args: '-DTHE_TARGET="' + x + '"') +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/not-found.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/not-found.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/not-found.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/not-found.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include "common.h" + +void some_random_function() +{ + std::cout << ANSI_START << "everything's alright" + << ANSI_END << std::endl; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/was-found.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/was-found.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/was-found.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/was-found.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +void some_random_function() +{ + std::cout << ANSI_START << "huh?" + << ANSI_END << std::endl; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/zlib.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/zlib.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/215 source set realistic example/zlib.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/215 source set realistic example/zlib.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#include +#include "common.h" + +struct ZLibDependency : Dependency { + void initialize(); +}; + +void ZLibDependency::initialize() { + if (ZLIB && ANOTHER) { + std::cout << ANSI_START << "hello from zlib" + << ANSI_END << std::endl; + } +} + +ZLibDependency zlib; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 custom target input extracted objects/check_object.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 custom target input extracted objects/check_object.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 custom target input extracted objects/check_object.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 custom target input extracted objects/check_object.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import sys, os + +if __name__ == '__main__': + if len(sys.argv) != 3: + print(sys.argv[0], 'object', 'output') + sys.exit(1) + elif os.path.exists(sys.argv[1]): + with open(sys.argv[2], 'wb') as out: + pass + else: + sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 custom target input extracted objects/libdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 custom target input extracted objects/libdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 custom target input extracted objects/libdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 custom target input extracted objects/libdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +objlib = static_library('object', 'source.c', override_options : ['unity=off']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 custom target input extracted objects/libdir/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 custom target input extracted objects/libdir/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 custom target input extracted objects/libdir/source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 custom target input extracted objects/libdir/source.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func1_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 custom target input extracted objects/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 custom target input extracted objects/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 custom target input extracted objects/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 custom target input extracted objects/meson.build" 2021-10-23 16:50:26.000000000 +0000 @@ -0,0 +1,18 @@ +project('custom target input extracted objects', 'c') + +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: sometimes Xcode puts object files in weird paths and we can not extract them.') +endif + + +checker = find_program('check_object.py') + +cc = meson.get_compiler('c').cmd_array().get(-1) + +subdir('libdir') + +custom_target('check', + input: objlib.extract_objects('source.c'), + output: 'objcheck', + command: [checker, '@INPUT@', '@OUTPUT@'], + build_by_default: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 link custom_i single from multiple/generate_conflicting_stlibs.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 link custom_i single from multiple/generate_conflicting_stlibs.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 link custom_i single from multiple/generate_conflicting_stlibs.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 link custom_i single from multiple/generate_conflicting_stlibs.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -#!/usr/bin/env python3 - -import shutil, sys, subprocess, argparse, pathlib - -parser = argparse.ArgumentParser() - -parser.add_argument('--private-dir', required=True) -parser.add_argument('-o', nargs='+', required=True) -parser.add_argument('cmparr', nargs='+') - -contents = [''' -int flob() { - return 0; -} -''', ''' -int flob() { - return 1; -} -'''] - -def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array): - if shutil.which('ar'): - static_linker = 'ar' - elif shutil.which('llvm-ar'): - static_linker = 'llvm-ar' - elif shutil.which('gcc-ar'): - static_linker = 'gcc-ar' - else: - sys.exit('Could not detect a static linker.') - o_file = c_file.with_suffix('.o') - compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)] - subprocess.check_call(compile_cmd) - out_file = pathlib.Path(outfile) - if out_file.exists(): - out_file.unlink() - link_cmd = [static_linker, 'csr', outfile, str(o_file)] - subprocess.check_call(link_cmd) - return 0 - - -def generate_lib_msvc(outfile, c_file, private_dir, compiler_array): - static_linker = 'lib' - o_file = c_file.with_suffix('.obj') - compile_cmd = compiler_array + ['/MDd', - '/nologo', - '/ZI', - '/Ob0', - '/Od', - '/c', - '/Fo' + str(o_file), - str(c_file)] - subprocess.check_call(compile_cmd) - out_file = pathlib.Path(outfile) - if out_file.exists(): - out_file.unlink() - link_cmd = [static_linker, - '/nologo', - '/OUT:' + str(outfile), - str(o_file)] - subprocess.check_call(link_cmd) - return 0 - -def generate_lib(outfiles, private_dir, compiler_array): - private_dir = pathlib.Path(private_dir) - if not private_dir.exists(): - private_dir.mkdir() - - for i, content in enumerate(contents): - c_file = private_dir / ('flob_' + str(i + 1) + '.c') - c_file.write_text(content) - outfile = outfiles[i] - - cl_found = False - for cl_arg in compiler_array: - if (cl_arg.endswith('cl') or cl_arg.endswith('cl.exe')) and 'clang-cl' not in cl_arg: - ret = generate_lib_msvc(outfile, c_file, private_dir, compiler_array) - if ret > 0: - return ret - else: - cl_found = True - break - if not cl_found: - ret = generate_lib_gnulike(outfile, c_file, private_dir, compiler_array) - if ret > 0: - return ret - return 0 - -if __name__ == '__main__': - options = parser.parse_args() - sys.exit(generate_lib(options.o, options.private_dir, options.cmparr)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 link custom_i single from multiple/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 link custom_i single from multiple/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 link custom_i single from multiple/meson.build" 2020-01-07 21:09:48.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 link custom_i single from multiple/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -project('linkcustom', 'c') - -# This would require passing the static linker to the build script or having -# it detect it by itself. I'm too lazy to implement it now and it is not -# really needed for testing that custom targets work. It is the responsibility -# of the custom target to produce things in the correct format. -assert(not meson.is_cross_build(), - 'MESON_SKIP_TEST cross checking not implemented.') - -cc = meson.get_compiler('c') -genprog = find_program('generate_conflicting_stlibs.py') - -clib = custom_target('linkcustom', - output: ['libflob_1.a', 'libflob_2.a'], - command: [genprog, - '-o', '@OUTPUT@', - '--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array()) - -clib_2 = clib[1] - -exe = executable('prog', 'prog.c', link_with: clib_2) -test('linkcustom', exe) - -d = declare_dependency(link_with: clib_2) - -exe2 = executable('prog2', 'prog.c', dependencies: d) -test('linkcustom2', exe2) - -# Link whole tests - -exe3 = executable('prog3', 'prog.c', link_whole: clib_2) -test('linkwhole', exe) - -d2 = declare_dependency(link_whole: clib_2) - -exe4 = executable('prog4', 'prog.c', dependencies: d2) -test('linkwhole2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 link custom_i single from multiple/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 link custom_i single from multiple/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/216 link custom_i single from multiple/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/216 link custom_i single from multiple/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int flob(void); - -int main(void) { - return (flob() == 1 ? 0 : 1); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 link custom_i multiple from multiple/generate_stlibs.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 link custom_i multiple from multiple/generate_stlibs.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 link custom_i multiple from multiple/generate_stlibs.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 link custom_i multiple from multiple/generate_stlibs.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -#!/usr/bin/env python3 - -import shutil, sys, subprocess, argparse, pathlib - -parser = argparse.ArgumentParser() - -parser.add_argument('--private-dir', required=True) -parser.add_argument('-o', nargs='+', required=True) -parser.add_argument('cmparr', nargs='+') - -contents = ['''#include - -void flob_1() { - printf("Now flobbing #1.\\n"); -} -''', '''#include - -void flob_2() { - printf("Now flobbing #2.\\n"); -} -'''] - -def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array): - if shutil.which('ar'): - static_linker = 'ar' - elif shutil.which('llvm-ar'): - static_linker = 'llvm-ar' - elif shutil.which('gcc-ar'): - static_linker = 'gcc-ar' - else: - sys.exit('Could not detect a static linker.') - o_file = c_file.with_suffix('.o') - compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)] - subprocess.check_call(compile_cmd) - out_file = pathlib.Path(outfile) - if out_file.exists(): - out_file.unlink() - link_cmd = [static_linker, 'csr', outfile, str(o_file)] - subprocess.check_call(link_cmd) - return 0 - - -def generate_lib_msvc(outfile, c_file, private_dir, compiler_array): - static_linker = 'lib' - o_file = c_file.with_suffix('.obj') - compile_cmd = compiler_array + ['/MDd', - '/nologo', - '/ZI', - '/Ob0', - '/Od', - '/c', - '/Fo' + str(o_file), - str(c_file)] - subprocess.check_call(compile_cmd) - out_file = pathlib.Path(outfile) - if out_file.exists(): - out_file.unlink() - link_cmd = [static_linker, - '/nologo', - '/OUT:' + str(outfile), - str(o_file)] - subprocess.check_call(link_cmd) - return 0 - -def generate_lib(outfiles, private_dir, compiler_array): - private_dir = pathlib.Path(private_dir) - if not private_dir.exists(): - private_dir.mkdir() - - for i, content in enumerate(contents): - c_file = private_dir / ('flob_' + str(i + 1) + '.c') - c_file.write_text(content) - outfile = outfiles[i] - - cl_found = False - for cl_arg in compiler_array: - if (cl_arg.endswith('cl') or cl_arg.endswith('cl.exe')) and 'clang-cl' not in cl_arg: - ret = generate_lib_msvc(outfile, c_file, private_dir, compiler_array) - if ret > 0: - return ret - else: - cl_found = True - break - if not cl_found: - ret = generate_lib_gnulike(outfile, c_file, private_dir, compiler_array) - if ret > 0: - return ret - return 0 - -if __name__ == '__main__': - options = parser.parse_args() - sys.exit(generate_lib(options.o, options.private_dir, options.cmparr)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 link custom_i multiple from multiple/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 link custom_i multiple from multiple/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 link custom_i multiple from multiple/meson.build" 2020-01-07 21:09:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 link custom_i multiple from multiple/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -project('linkcustom', 'c') - -# This would require passing the static linker to the build script or having -# it detect it by itself. I'm too lazy to implement it now and it is not -# really needed for testing that custom targets work. It is the responsibility -# of the custom target to produce things in the correct format. -assert(not meson.is_cross_build(), - 'MESON_SKIP_TEST cross checking not implemented.') - -cc = meson.get_compiler('c') -genprog = find_program('generate_stlibs.py') - -clib = custom_target('linkcustom', - output: ['libflob_1.a', 'libflob_2.a'], - command: [genprog, - '-o', '@OUTPUT@', - '--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array()) - -clibs = [clib[0], clib[1]] - -exe = executable('prog', 'prog.c', link_with: clibs) -test('linkcustom', exe) - -d = declare_dependency(link_with: clibs) - -exe2 = executable('prog2', 'prog.c', dependencies: d) -test('linkcustom2', exe2) - -# Link whole tests - -exe3 = executable('prog3', 'prog.c', link_whole: clibs) -test('linkwhole', exe) - -d2 = declare_dependency(link_whole: clibs) - -exe4 = executable('prog4', 'prog.c', dependencies: d2) -test('linkwhole2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 link custom_i multiple from multiple/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 link custom_i multiple from multiple/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 link custom_i multiple from multiple/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 link custom_i multiple from multiple/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -void flob_1(void); -void flob_2(void); - -int main(void) { - flob_1(); - flob_2(); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 test priorities/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 test priorities/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 test priorities/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 test priorities/meson.build" 2021-10-23 16:50:27.000000000 +0000 @@ -0,0 +1,22 @@ +project('test priorities', 'c') + +test_prog = find_program('testprog.py') + +test('priority 0', test_prog, + args : ['0'], +) + +test('priority neg 10', test_prog, + args : ['-10'], + priority : -10 +) + +test('priority 1000', test_prog, + args : ['1000'], + priority : 1000 +) + +test('priority 50', test_prog, + args : ['50'], + priority : 50 +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 test priorities/testprog.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 test priorities/testprog.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/217 test priorities/testprog.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/217 test priorities/testprog.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +import sys + +print(sys.argv[1]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 dependency get_variable method/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 dependency get_variable method/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 dependency get_variable method/meson.build" 2020-01-07 21:09:53.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 dependency get_variable method/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -project( - 'dependency get_variable', - ['c', 'cpp'], -) - -# Just some string that nothing should return -default = 'asufoiqwjtl;adjfbpiuqwoehtl;ajdfl;ghal;sdjg' - -dep = dependency('zlib', method: 'pkg-config', required : false) -if not dep.found() - warning('Skipping pkg-config tests as zlib is not available or is not pkg-config') -else - # Test for regular pkg-config - # We don't know what the value will be, but we know it should be the same - dep = dependency('zlib', method : 'pkg-config') - assert(dep.get_pkgconfig_variable('prefix') == dep.get_variable(pkgconfig : 'prefix'), - 'Got different values from get_pkgconfig_variable and get_variable(pkgconfig: )') - assert(dep.get_variable(pkgconfig : default, default_value : default) == default, - 'pkg-config didn\'t get default when we should have.') - assert(dep.get_variable(pkgconfig : 'prefix', default_value : default) != default, - 'pkg-config got default when we shouldn\'t have.') -endif - -dep_ct = dependency('llvm', method : 'config-tool', required : false) -if not dep_ct.found() - warning('Skipping config-tool tests as llvm is not available or llvm-config was not found.') -else - assert(dep_ct.get_configtool_variable('has-rtti') == dep_ct.get_variable(configtool : 'has-rtti'), - 'Got different values from get_configtool_variable and get_variable(configtool: )') - assert(dep_ct.get_variable(configtool : default, default_value : default) == default, - 'config-tool didn\'t get default when we should have.') - assert(dep_ct.get_variable(configtool : 'has-rtti', default_value : default) != default, - 'config-tool got default when we shouldn\'t have.') -endif - -dep_cm = dependency('llvm', method : 'cmake', required : false) -if not dep_cm.found() - warning('Skipping cmake tests as llvm is not available via the cmake finder.') -else - if dep_ct.found() - assert((dep_cm.get_variable(cmake : 'LLVM_ENABLE_RTTI') == 'ON') == (dep_ct.get_variable(configtool : 'has-rtti') == 'YES'), - 'RTTI information for cmake and config tools disagree') - endif - assert(dep_cm.get_variable(cmake : default, default_value : default) == default, - 'cmake didn\'t get default when we should have.') - assert(dep_cm.get_variable(cmake : 'LLVM_ENABLE_RTTI', default_value : default) != default, - 'cmake config-tool got default when we shouldn\'t have.') -endif - -idep = declare_dependency() -assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', default_value : default) == default, - 'Got something other than default from an internal dependency') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/meson.build" 2021-10-23 16:50:28.000000000 +0000 @@ -0,0 +1,8 @@ +project('Include Here', 'c') + +# The layout with the .h file in . and the .c files in src/ is critical to +# tickle the bug #5847 + +inc = include_directories('.') + +subdir('src') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/rone.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/rone.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/rone.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/rone.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int rOne(void); \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/src/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/src/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/src/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/src/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "rone.h" + +int main(void) { + return rOne(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +t = executable( + 'main', + ['main.c', 'rone.c'], + include_directories : inc, + implicit_include_directories : false, +) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/src/rone.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/src/rone.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/218 include_dir dot/src/rone.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/218 include_dir dot/src/rone.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int rOne(void) { + return 1; +} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 include_type dependency/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 include_type dependency/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 include_type dependency/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 include_type dependency/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include + +using namespace std; + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 include_type dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 include_type dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 include_type dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 include_type dependency/meson.build" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,44 @@ +project( + 'dependency include_type', + ['c', 'cpp'], +) + +dep = dependency('zlib', method: 'pkg-config', required : false) +boost_dep = dependency('boost', modules: ['graph'], include_type : 'system', required: false) + +if not dep.found() + error('MESON_SKIP_TEST zlib was not found') +endif + +if not boost_dep.found() + error('MESON_SKIP_TEST boost was not found') +endif + +assert(dep.include_type() == 'preserve', 'include_type must default to "preserve"') + +dep_sys = dep.as_system() +assert(dep_sys.include_type() == 'system', 'as_system must return a system dep') + +dep2 = dependency('zlib', method: 'pkg-config', include_type : 'system') +assert(dep2.include_type() == 'system', 'include_type must be true when set') + +dep2_sys = dep2.as_system('non-system') +assert(dep2_sys.include_type() == 'non-system', 'as_system must set include_type correctly') + +sp = subproject('subDep') +sp_dep = sp.get_variable('subDep_dep') +assert(sp_dep.include_type() == 'preserve', 'default is preserve') + +sp_dep_sys = sp_dep.as_system('system') +assert(sp_dep_sys.include_type() == 'system', 'changing include_type works') +assert(sp_dep.include_type() == 'preserve', 'as_system must not mutate the original object') + +fallback = dependency('sdffgagf_does_not_exist', include_type: 'system', fallback: ['subDep', 'subDep_dep']) +assert(fallback.include_type() == 'system', 'include_type works with dependency fallback') + +fallback_empty = dependency('', include_type: 'system', fallback: ['subDep', 'subDep_dep']) +assert(fallback_empty.include_type() == 'system', 'include_type works with empty name dependency fallback') + +# Check that PCH works with `include_type : 'system'` See https://github.com/mesonbuild/meson/issues/7167 +main_exe = executable('main_exe', 'main.cpp', cpp_pch: 'pch/test.hpp', dependencies: boost_dep) +test('main_test', main_exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 include_type dependency/pch/test.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 include_type dependency/pch/test.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 include_type dependency/pch/test.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 include_type dependency/pch/test.hpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 include_type dependency/subprojects/subDep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 include_type dependency/subprojects/subDep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 include_type dependency/subprojects/subDep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 include_type dependency/subprojects/subDep/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('subDep', ['cpp']) + +subDep_dep = declare_dependency(compile_args : []) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/a.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include -#include "all.h" - -int main(void) -{ - if (p) abort(); - f(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/all.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/all.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/all.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/all.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -extern void f(void); -extern void g(void); -extern void h(void); -extern void undefined(void); - -/* No extern here to get a common symbol */ -void (*p)(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/f.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/f.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/f.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/f.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "all.h" - -void f(void) -{ -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/g.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/g.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/g.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/g.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include "all.h" - -void g(void) -{ - h(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/meson.build" 2020-01-07 21:09:54.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -project('a', 'c') - -good = declare_dependency(link_with: static_library('good', 'g.c')) -bad = declare_dependency(link_args: 'nonexistent.a') -not_found = dependency('invalid', required: false) - -source_set = import('sourceset') - -sources = source_set.source_set() -sources.add(when: 'YES', if_false: ['nope.c']) -sources.add(when: 'YES1', if_true: files('a.c')) -subdir('subdir') -sources.add(when: 'NO', if_true: 'nope.c', if_false: ['f.c']) -sources.add(when: 'NO', if_true: bad, if_false: ['f.c']) - -sources.add(when: 'YES2', if_true: good) - -# dependencies as conditions -sources.add(when: not_found, if_true: 'nope.c') - -# test add_all -sources2 = source_set.source_set() -sources2.add(when: 'YES1', if_true: 'nope.c') -sources.add_all(when: 'NO', if_true: sources2) - -# test duplicate items -sources.add(when: 'YES1', if_true: files('a.c')) - -conf1 = configuration_data() -conf1.set10('YES', true) -conf1.set10('YES1', true) -conf1.set10('YES2', false) -conf1.set10('NO', false) -result1 = sources.apply(conf1) - -conf2 = configuration_data() -conf2.set10('YES', true) -conf2.set10('YES1', false) -conf2.set10('YES2', true) -conf2.set10('NO', false) -result2 = sources.apply(conf2) - -# Each target will recompile the objects -executable('first', sources: result1.sources(), dependencies: result1.dependencies()) -executable('second', sources: result2.sources(), dependencies: result2.dependencies()) - -# All target will use the same object files -if meson.is_unity() - message('Skipping extraction test because this is a Unity build.') -else - all_objs = static_library('all_objs', sources.all_sources()) - executable('first_via_lib', objects: all_objs.extract_objects(result1.sources()), dependencies: result1.dependencies()) - executable('second_via_lib', objects: all_objs.extract_objects(result2.sources()), dependencies: result2.dependencies()) -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/nope.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/nope.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/nope.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/nope.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#include "all.h" - -void (*p)(void) = undefined; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/subdir/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/subdir/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/subdir/b.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/subdir/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include -#include "all.h" - -void h(void) -{ -} - -int main(void) -{ - if (p) abort(); - f(); - g(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/219 source set configuration_data/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/219 source set configuration_data/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -sources.add(when: ['YES2', good], if_true: [ files('b.c') ]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 global arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 global arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 global arg/meson.build" 2020-01-07 21:06:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 global arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -project('global arg test', 'cpp', 'c') - -add_global_arguments('-DMYTHING', language : 'c', native : true) -add_global_arguments('-DMYTHING', language : 'c', native : false) -add_global_arguments('-DMYCPPTHING', language : 'cpp', native : true) -add_global_arguments('-DMYCPPTHING', language : 'cpp', native : false) - -add_global_arguments('-DGLOBAL_BUILD', language : 'c', native : true) -add_global_arguments('-DGLOBAL_HOST', language : 'c', native : false) - -build_c_args = ['-DARG_BUILD'] -c_args = ['-DARG_HOST'] - -add_global_arguments('-DMYCANDCPPTHING', language: ['c', 'cpp'], native: true) -add_global_arguments('-DMYCANDCPPTHING', language: ['c', 'cpp'], native: false) - -exe1 = executable('prog1', 'prog.c', c_args : build_c_args, native : true) -exe2 = executable('prog2', 'prog.c', c_args : c_args, native : false) -exe3 = executable('prog3', 'prog.cc') - -test('prog1', exe1) -test('prog2', exe2) -test('prog3', exe3) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 global arg/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 global arg/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 global arg/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 global arg/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -#ifndef MYTHING - #error "Global argument not set" -#endif - -#ifdef MYCPPTHING - #error "Wrong global argument set" -#endif - -#ifndef MYCANDCPPTHING - #error "Global argument not set" -#endif - -#if !defined(GLOBAL_HOST) && !defined(GLOBAL_BUILD) - #error "Neither global_host nor glogal_build is set." -#endif - -#if defined(GLOBAL_HOST) && defined(GLOBAL_BUILD) - #error "Both global build and global host set." -#endif - -#ifdef GLOBAL_BUILD - #ifndef ARG_BUILD - #error "Global is build but arg_build is not set." - #endif - - #ifdef ARG_HOST - #error "Global is build but arg host is set." - #endif -#endif - -#ifdef GLOBAL_HOST - #ifndef ARG_HOST - #error "Global is host but arg_host is not set." - #endif - - #ifdef ARG_BUILD - #error "Global is host but arg_build is set." - #endif -#endif - -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 global arg/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 global arg/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 global arg/prog.cc" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 global arg/prog.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#ifdef MYTHING -#error "Wrong global argument set" -#endif - -#ifndef MYCPPTHING -#error "Global argument not set" -#endif - -#ifndef MYCANDCPPTHING -#error "Global argument not set" -#endif - -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/func2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/func2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/func2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/func2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#ifdef CTHING +#error "Local C argument set in wrong target" +#endif + +#ifdef CPPTHING +#error "Local CPP argument set in wrong target" +#endif + +int func(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/func.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/func.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/func.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/func.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#ifndef CTHING +#error "Local argument not set" +#endif + +#ifdef CPPTHING +#error "Wrong local argument set" +#endif + +int func(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/meson.build" 2021-10-23 16:48:00.000000000 +0000 @@ -0,0 +1,9 @@ +project('local arg test', 'cpp', 'c') + +exe1 = executable('prog', 'prog.cc', 'func.c', \ +c_args : '-DCTHING', \ +cpp_args : '-DCPPTHING') +exe2 = executable('prog2', 'prog2.cc', 'func2.c') + +test('prog1', exe1) +test('prog2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/prog2.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/prog2.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/prog2.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/prog2.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#ifdef CTHING +#error "Local C argument set in wrong target" +#endif + +#ifdef CPPTHING +#error "Local CPP argument set in wrong target" +#endif + +extern "C" int func(); + +int main(void) { + return func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/21 target arg/prog.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/21 target arg/prog.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#ifdef CTHING +#error "Wrong local argument set" +#endif + +#ifndef CPPTHING +#error "Local argument not set" +#endif + +extern "C" int func(); + +int main(void) { + return func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,144 @@ +project('fs module test') + +is_windows = build_machine.system() == 'windows' + +fs = import('fs') + +f = files('meson.build') + +assert(fs.exists('meson.build'), 'Existing file reported as missing.') +assert(not fs.exists('nonexisting'), 'Nonexisting file was found.') + +if not is_windows and build_machine.system() != 'cygwin' + # Symlinks on Windows have specific requirements including: + # * Meson running under Python >= 3.8 + # * Windows user permissions to create symlinks, and/or Windows in Developer mode + # so at this time the symlink test is skipped for Windows. + symlink = meson.current_build_dir() / 'a_symlink' + run_command('ln', '-s', '-f', meson.current_source_dir() / 'meson.build', symlink, check: true) + assert(fs.is_symlink(symlink), 'Symlink not detected.') + assert(not fs.is_symlink('meson.build'), 'Regular file detected as symlink.') + assert(not fs.is_symlink(f[0]), 'Regular file detected as symlink.') +endif + +assert(fs.is_file('meson.build'), 'File not detected as a file.') +assert(not fs.is_file('subprojects'), 'Directory detected as a file.') +assert(not fs.is_file('nonexisting'), 'Bad path detected as a file.') + +assert(fs.is_dir('subprojects'), 'Dir not detected correctly.') +assert(not fs.is_dir('meson.build'), 'File detected as a dir.') +assert(not fs.is_dir('nonexisting'), 'Bad path detected as a dir.') + +assert(fs.is_dir('~'), 'home directory not detected') +assert(not fs.is_file('~'), 'home directory detected as file') + +# -- expanduser +assert(fs.expanduser('~') != '~','expanduser failed') +assert(fs.expanduser('~/foo').endswith('foo'), 'expanduser with tail failed') + +# -- as_posix +assert(fs.as_posix('/') == '/', 'as_posix idempotent') +assert(fs.as_posix('\\') == '/', 'as_posix simple') +assert(fs.as_posix('\\\\') == '/', 'as_posix simple') +assert(fs.as_posix('foo\\bar/baz') == 'foo/bar/baz', 'as_posix mixed slash') + +# -- is_absolute +winabs = 'q:/foo' +unixabs = '/foo' +if is_windows + assert(fs.is_absolute(winabs), 'is_absolute windows not detected') + assert(not fs.is_absolute(unixabs), 'is_absolute unix false positive') +else + assert(fs.is_absolute(unixabs), 'is_absolute unix not detected') + assert(not fs.is_absolute(winabs), 'is_absolute windows false positive') +endif + +# -- replace_suffix + +original = 'foo' +assert(fs.replace_suffix(original, '') == original, 'replace_suffix idempotent') +assert(fs.replace_suffix(f[0], '') == 'meson', 'replace_suffix trim') + +original = 'foo.txt' +new = fs.replace_suffix(original, '.ini') +assert(new == 'foo.ini', 'replace_suffix failed') + +new = fs.replace_suffix(f[0], '.ini') +assert(new == 'meson.ini', 'replace_suffix failed') + +original = 'foo' +new = fs.replace_suffix(original, '.ini') +assert(new == 'foo.ini', 'replace_suffix did not add suffix to suffixless file') + +original = 'foo.dll.a' +new = fs.replace_suffix(original, '.so') +assert(new == 'foo.dll.so', 'replace_suffix did not only modify last suffix') + +original = 'foo.dll' +new = fs.replace_suffix(original, '') +assert(new == 'foo', 'replace_suffix did not only delete last suffix') + +# `/` on windows is interpreted like `.drive` which in general may not be `c:/` +# the files need not exist for fs.replace_suffix() +original = is_windows ? 'j:/foo/bar.txt' : '/foo/bar.txt' +new_check = is_windows ? 'j:\\foo\\bar.ini' : '/foo/bar.ini' + +new = fs.replace_suffix(original, '.ini') +assert(new == new_check, 'absolute path replace_suffix failed') + +# -- hash + +md5 = fs.hash('subdir/subdirfile.txt', 'md5') +sha256 = fs.hash('subdir/subdirfile.txt', 'sha256') +assert(md5 == 'd0795db41614d25affdd548314b30b3b', 'md5sum did not match') +assert(sha256 == 'be2170b0dae535b73f6775694fffa3fd726a43b5fabea11b7342f0605917a42a', 'sha256sum did not match') + +f = files('subdir/subdirfile.txt') +md5 = fs.hash(f[0], 'md5') +assert(md5 == 'd0795db41614d25affdd548314b30b3b', 'md5sum did not match') +sha256 = fs.hash(f[0], 'sha256') +assert(sha256 == 'be2170b0dae535b73f6775694fffa3fd726a43b5fabea11b7342f0605917a42a', 'sha256sum did not match') + +# -- size + +size = fs.size('subdir/subdirfile.txt') +assert(size == 19, 'file size not found correctly') + +size = fs.size(f[0]) +assert(size == 19, 'file size not found correctly') + +# -- are filenames referring to the same file? +f1 = 'meson.build' +f2 = 'subdir/../meson.build' +assert(fs.is_samepath(f1, f2), 'is_samepath not detecting same files') +assert(fs.is_samepath(meson.source_root(), 'subdir/..'), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.project_source_root(), 'subdir/..'), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / 'subdir/..'), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.global_source_root(), meson.current_source_dir()), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.global_build_root(), meson.current_build_dir()), 'is_samepath not detecting same directory') +assert(not fs.is_samepath(f1, 'subdir/subdirfile.txt'), 'is_samepath known bad comparison') +assert(not fs.is_samepath('not-a-path', f2), 'is_samepath should not error if path(s) do not exist') + +f = files('meson.build', 'subdir/../meson.build') +assert(fs.is_samepath(f[0], f[1]), 'is_samepath not detercting same files') + +if not is_windows and build_machine.system() != 'cygwin' + assert(fs.is_samepath(symlink, 'meson.build'), 'symlink is_samepath fail') +endif + +# parts of path +assert(fs.parent('foo/bar') == 'foo', 'failed to get dirname') +if not is_windows +assert(fs.parent(f[1]) == 'subdir/..', 'failed to get dirname') +else +assert(fs.parent(f[1]) == 'subdir\..', 'failed to get dirname') +endif +assert(fs.name('foo/bar') == 'bar', 'failed to get basename') +assert(fs.name(f[1]) == 'meson.build', 'failed to get basename') +assert(fs.name('foo/bar/baz.dll.a') == 'baz.dll.a', 'failed to get basename with compound suffix') +assert(fs.stem('foo/bar/baz.dll') == 'baz', 'failed to get stem with suffix') +assert(fs.stem('foo/bar/baz.dll.a') == 'baz.dll', 'failed to get stem with compound suffix') + +subdir('subdir') + +subproject('subbie') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +subdirfiles = files('subdirfile.txt') +assert(fs.exists('subdirfile.txt'), 'Subdir file lookup is broken.') +assert(fs.is_samepath(meson.project_source_root(), '..'), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / '..'), 'is_samepath not detecting same directory') + +assert(fs.is_samepath(subdirfiles[0], 'subdirfile.txt'), 'is_samepath not detecting same directory when using File and str') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subdir/subdirfile.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subdir/subdirfile.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subdir/subdirfile.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subdir/subdirfile.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +I have no content. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subprojects/subbie/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subprojects/subbie/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subprojects/subbie/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subprojects/subbie/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +project('subbie') + +fs = import('fs') + +assert(fs.exists('subprojectfile.txt'), 'Subproject root file not found.') +assert(fs.is_samepath(meson.project_source_root(), meson.current_source_dir()), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir()), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.global_source_root(), meson.current_source_dir() / '../..'), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.global_build_root(), meson.current_build_dir() / '../..'), 'is_samepath not detecting same directory') + +subdir('subsub') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subprojects/subbie/subprojectfile.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subprojects/subbie/subprojectfile.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subprojects/subbie/subprojectfile.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subprojects/subbie/subprojectfile.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +I'm not empty. So there's at least that. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subprojects/subbie/subsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subprojects/subbie/subsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subprojects/subbie/subsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subprojects/subbie/subsub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +assert(fs.exists('subsubfile.txt'), 'Subproject subdir lookup failed.') +assert(fs.is_samepath(meson.project_source_root(), meson.current_source_dir() / '..'), 'is_samepath not detecting same directory') +assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / '..'), 'is_samepath not detecting same directory') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subprojects/subbie/subsub/subsubfile.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subprojects/subbie/subsub/subsubfile.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 fs module/subprojects/subbie/subsub/subsubfile.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 fs module/subprojects/subbie/subsub/subsubfile.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Thank you for looking inside me. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/a.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include -#include "all.h" - -int main(void) -{ - if (p) abort(); - f(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/all.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/all.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/all.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/all.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -extern void f(void); -extern void g(void); -extern void h(void); -extern void undefined(void); - -/* No extern here to get a common symbol */ -void (*p)(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/f.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/f.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/f.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/f.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "all.h" - -void f(void) -{ -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/g.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/g.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/g.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/g.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include "all.h" - -void g(void) -{ - h(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/meson.build" 2020-01-07 21:09:54.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -project('a', 'c') - -good = declare_dependency(link_with: static_library('good', 'g.c')) -bad = declare_dependency(link_args: 'nonexistent.a') -not_found = dependency('invalid', required: false) - -source_set = import('sourceset') - -sources = source_set.source_set() -sources.add(when: 'YES', if_false: ['nope.c']) -sources.add(when: 'YES1', if_true: files('a.c')) -subdir('subdir') -sources.add(when: 'NO', if_true: 'nope.c', if_false: ['f.c']) -sources.add(when: 'NO', if_true: bad, if_false: ['f.c']) - -sources.add(when: 'YES2', if_true: good) - -# dependencies as conditions -sources.add(when: not_found, if_true: 'nope.c') - -# test add_all -sources2 = source_set.source_set() -sources2.add(when: 'YES1', if_true: 'nope.c') -sources.add_all(when: 'NO', if_true: sources2) - -# test duplicate items -sources.add(when: 'YES1', if_true: files('a.c')) - -conf1 = { - 'YES': true, - 'YES1': true, - 'YES2': false, - 'NO': false, -} -result1 = sources.apply(conf1) - -conf2 = { - 'YES': true, - 'YES1': false, - 'YES2': true, - 'NO': false, -} -result2 = sources.apply(conf2) - -# Each target will recompile the objects -executable('first', sources: result1.sources(), dependencies: result1.dependencies()) -executable('second', sources: result2.sources(), dependencies: result2.dependencies()) - -# All target will use the same object files -if meson.is_unity() - message('Skipping extraction test because this is a Unity build.') -else - all_objs = static_library('all_objs', sources.all_sources()) - executable('first_via_lib', objects: all_objs.extract_objects(result1.sources()), dependencies: result1.dependencies()) - executable('second_via_lib', objects: all_objs.extract_objects(result2.sources()), dependencies: result2.dependencies()) -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/nope.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/nope.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/nope.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/nope.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#include "all.h" - -void (*p)(void) = undefined; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/subdir/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/subdir/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/subdir/b.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/subdir/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include -#include "all.h" - -void h(void) -{ -} - -int main(void) -{ - if (p) abort(); - f(); - g(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/220 source set dictionary/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/220 source set dictionary/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -sources.add(when: ['YES2', good], if_true: [ files('b.c') ]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/a.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include "all.h" - -int main(void) -{ - f(); - g(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/all.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/all.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/all.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/all.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -extern void f(void); -extern void g(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/cp.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/cp.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/cp.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/cp.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#! /usr/bin/env python3 - -import sys -from shutil import copyfile -copyfile(*sys.argv[1:]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/f.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/f.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/f.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/f.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "all.h" - -void f(void) -{ -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/g.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/g.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/g.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/g.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "all.h" - -void g(void) -{ -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 source set custom target/meson.build" 2020-01-07 21:09:54.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 source set custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -# Try using sourceset with various kinds of generated sources - -project('a', 'c') - -cp = find_program('cp.py') - -source_set = import('sourceset') -sources = source_set.source_set() - -a_c = custom_target('gen-custom-target', - input: 'a.c', output: 'out_a.c', - command: [cp, '@INPUT@', '@OUTPUT@']) -sources.add(when: 'YES', if_true: a_c) -sources.add(when: 'YES', if_true: a_c[0]) - -f_c = configure_file(input: 'f.c', output: 'out_f.c', copy: true) -sources.add(when: 'YES', if_true: f_c) -sources.add(when: 'YES', if_true: f_c) - -gen = generator(cp, output: 'out_@PLAINNAME@', arguments: ['@INPUT@', '@OUTPUT@']) -g_c = gen.process(files('g.c')) -sources.add(when: 'YES', if_true: g_c) -sources.add(when: 'YES', if_true: g_c) - -conf1 = { 'YES': true, } -result1 = sources.apply(conf1) - -executable('first', sources: result1.sources(), dependencies: result1.dependencies()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 zlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 zlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/221 zlib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/221 zlib/meson.build" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,23 @@ +project('zlib system dependency', 'c') + +if not ['darwin', 'freebsd', 'dragonfly', 'windows', 'android'].contains(host_machine.system()) + error('MESON_SKIP_TEST only applicable on macOS, FreeBSD, DragonflyBSD, Windows, and Android.') +endif + +cc = meson.get_compiler('c') + +if host_machine.system() == 'darwin' and cc.get_id() != 'clang' + # this will only work on mac if using Apple's clang compiler, but there is no + # way in the meson source level to differentiate apple clang and llvm clang + # In the meson CI only apple clang is tested + error('MESON_SKIP_TEST on macOS only clang is supported.') +endif + +if not (cc.find_library('z', required: false).found() or + cc.find_library('zlib', required : false).found() or + cc.find_library('zlib1', required : false).found()) + error('MESON_SKIP_TEST Cannot seem to find zlib via find_library, this test will probably fail.') +endif + +z = dependency('zlib', method : 'system') +assert(z.version().version_compare('>= 1.2'), 'Version does not seem to have been detected correctly.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 native prop/crossfile.ini" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 native prop/crossfile.ini" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 native prop/crossfile.ini" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 native prop/crossfile.ini" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +[properties] +astring = 'cross' +anarray = ['one', 'two'] +red = true diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 native prop/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 native prop/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 native prop/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 native prop/meson.build" 2021-10-23 16:50:30.000000000 +0000 @@ -0,0 +1,49 @@ +project('get prop') + +x = meson.get_external_property('astring') +ref = meson.is_cross_build() ? 'cross' : 'mystring' +assert(x==ref, 'did not get native property string. did you use "meson setup --native-file native.txt"') + +x = meson.get_external_property('astring', native: true) +assert(x=='mystring', 'did not get native property with native:true and non-cross build.') + +x = meson.get_external_property('astring', 'fallback', native: false) +assert(x==ref, 'did not get get native property with native:false and non-cross build.') + + +x = meson.get_external_property('notexist', 'fallback') +assert(x=='fallback', 'fallback did not work') + +x = meson.get_external_property('notexist', 'fallback', native: true) +assert(x=='fallback', 'fallback native:true did not work') + +x = meson.get_external_property('notexist', 'fallback', native: false) +assert(x=='fallback', 'fallback native:false did not work') + + +x = meson.get_external_property('anarray') +assert(x==['one', 'two'], 'array did not work') + +assert(meson.has_external_property('anarray'), 'expected property "anarray" to exist') +assert(meson.has_external_property('astring'), 'expected property "astring" to exist') +assert(not meson.has_external_property('abool'), 'did not expect property "abool" to exist') + +# These exist in both +assert(meson.has_external_property('anarray', native: false), 'FIXME') +assert(meson.has_external_property('anarray', native: true), 'FIXME') +assert(meson.has_external_property('astring', native: false), 'FIXME') +assert(meson.has_external_property('astring', native: true), 'FIXME') + +if meson.is_cross_build() + # This property only exists in the cross file + assert(meson.has_external_property('red'), 'expected property "red" to exist in cross file') + assert(meson.has_external_property('red', native: false), 'expected property "red" to exist in cross file') + assert(not meson.has_external_property('red', native: true), 'did not expect property "red" to exist in native file') + + assert(not meson.has_external_property('abool', native: false), 'FIXME') + assert(not meson.has_external_property('abool', native: false), 'FIXME') +else + assert(not meson.has_external_property('red'), 'did not expect property "red" to exist in native file') + assert(not meson.has_external_property('red', native: false), 'did not expect property "red" to exist in cross file because we are not doing a cross build') + assert(not meson.has_external_property('red', native: true), 'did not expect property "red" to exist in native file') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 native prop/nativefile.ini" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 native prop/nativefile.ini" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 native prop/nativefile.ini" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 native prop/nativefile.ini" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +[properties] +astring = 'mystring' +anarray = ['one', 'two'] \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/aarch64.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/aarch64.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/aarch64.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/aarch64.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "common.h" -#include - -void initialize_target() -{ - std::cout << ANSI_START << "some " << THE_TARGET - << " initialization" << ANSI_END << std::endl; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/arm32.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/arm32.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/arm32.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/arm32.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "common.h" -#include - -void initialize_target() -{ - std::cout << ANSI_START << "a different " << THE_TARGET - << " initialization" << ANSI_END << std::endl; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/arm.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/arm.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/arm.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/arm.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include "arm.h" - -const char *ARMBoard::target() -{ - return THE_TARGET; -} - -void ARMBoard::some_arm_thing() -{ -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/arm.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/arm.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/arm.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/arm.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#ifndef ARM_H -#define ARM_H 1 - -#include "common.h" - -struct ARMBoard: Board { - const char *target(); - void some_arm_thing(); -}; - - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/versatilepb.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/versatilepb.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/versatilepb.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/versatilepb.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include -#include "common.h" -#include "arm.h" - -struct VersatilePBBoard: ARMBoard { - void say_hello(); -}; - -void VersatilePBBoard::say_hello() -{ - some_arm_thing(); - std::cout << ANSI_START << "I am the versatilepb board" - << ANSI_END << std::endl; -} - -static VersatilePBBoard versatilepb; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/virt.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/virt.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/virt.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/virt.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include -#include "common.h" -#include "arm.h" - -struct VirtBoard: ARMBoard { - void say_hello(); -}; - -void VirtBoard::say_hello() -{ - some_arm_thing(); - std::cout << ANSI_START << "I am the virt board" - << ANSI_END << std::endl; -} - -static VirtBoard virt; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/xlnx_zcu102.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/xlnx_zcu102.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/arm/xlnx_zcu102.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/arm/xlnx_zcu102.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include -#include "common.h" -#include "arm.h" - -struct XlnxZCU102Board: ARMBoard { - void say_hello(); -}; - -void XlnxZCU102Board::say_hello() -{ - some_arm_thing(); - std::cout << ANSI_START << "I am the xlnx_zcu102 board" - << ANSI_END << std::endl; -} - -static XlnxZCU102Board xlnx_zcu102; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -specific.add(when: 'TARGET_ARM', if_true: files('arm/arm.cc', 'arm/arm32.cc')) -specific.add(when: 'TARGET_AARCH64', if_true: files('arm/arm.cc', 'arm/aarch64.cc')) -specific.add(when: 'CONFIG_VIRT', if_true: files('arm/virt.cc')) -specific.add(when: 'CONFIG_XLNX_ZCU102', if_true: files('arm/xlnx_zcu102.cc')) -specific.add(when: 'CONFIG_VERSATILEPB', if_true: files('arm/versatilepb.cc')) - -specific.add(when: 'TARGET_X86', if_true: files('x86/pc.cc')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/x86/pc.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/x86/pc.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/boards/x86/pc.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/boards/x86/pc.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -#include -#include "common.h" - -struct X86Board: Board { - const char *target(); - void say_hello(); -}; - -const char *X86Board::target() -{ - return THE_TARGET; -} - -void X86Board::say_hello() -{ - std::cout << ANSI_START << "I am a 1996 PC" - << ANSI_END << std::endl; -} - -void initialize_target() -{ - std::cout << ANSI_START << "ready, set, go" - << ANSI_END << std::endl; -} - -static X86Board pc; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/common.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/common.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/common.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/common.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H 1 - -/* - * target-specific code will print in yellow, common code will print - * in grey. - */ -#ifdef THE_TARGET -#define ANSI_START "\x1b[33;1m" -#define ANSI_END "\x1b[0m" -#else -#define ANSI_START "" -#define ANSI_END "" -#endif - -void some_random_function(); -void initialize_target(); - -struct Board { - Board *next; - Board(); - virtual ~Board(); - virtual void say_hello() = 0; - virtual const char *target() = 0; -}; - -struct Device { - Device *next; - Device(); - virtual ~Device(); - virtual void say_hello() = 0; -}; - -struct Dependency { - Dependency *next; - Dependency(); - virtual ~Dependency(); - virtual void initialize() = 0; -}; - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/config/aarch64" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/config/aarch64" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/config/aarch64" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/config/aarch64" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -TARGET_AARCH64=y -CONFIG_VIRT=y -CONFIG_XLNX_ZCU102=y -CONFIG_VIRTIO=y -CONFIG_VIRTIO_MMIO=y diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/config/arm" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/config/arm" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/config/arm" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/config/arm" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -TARGET_ARM=y -CONFIG_VIRT=y -CONFIG_VERSATILEPB=y diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/config/x86" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/config/x86" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/config/x86" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/config/x86" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -TARGET_X86=y -CONFIG_PC=y -CONFIG_VIRTIO=y -CONFIG_VIRTIO_PCI=y diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -specific.add(when: 'CONFIG_VIRTIO', if_true: files('virtio.cc')) -common.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('virtio-pci.cc')) -common.add(when: 'CONFIG_VIRTIO_MMIO', if_true: files('virtio-mmio.cc')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/virtio.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/virtio.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/virtio.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/virtio.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include -#include "common.h" -#include "virtio.h" - -void VirtioDevice::some_virtio_thing() { -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/virtio.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/virtio.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/virtio.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/virtio.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#ifndef VIRTIO_H -#define VIRTIO_H 1 - -#include "common.h" - -struct VirtioDevice: Device { - void some_virtio_thing(); -}; - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/virtio-mmio.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/virtio-mmio.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/virtio-mmio.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/virtio-mmio.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include -#include "common.h" -#include "virtio.h" - -struct VirtioMMIODevice: VirtioDevice { - void say_hello(); -}; - -void VirtioMMIODevice::say_hello() -{ - some_virtio_thing(); - std::cout << ANSI_START << "virtio-mmio is available" - << ANSI_END << std::endl; -} - -static VirtioMMIODevice virtio_mmio; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/virtio-pci.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/virtio-pci.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/devices/virtio-pci.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/devices/virtio-pci.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include -#include "common.h" -#include "virtio.h" - -struct VirtioPCIDevice: VirtioDevice { - void say_hello(); -}; - -void VirtioPCIDevice::say_hello() -{ - some_virtio_thing(); - std::cout << ANSI_START << "virtio-pci is available" - << ANSI_END << std::endl; -} - -static VirtioPCIDevice virtio_pci; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/main.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/main.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/main.cc" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/main.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -#include -#include -#include "common.h" - -Board* boards; -Device* devices; -Dependency* deps; - -Board::Board() { this->next = boards; boards = this; } -Board::~Board() {} - -Device::Device() { this->next = devices; devices = this; } -Device::~Device() {} - -Dependency::Dependency() { this->next = deps; deps = this; } -Dependency::~Dependency() {} - -int main(void) -{ - some_random_function(); - for (auto d = deps; d; d = d->next) - d->initialize(); - - initialize_target(); - for (auto b = boards; b; b = b->next) { - std::cout << ANSI_START << b->target() << " - " << ANSI_END; - b->say_hello(); - } - - for (auto d = devices; d; d = d->next) - d->say_hello(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/meson.build" 2020-01-23 21:41:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -# a sort-of realistic example that combines the sourceset and kconfig -# modules, inspired by QEMU's build system - -project('sourceset-example', 'cpp', default_options: ['cpp_std=c++11']) - -cppid = meson.get_compiler('cpp').get_id() -if cppid == 'pgi' - error('MESON_SKIP_TEST: Even PGI 19.4 that claims C++17 full support, cannot handle auto x = y syntax used in this test.') -endif - -ss = import('sourceset') -kconfig = import('unstable-kconfig') - -zlib = declare_dependency(compile_args: '-DZLIB=1') -another = declare_dependency(compile_args: '-DANOTHER=1') -not_found = dependency('not-found', required: false) - -common = ss.source_set() -specific = ss.source_set() - -common.add(files('main.cc')) -common.add(when: [zlib, another], if_true: files('zlib.cc')) -common.add(when: not_found, - if_true: files('was-found.cc'), - if_false: files('not-found.cc')) - -subdir('boards') -subdir('devices') - -if meson.is_unity() - specific.add_all(common) - common = ss.source_set() -endif - -common_lib = static_library('common', common.all_sources(), - dependencies: common.all_dependencies()) - -targets = [ 'arm', 'aarch64', 'x86' ] -target_dirs = { 'arm' : 'arm', 'aarch64' : 'arm', 'x86': 'x86' } - -foreach x : targets - config = kconfig.load('config' / x) - target_specific = specific.apply(config, strict: false) - target_common = common.apply(config, strict: false) - target_deps = target_specific.dependencies() + target_common.dependencies() - executable(x, - objects: common_lib.extract_objects(target_common.sources()), - sources: target_specific.sources(), - dependencies: target_deps, - include_directories: 'boards' / target_dirs[x], - cpp_args: '-DTHE_TARGET="' + x + '"') -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/not-found.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/not-found.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/not-found.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/not-found.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include -#include "common.h" - -void some_random_function() -{ - std::cout << ANSI_START << "everything's alright" - << ANSI_END << std::endl; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/was-found.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/was-found.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/was-found.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/was-found.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include - -void some_random_function() -{ - std::cout << ANSI_START << "huh?" - << ANSI_END << std::endl; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/zlib.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/zlib.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/222 source set realistic example/zlib.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/222 source set realistic example/zlib.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#include -#include "common.h" - -struct ZLibDependency : Dependency { - void initialize(); -}; - -void ZLibDependency::initialize() { - if (ZLIB && ANOTHER) { - std::cout << ANSI_START << "hello from zlib" - << ANSI_END << std::endl; - } -} - -ZLibDependency zlib; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 custom target input extracted objects/check_object.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 custom target input extracted objects/check_object.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 custom target input extracted objects/check_object.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 custom target input extracted objects/check_object.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os - -if __name__ == '__main__': - if len(sys.argv) != 3: - print(sys.argv[0], 'object', 'output') - sys.exit(1) - elif os.path.exists(sys.argv[1]): - with open(sys.argv[2], 'wb') as out: - pass - else: - sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 custom target input extracted objects/libdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 custom target input extracted objects/libdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 custom target input extracted objects/libdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 custom target input extracted objects/libdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -objlib = static_library('object', 'source.c', override_options : ['unity=off']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 custom target input extracted objects/libdir/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 custom target input extracted objects/libdir/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 custom target input extracted objects/libdir/source.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 custom target input extracted objects/libdir/source.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func1_in_obj(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 custom target input extracted objects/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 custom target input extracted objects/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 custom target input extracted objects/meson.build" 2020-01-07 21:09:58.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 custom target input extracted objects/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('custom target input extracted objects', 'c') - -checker = find_program('check_object.py') - -cc = meson.get_compiler('c').cmd_array().get(-1) - -subdir('libdir') - -custom_target('check', - input: objlib.extract_objects('source.c'), - output: 'objcheck', - command: [checker, '@INPUT@', '@OUTPUT@'], - build_by_default: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int foo(void); + +int foo(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/meson.build" 2021-10-23 16:50:32.000000000 +0000 @@ -0,0 +1,14 @@ +project('persubproject options', 'c', + default_options : ['werror=true', + 'warning_level=3']) + +assert(get_option('default_library') == 'both', 'Parent default_library should be "both"') +assert(get_option('werror')) +assert(get_option('warning_level') == '3') + +# Check it build both by calling a method only both_libraries target implement +lib = library('lib1', 'foo.c') +lib.get_static_lib() + +subproject('sub1') +subproject('sub2', default_options : ['default_library=static']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/subprojects/sub1/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/subprojects/sub1/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/subprojects/sub1/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/subprojects/sub1/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +int foo(void); + +int foo(void) { + /* This is built with -Werror, it would error if warning_level=3 was inherited + * from main project and not overridden by this subproject's default_options. */ + int x; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/subprojects/sub1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/subprojects/sub1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/subprojects/sub1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/subprojects/sub1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +project('sub1', 'c', + default_options : ['warning_level=0']) + +assert(get_option('default_library') == 'both', 'Should inherit parent project default_library') +assert(get_option('warning_level') == '0') + +# Check it build both by calling a method only both_libraries target implement +lib = library('lib1', 'foo.c') +lib.get_static_lib() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/subprojects/sub2/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/subprojects/sub2/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/subprojects/sub2/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/subprojects/sub2/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +int foo(void); + +#ifdef __GNUC__ +#warning This should not produce error +#endif + +int foo(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/subprojects/sub2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/subprojects/sub2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/subprojects/sub2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/subprojects/sub2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +project('sub2', 'c', + default_options : ['default_library=shared', + 'werror=false']) + +assert(get_option('default_library') == 'static', 'Parent should override default_library') +assert(not get_option('werror')) + +# If it doesn't build only a static library, it would make target name clash. +library('lib1', 'foo.c') +shared_library('lib1', 'foo.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/223 persubproject options/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/223 persubproject options/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "matrix": { + "options": { + "default_library": [ { "val": "both" } ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/224 arithmetic operators/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/224 arithmetic operators/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/224 arithmetic operators/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/224 arithmetic operators/meson.build" 2021-10-23 16:50:31.000000000 +0000 @@ -0,0 +1,8 @@ +project('arithmetic operators') +assert(5 - 3 - 1 == 1) +assert(5 - (3 - 1) == 3) +assert(5 - 1 * 3 - 3 == -1) +assert(420 - 300 - 51 == 69) +assert(1000 / 2 / 2 / 2 == 125) +assert(4 * 9 / 3 % 8 - 3 - 10 / 2 == -4) +assert(94 - 30 + (2 - (40 - 6 + 7) - 9) - 10 == 6) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/224 test priorities/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/224 test priorities/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/224 test priorities/meson.build" 2020-01-07 21:09:58.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/224 test priorities/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -project('test priorities', 'c') - -test_prog = find_program('testprog.py') - -test('priority 0', test_prog, - args : ['0'], -) - -test('priority neg 10', test_prog, - args : ['-10'], - priority : -10 -) - -test('priority 1000', test_prog, - args : ['1000'], - priority : 1000 -) - -test('priority 50', test_prog, - args : ['50'], - priority : 50 -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/224 test priorities/testprog.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/224 test priorities/testprog.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/224 test priorities/testprog.py" 2019-09-16 21:20:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/224 test priorities/testprog.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -print(sys.argv[1]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/meson.build" 2020-01-07 21:09:58.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('Include Here', 'c') - -# The layout with the .h file in . and the .c files in src/ is critical to -# tickle the bug #5847 - -inc = include_directories('.') - -subdir('src') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/rone.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/rone.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/rone.h" 2019-09-16 21:20:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/rone.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int rOne(void); \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/src/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/src/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/src/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/src/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "rone.h" - -int main(void) { - return rOne(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/src/meson.build" 2019-09-16 21:20:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -t = executable( - 'main', - ['main.c', 'rone.c'], - include_directories : inc, - implicit_include_directories : false, -) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/src/rone.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/src/rone.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 include_dir dot/src/rone.c" 2019-09-16 21:20:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 include_dir dot/src/rone.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int rOne(void) { - return 1; -} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/c_linkage.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/c_linkage.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/c_linkage.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/c_linkage.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +extern "C" { + int makeInt(void) { + return 0; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/c_linkage.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/c_linkage.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/c_linkage.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/c_linkage.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ + +#ifdef __cplusplus +extern "C" { +#endif + +int makeInt(void); + +#ifdef __cplusplus +} +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/lib.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/lib.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/lib.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/lib.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +extern "C" { + int makeInt(void) { + return 1; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "c_linkage.h" + +int main(void) { + return makeInt(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/225 link language/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/225 link language/meson.build" 2021-10-23 16:50:33.000000000 +0000 @@ -0,0 +1,18 @@ +project( + 'link_language', + ['c', 'cpp'], +) + +exe = executable( + 'main', + ['main.c', 'c_linkage.cpp'], + link_language : 'c', +) + +lib = library( + 'mylib', + ['lib.cpp'], + link_language : 'c', +) + +test('main', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 include_type dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 include_type dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 include_type dependency/meson.build" 2020-01-07 21:10:03.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 include_type dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -project( - 'dependency include_type', - ['c', 'cpp'], -) - -dep = dependency('zlib', method: 'pkg-config', required : false) -if not dep.found() - error('MESON_SKIP_TEST zlib was not found') -endif - -assert(dep.include_type() == 'preserve', 'include_type must default to "preserve"') - -dep_sys = dep.as_system() -assert(dep_sys.include_type() == 'system', 'as_system must return a system dep') - -dep2 = dependency('zlib', method: 'pkg-config', include_type : 'system') -assert(dep2.include_type() == 'system', 'include_type must be true when set') - -dep2_sys = dep2.as_system('non-system') -assert(dep2_sys.include_type() == 'non-system', 'as_system must set include_type correctly') - -sp = subproject('subDep') -sp_dep = sp.get_variable('subDep_dep') -assert(sp_dep.include_type() == 'preserve', 'default is preserve') - -sp_dep_sys = sp_dep.as_system('system') -assert(sp_dep_sys.include_type() == 'system', 'changing include_type works') -assert(sp_dep.include_type() == 'preserve', 'as_system must not mutate the original object') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 include_type dependency/subprojects/subDep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 include_type dependency/subprojects/subDep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 include_type dependency/subprojects/subDep/meson.build" 2019-10-06 17:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 include_type dependency/subprojects/subDep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('subDep', ['cpp']) - -subDep_dep = declare_dependency(compile_args : []) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 link depends indexed custom target/check_arch.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 link depends indexed custom target/check_arch.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 link depends indexed custom target/check_arch.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 link depends indexed custom target/check_arch.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import re +import sys +import shutil +import subprocess + +exepath = sys.argv[1] +want_arch = sys.argv[2] +dummy_output = sys.argv[3] + +with open(dummy_output, 'w') as f: + f.write('') + +if not shutil.which('dumpbin'): + print('dumpbin not found, skipping') + sys.exit(0) + +out = subprocess.check_output(['dumpbin', '/HEADERS', exepath], + universal_newlines=True) +for line in out.split('\n'): + m = re.match(r'.* machine \(([A-Za-z0-9]+)\)$', line) + if m: + arch = m.groups()[0].lower() + +if arch == 'arm64': + arch = 'aarch64' +elif arch == 'x64': + arch = 'x86_64' + +if arch != want_arch: + raise RuntimeError(f'Wanted arch {want_arch} but exe uses {arch}') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 link depends indexed custom target/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 link depends indexed custom target/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 link depends indexed custom target/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 link depends indexed custom target/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#include + +int main(void) { + const char *fn = DEPFILE; + FILE *f = fopen(fn, "r"); + if (!f) { + printf("could not open %s", fn); + return 1; + } + else { + printf("successfully opened %s", fn); + } + + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 link depends indexed custom target/make_file.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 link depends indexed custom target/make_file.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 link depends indexed custom target/make_file.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 link depends indexed custom target/make_file.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 +import sys + +with open(sys.argv[1], 'w') as f: + print('# this file does nothing', file=f) + +with open(sys.argv[2], 'w') as f: + print('# this file does nothing', file=f) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 link depends indexed custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 link depends indexed custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/226 link depends indexed custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/226 link depends indexed custom target/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,20 @@ +project('link_depends_indexed_custom_target', 'c') + +cmd = find_program('make_file.py') + +dep_files = custom_target('gen_dep', + command: [cmd, '@OUTPUT@'], + output: ['dep_file1', 'dep_file2']) + +exe = executable('foo', 'foo.c', + link_depends: dep_files[1], + c_args: ['-DDEPFILE="' + dep_files[0].full_path()+ '"']) + +check_arch = find_program('check_arch.py') +custom_target('check-arch', + command: [check_arch, exe, host_machine.cpu_family(), '@OUTPUT@'], + build_by_default: true, + output: 'dummy.txt') + +# check that dep_file1 exists, which means that link_depends target ran +test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/a_symlink" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/a_symlink" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/a_symlink" 2020-01-07 21:10:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/a_symlink" 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -project('fs module test') - -is_windows = build_machine.system() == 'windows' - -fs = import('fs') - -assert(fs.exists('meson.build'), 'Existing file reported as missing.') -assert(not fs.exists('nonexisting'), 'Nonexisting file was found.') - -# When one creates a source release with sdist, Python -# does not store symlinks in the archive as native symlinks. -# Thus the extracted archive does not contain them either. -# Sadly this means that we can only execute the symlink test when -# running from a git checkout because otherwise we'd need to -# do postprocessing on the generated archive before actual release. -# That is both nonstandard an error prone and having symlinks in -# the archive would probably break on Windows anyway. -is_git_checkout = fs.exists('../../../.git') - -if not is_windows and build_machine.system() != 'cygwin' and is_git_checkout - assert(fs.is_symlink('a_symlink'), 'Symlink not detected.') - assert(not fs.is_symlink('meson.build'), 'Regular file detected as symlink.') -endif - -assert(fs.is_file('meson.build'), 'File not detected as a file.') -assert(not fs.is_file('subprojects'), 'Directory detected as a file.') -assert(not fs.is_file('nonexisting'), 'Bad path detected as a file.') - -assert(fs.is_dir('subprojects'), 'Dir not detected correctly.') -assert(not fs.is_dir('meson.build'), 'File detected as a dir.') -assert(not fs.is_dir('nonexisting'), 'Bad path detected as a dir.') - -assert(fs.is_dir('~'), 'expanduser not working') -assert(not fs.is_file('~'), 'expanduser not working') - -original = 'foo.txt' -new = fs.replace_suffix(original, '.ini') -assert(new == 'foo.ini', 'replace_suffix failed') - -original = 'foo' -new = fs.replace_suffix(original, '.ini') -assert(new == 'foo.ini', 'replace_suffix did not add suffix to suffixless file') - -original = 'foo.dll.a' -new = fs.replace_suffix(original, '.so') -assert(new == 'foo.dll.so', 'replace_suffix did not only modify last suffix') - -original = 'foo.dll' -new = fs.replace_suffix(original, '') -assert(new == 'foo', 'replace_suffix did not only delete last suffix') - -# `/` on windows is interpreted like `.drive` which in general may not be `c:/` -# the files need not exist for fs.replace_suffix() -original = is_windows ? 'j:/foo/bar.txt' : '/foo/bar.txt' -new_check = is_windows ? 'j:\\foo\\bar.ini' : '/foo/bar.ini' - -new = fs.replace_suffix(original, '.ini') -assert(new == new_check, 'absolute path replace_suffix failed') - -# -- hash - -md5 = fs.hash('subdir/subdirfile.txt', 'md5') -sha256 = fs.hash('subdir/subdirfile.txt', 'sha256') -assert(md5 == 'd0795db41614d25affdd548314b30b3b', 'md5sum did not match') -assert(sha256 == 'be2170b0dae535b73f6775694fffa3fd726a43b5fabea11b7342f0605917a42a', 'sha256sum did not match') - -# -- size - -size = fs.size('subdir/subdirfile.txt') -assert(size == 19, 'file size not found correctly') - -# -- are filenames referring to the same file? -f1 = 'meson.build' -f2 = 'subdir/../meson.build' -assert(fs.is_samepath(f1, f2), 'is_samepath not detercting same files') -assert(fs.is_samepath(meson.source_root(), 'subdir/..'), 'is_samepath not detecting same directory') -assert(not fs.is_samepath(f1, 'subdir/subdirfile.txt'), 'is_samepath known bad comparison') -assert(not fs.is_samepath('not-a-path', f2), 'is_samepath should not error if path(s) do not exist') - -if not is_windows and build_machine.system() != 'cygwin' and is_git_checkout - assert(fs.is_samepath('a_symlink', 'meson.build'), 'symlink is_samepath fail') -endif - -assert(fs.parent('foo/bar') == 'foo', 'failed to get dirname') -assert(fs.name('foo/bar') == 'bar', 'failed to get basename') - -subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/meson.build" 2020-01-07 21:10:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -project('fs module test') - -is_windows = build_machine.system() == 'windows' - -fs = import('fs') - -assert(fs.exists('meson.build'), 'Existing file reported as missing.') -assert(not fs.exists('nonexisting'), 'Nonexisting file was found.') - -# When one creates a source release with sdist, Python -# does not store symlinks in the archive as native symlinks. -# Thus the extracted archive does not contain them either. -# Sadly this means that we can only execute the symlink test when -# running from a git checkout because otherwise we'd need to -# do postprocessing on the generated archive before actual release. -# That is both nonstandard an error prone and having symlinks in -# the archive would probably break on Windows anyway. -is_git_checkout = fs.exists('../../../.git') - -if not is_windows and build_machine.system() != 'cygwin' and is_git_checkout - assert(fs.is_symlink('a_symlink'), 'Symlink not detected.') - assert(not fs.is_symlink('meson.build'), 'Regular file detected as symlink.') -endif - -assert(fs.is_file('meson.build'), 'File not detected as a file.') -assert(not fs.is_file('subprojects'), 'Directory detected as a file.') -assert(not fs.is_file('nonexisting'), 'Bad path detected as a file.') - -assert(fs.is_dir('subprojects'), 'Dir not detected correctly.') -assert(not fs.is_dir('meson.build'), 'File detected as a dir.') -assert(not fs.is_dir('nonexisting'), 'Bad path detected as a dir.') - -assert(fs.is_dir('~'), 'expanduser not working') -assert(not fs.is_file('~'), 'expanduser not working') - -original = 'foo.txt' -new = fs.replace_suffix(original, '.ini') -assert(new == 'foo.ini', 'replace_suffix failed') - -original = 'foo' -new = fs.replace_suffix(original, '.ini') -assert(new == 'foo.ini', 'replace_suffix did not add suffix to suffixless file') - -original = 'foo.dll.a' -new = fs.replace_suffix(original, '.so') -assert(new == 'foo.dll.so', 'replace_suffix did not only modify last suffix') - -original = 'foo.dll' -new = fs.replace_suffix(original, '') -assert(new == 'foo', 'replace_suffix did not only delete last suffix') - -# `/` on windows is interpreted like `.drive` which in general may not be `c:/` -# the files need not exist for fs.replace_suffix() -original = is_windows ? 'j:/foo/bar.txt' : '/foo/bar.txt' -new_check = is_windows ? 'j:\\foo\\bar.ini' : '/foo/bar.ini' - -new = fs.replace_suffix(original, '.ini') -assert(new == new_check, 'absolute path replace_suffix failed') - -# -- hash - -md5 = fs.hash('subdir/subdirfile.txt', 'md5') -sha256 = fs.hash('subdir/subdirfile.txt', 'sha256') -assert(md5 == 'd0795db41614d25affdd548314b30b3b', 'md5sum did not match') -assert(sha256 == 'be2170b0dae535b73f6775694fffa3fd726a43b5fabea11b7342f0605917a42a', 'sha256sum did not match') - -# -- size - -size = fs.size('subdir/subdirfile.txt') -assert(size == 19, 'file size not found correctly') - -# -- are filenames referring to the same file? -f1 = 'meson.build' -f2 = 'subdir/../meson.build' -assert(fs.is_samepath(f1, f2), 'is_samepath not detercting same files') -assert(fs.is_samepath(meson.source_root(), 'subdir/..'), 'is_samepath not detecting same directory') -assert(not fs.is_samepath(f1, 'subdir/subdirfile.txt'), 'is_samepath known bad comparison') -assert(not fs.is_samepath('not-a-path', f2), 'is_samepath should not error if path(s) do not exist') - -if not is_windows and build_machine.system() != 'cygwin' and is_git_checkout - assert(fs.is_samepath('a_symlink', 'meson.build'), 'symlink is_samepath fail') -endif - -assert(fs.parent('foo/bar') == 'foo', 'failed to get dirname') -assert(fs.name('foo/bar') == 'bar', 'failed to get basename') - -subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subdir/meson.build" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -assert(fs.exists('subdirfile.txt'), 'Subdir file lookup is broken.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subdir/subdirfile.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subdir/subdirfile.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subdir/subdirfile.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subdir/subdirfile.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -I have no content. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subprojects/subbie/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subprojects/subbie/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subprojects/subbie/meson.build" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subprojects/subbie/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('subbie') - -fs = import('fs') - -assert(fs.exists('subprojectfile.txt'), 'Subproject root file not found.') - -subdir('subsub') - -subproject('subbie') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subprojects/subbie/subprojectfile.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subprojects/subbie/subprojectfile.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subprojects/subbie/subprojectfile.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subprojects/subbie/subprojectfile.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -I'm not empty. So there's at least that. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subprojects/subbie/subsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subprojects/subbie/subsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subprojects/subbie/subsub/meson.build" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subprojects/subbie/subsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -assert(fs.exists('subsubfile.txt'), 'Subproject subdir lookup failed.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subprojects/subbie/subsub/subsubfile.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subprojects/subbie/subsub/subsubfile.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 fs module/subprojects/subbie/subsub/subsubfile.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 fs module/subprojects/subbie/subsub/subsubfile.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Thank you for looking inside me. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 very long commmand line/codegen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 very long commmand line/codegen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 very long commmand line/codegen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 very long commmand line/codegen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys +from pathlib import Path + +Path(sys.argv[2]).write_text( + 'int func{n}(void) {{ return {n}; }}'.format(n=sys.argv[1])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 very long commmand line/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 very long commmand line/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 very long commmand line/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 very long commmand line/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 very long commmand line/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 very long commmand line/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 very long commmand line/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 very long commmand line/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,49 @@ +project('very long command lines', 'c') + +# Get the current system's commandline length limit. +if build_machine.system() == 'windows' + # Various limits on windows: + # cmd.exe: 8kb + # CreateProcess: 32kb + limit = 32767 + # NOTE: filename limit is 260 characters unless + # 1. Python >= 3.6 is being used + # 2. Windows 10 registry has been edited to enable long pathnaems + # ninja backend uses absolute filenames, so we ensure they don't exceed 260. +elif build_machine.system() == 'cygwin' + # cygwin-to-win32: see above + # cygwin-to-cygwin: no limit? + # Cygwin is slow, so only test it lightly here. + limit = 8192 +else + # ninja passes whole line as a single argument, for which + # the limit is 128k as of Linux 2.6.23. See MAX_ARG_STRLEN. + # BSD seems similar, see https://www.in-ulm.de/~mascheck/various/argmax + limit = 131072 +endif +# Now exceed that limit, but not so far that the test takes too long. +namelen = 260 +nfiles = 50 + limit / namelen +message('Expected link commandline length is approximately ' + '@0@'.format((nfiles * (namelen+28)))) + +seq = run_command('name_gen.py', nfiles.to_string(), meson.build_root(), check: true).stdout().strip().split('\n') + +sources = [] +codegen = find_program('codegen.py') + +i=0 +foreach name : seq + sources += custom_target('codegen' + i.to_string(), + command: [codegen, i.to_string(), '@OUTPUT@'], + output: name + '.c') + i+=1 +endforeach + +shared_library('sharedlib', sources) +static_library('staticlib', sources) +executable('app', 'main.c', sources) + +# Also test short commandlines to make sure that doesn't regress +shared_library('sharedlib0', sources[0]) +static_library('staticlib0', sources[0]) +executable('app0', 'main.c', sources[0]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 very long commmand line/name_gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 very long commmand line/name_gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/227 very long commmand line/name_gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/227 very long commmand line/name_gen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +""" +generate sequence of filename that does not exceed MAX_LEN=260 +for Python < 3.6 and Windows without modified registry +""" + +import sys +import string + +name_len = 260 - len(sys.argv[2]) - 4 - 39 - 4 - 2 +if name_len < 1: + raise ValueError('The meson build directory pathname is so long ' + 'that we cannot generate filenames within 260 characters.') +# leave room for suffix and file separators, and meson generated text +# e.g. ".c.obj.d" and other decorators added by Meson at configuration +# for intermediate files + +base = string.ascii_letters * 5 # 260 characters +max_num_len = len(str(sys.argv[1])) +base = base[: name_len - max_num_len] + +for i in range(int(sys.argv[1])): + print("{base}{i:0{max_num_len}d}".format(base=base, max_num_len=max_num_len, i=i)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/228 custom_target source/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/228 custom_target source/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/228 custom_target source/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/228 custom_target source/meson.build" 2021-10-23 16:50:34.000000000 +0000 @@ -0,0 +1,5 @@ +project('a', ['c']) + +x = find_program('x.py') +outs = custom_target('foo', output: ['x.c', 'y'], input: 'a', command: [x]) +executable('testprog', outs[0]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/228 custom_target source/x.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/228 custom_target source/x.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/228 custom_target source/x.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/228 custom_target source/x.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#! /usr/bin/env python3 +with open('x.c', 'w') as f: + print('int main(void) { return 0; }', file=f) +with open('y', 'w'): + pass diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/229 disabler array addition/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/229 disabler array addition/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/229 disabler array addition/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/229 disabler array addition/meson.build" 2021-10-23 16:50:35.000000000 +0000 @@ -0,0 +1,9 @@ +project('disabler_inside_array', 'c') + +exes = [] + +exes += library('a', 'test.c') + +exes += library('b', 'test.c', dependencies : disabler()) + +exes += library('c', 'test.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/229 disabler array addition/test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/229 disabler array addition/test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/229 disabler array addition/test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/229 disabler array addition/test.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int stub(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/check-obj.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/check-obj.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/check-obj.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/check-obj.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,21 @@ +#! /usr/bin/env python3 + +import json +import sys +import os + +cc = None +output = None + +# Only the ninja backend produces compile_commands.json +if sys.argv[1] == 'ninja': + with open('compile_commands.json') as f: + cc = json.load(f) + output = {x['output'] for x in cc} + +for obj in sys.argv[2:]: + if not os.path.exists(obj): + sys.exit(f'File {obj} not found.') + if sys.argv[1] == 'ninja' and obj not in output: + sys.exit(1) + print('Verified', obj) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/create-source.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/create-source.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/create-source.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/create-source.py" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,3 @@ +#! /usr/bin/env python3 +import sys +print(f'#include "{sys.argv[1]}"') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/header.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/header.h" 2021-07-20 08:56:20.000000000 +0000 @@ -0,0 +1 @@ +/* Check that extract_all_objects works with headers. */ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/lib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/lib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/lib2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/lib2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int retval(void) { + return 43; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int func(void); + +int main(void) { + return func() == 42 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,50 @@ +project('object extraction', 'c') + +if meson.is_unity() + message('Skipping extraction test because this is a Unity build.') +else + lib1 = library('somelib', 'src/lib.c') + lib2 = library('somelib2', 'lib.c', 'header.h', 'lib2.c') + + obj1 = lib1.extract_objects('src/lib.c') + obj2 = lib2.extract_objects(['lib.c']) + obj3 = lib2.extract_objects(files('lib.c')) + obj4 = lib2.extract_objects(['lib.c', 'lib.c']) + obj5 = lib2.extract_objects(['lib.c', 'header.h']) + obj6 = lib2.extract_all_objects(recursive: true) + + e1 = executable('main1', 'main.c', objects : obj1) + e2 = executable('main2', 'main.c', objects : obj2) + e3 = executable('main3', 'main.c', objects : obj3) + e4 = executable('main4', 'main.c', objects : obj4) + e5 = executable('main5', 'main.c', objects : obj5) + e6 = executable('main6', 'main.c', objects : obj6) + + ct_src = custom_target('lib3.c', output: 'lib3.c', capture: true, + command: [find_program('create-source.py'), 'lib.c']) + lib3 = library('somelib3', ct_src) + e7 = executable('main7', 'main.c', objects: lib3.extract_objects(ct_src[0])) + e8 = executable('main8', 'main.c', objects: lib3.extract_objects(ct_src)) + + gen = generator(find_program('create-source.py'), arguments: ['@INPUT@'], + output: '@BASENAME@4.c', capture: true) + gen_src = gen.process('lib.c') + lib4 = library('somelib4', gen_src) + e9 = executable('main9', 'main.c', objects: lib4.extract_objects(gen_src)) + + custom_target('custom_target with object inputs', output: 'objs', + input: [obj1, obj2, obj3, obj5, obj6], + build_by_default: true, + command: [find_program('check-obj.py'), meson.backend(), '@INPUT@'], + capture: true) + + test('extraction test 1', e1) + test('extraction test 2', e2) + test('extraction test 3', e3) + test('extraction test 4', e4) + test('extraction test 5', e5) + test('extraction test 6', e6) + test('extraction test 7', e7) + test('extraction test 8', e8) + test('extraction test 9', e9) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/src/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/src/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 object extraction/src/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 object extraction/src/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/func2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/func2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/func2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/func2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#ifdef CTHING -#error "Local C argument set in wrong target" -#endif - -#ifdef CPPTHING -#error "Local CPP argument set in wrong target" -#endif - -int func(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/func.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/func.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/func.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/func.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#ifndef CTHING -#error "Local argument not set" -#endif - -#ifdef CPPTHING -#error "Wrong local argument set" -#endif - -int func(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/meson.build" 2020-01-07 21:06:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('local arg test', 'cpp', 'c') - -exe1 = executable('prog', 'prog.cc', 'func.c', \ -c_args : '-DCTHING', \ -cpp_args : '-DCPPTHING') -exe2 = executable('prog2', 'prog2.cc', 'func2.c') - -test('prog1', exe1) -test('prog2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/prog2.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/prog2.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/prog2.cc" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/prog2.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#ifdef CTHING -#error "Local C argument set in wrong target" -#endif - -#ifdef CPPTHING -#error "Local CPP argument set in wrong target" -#endif - -extern "C" int func(); - -int main(void) { - return func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/22 target arg/prog.cc" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/22 target arg/prog.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#ifdef CTHING -#error "Wrong local argument set" -#endif - -#ifndef CPPTHING -#error "Local argument not set" -#endif - -extern "C" int func(); - -int main(void) { - return func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/app.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/app.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/app.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/app.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) +{ + return call_foo() == 42 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/func.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/func.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/func.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/func.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +#include "func.h" + +int func(void) +{ + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/func.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/func.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/func.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/func.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int func(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/libfoo/configure" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/libfoo/configure" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/libfoo/configure" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/libfoo/configure" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,44 @@ +#! /bin/sh + +srcdir=$(dirname "$0") + +for i in "$@" +do +case $i in + --prefix=*) + PREFIX="${i#*=}" + shift + ;; + --libdir=*) + LIBDIR="${i#*=}" + shift + ;; + --includedir=*) + INCDIR="${i#*=}" + shift + ;; + --libext=*) + LIBEXT="${i#*=}" + shift + ;; + *) + shift + ;; +esac +done + +DEP_ARGS=$(pkg-config --cflags --libs somelib) + +cat > Makefile << EOL +all: libfoo.$LIBEXT + +libfoo.$LIBEXT: + $CC "$srcdir/libfoo.c" -shared -fPIC $DEP_ARGS -o \$@ + +install: libfoo.$LIBEXT + mkdir -p "\$(DESTDIR)$LIBDIR"; + mkdir -p "\$(DESTDIR)$LIBDIR/pkgconfig"; + mkdir -p "\$(DESTDIR)$INCDIR"; + cp \$< "\$(DESTDIR)$LIBDIR"; + cp "$srcdir/libfoo.h" "\$(DESTDIR)$INCDIR"; +EOL diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/libfoo/libfoo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/libfoo/libfoo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/libfoo/libfoo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/libfoo/libfoo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "libfoo.h" + +int func(void); + +int call_foo() +{ + return func() == 1 ? 42 : 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/libfoo/libfoo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/libfoo/libfoo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/libfoo/libfoo.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/libfoo/libfoo.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +int call_foo(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/libfoo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/libfoo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/libfoo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/libfoo/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,22 @@ +mod = import('unstable_external_project') + +target_system = target_machine.system() +if target_system in ['windows', 'cygwin'] + libext = 'dll' +elif target_system == 'darwin' + libext = 'dylib' +else + libext = 'so' +endif + +p = mod.add_project('configure', + configure_options : [ + '--prefix=@PREFIX@', + '--libdir=@PREFIX@/@LIBDIR@', + '--includedir=@PREFIX@/@INCLUDEDIR@', + '--libext=' + libext, + ], +) + +libfoo_dep = declare_dependency(link_with : somelib, + dependencies : p.dependency('foo')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/meson.build" 2021-10-23 16:50:37.000000000 +0000 @@ -0,0 +1,27 @@ +project('test external project', 'c') + +if not find_program('pkg-config', required: false).found() + error('MESON_SKIP_TEST: pkg-config not found') +endif + +if not find_program('make', required : false).found() + error('MESON_SKIP_TEST: make not found') +endif + +if host_machine.system() == 'windows' + error('MESON_SKIP_TEST: The fake configure script is too dumb to work on Windows') +endif + +if meson.is_cross_build() + # CI uses PKG_CONFIG_SYSROOT_DIR which breaks -uninstalled.pc usage. + error('MESON_SKIP_TEST: Cross build support is too limited for this test') +endif + +pkg = import('pkgconfig') + +somelib = library('somelib', 'func.c') +pkg.generate(somelib) + +subdir('libfoo') + +executable('test-find-library', 'app.c', dependencies : libfoo_dep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/230 external project/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/230 external project/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + { "type": "shared_lib", "file": "usr/lib/foo" }, + { "type": "file", "file": "usr/include/libfoo.h" }, + { "type": "file", "file": "usr/lib/pkgconfig/somelib.pc" } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/231 subdir files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/231 subdir files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/231 subdir files/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/231 subdir files/meson.build" 2021-10-23 16:50:35.000000000 +0000 @@ -0,0 +1,3 @@ +project('subdir files test', 'c') +subdir('subdir') +executable('prog', sources: subdir_sources) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/231 subdir files/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/231 subdir files/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/231 subdir files/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/231 subdir files/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +subdir_sources = files(['prog.c']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/231 subdir files/subdir/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/231 subdir files/subdir/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/231 subdir files/subdir/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/231 subdir files/subdir/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/232 dependency allow_fallback/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/232 dependency allow_fallback/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/232 dependency allow_fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/232 dependency allow_fallback/meson.build" 2021-10-23 16:50:39.000000000 +0000 @@ -0,0 +1,12 @@ +project('subproject fallback', 'c') + +foob_dep = dependency('foob', allow_fallback: true, required: false) +assert(foob_dep.found()) + +# Careful! Once a submodule has been triggered and it has +# overridden the dependency, it sticks. +foob_dep = dependency('foob', allow_fallback: false, required: false) +assert(foob_dep.found()) + +foob3_dep = dependency('foob3', allow_fallback: false, required: false) +assert(not foob3_dep.found()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/232 dependency allow_fallback/subprojects/foob/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/232 dependency allow_fallback/subprojects/foob/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/232 dependency allow_fallback/subprojects/foob/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/232 dependency allow_fallback/subprojects/foob/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +project('foob', 'c') +meson.override_dependency('foob', declare_dependency()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/232 dependency allow_fallback/subprojects/foob3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/232 dependency allow_fallback/subprojects/foob3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/232 dependency allow_fallback/subprojects/foob3/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/232 dependency allow_fallback/subprojects/foob3/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +project('foob3', 'c') +# Note that there is no override_dependency here diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/meson.build" 2021-10-23 16:50:42.000000000 +0000 @@ -0,0 +1,6 @@ +project('CaSe DePenDenCy In Wrap', 'c') + +d = dependency('UP_down') + +e = executable('prog', 'prog.c', dependencies: d) +test('prog', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include +#include + +int main(int argc, char **argv) { + if(argc == 42) { + printf("Very sneaky, %s\n", argv[0]); + } +#ifdef UP_IS_DOWN + return 0; +#else + return 1; +#endif +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/subprojects/up_down/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/subprojects/up_down/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/subprojects/up_down/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/subprojects/up_down/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('up down', 'c') + +up_down_dep = declare_dependency(include_directories: '.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/subprojects/up_down/up_down.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/subprojects/up_down/up_down.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/subprojects/up_down/up_down.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/subprojects/up_down/up_down.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +#define UP_IS_DOWN diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/subprojects/up_down.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/subprojects/up_down.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/233 wrap case/subprojects/up_down.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/233 wrap case/subprojects/up_down.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +[wrap-file] +directory = up_down + +[provide] +UP_down = up_down_dep diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/.gitattributes" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/.gitattributes" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/.gitattributes" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/.gitattributes" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +utf-16-text binary diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/meson.build" 2021-10-23 16:50:39.000000000 +0000 @@ -0,0 +1,21 @@ +project( + 'meson-fs-read-file', + [], + version: files('VERSION') +) +fs = import('fs') + +assert(fs.read('VERSION').strip() == meson.project_version(), 'file misread') + +expected = ( + '∮ Eâ‹…da = Q, n → ∞, ∑ f(i) = ∠g(i), ∀x∈â„: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β)' +) +assert( + fs.read('utf-16-text', encoding: 'utf-16').strip() == expected, + 'file was not decoded correctly' +) + +# Make sure we handle `files()` objects properly, too +version_file = files('VERSION') + +subdir('other') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/other/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/other/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/other/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/other/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +fs = import('fs') +assert(fs.read(version_file).strip() == '1.2.0') +assert(fs.read('../VERSION').strip() == '1.2.0') Binary files /tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/utf-16-text and /tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/utf-16-text differ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/VERSION" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/VERSION" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/234 get_file_contents/VERSION" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/234 get_file_contents/VERSION" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +1.2.0 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/235 invalid standard overriden to valid/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/235 invalid standard overriden to valid/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/235 invalid standard overriden to valid/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/235 invalid standard overriden to valid/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/235 invalid standard overriden to valid/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/235 invalid standard overriden to valid/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/235 invalid standard overriden to valid/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/235 invalid standard overriden to valid/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,8 @@ +project( + 'invalid C standard overridden to valid one', + 'c', + default_options : ['c_std=invalid99'], +) + +exe = executable('main', 'main.c') +test('main', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/235 invalid standard overriden to valid/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/235 invalid standard overriden to valid/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/235 invalid standard overriden to valid/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/235 invalid standard overriden to valid/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "matrix": { + "options": { + "c_std": [ + { "val": "c89" } + ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/236 proper args splitting/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/236 proper args splitting/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/236 proper args splitting/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/236 proper args splitting/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#ifndef FOO +# error "FOO is not defined" +#endif + +#ifndef BAR +# error "BAR is not defined" +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/236 proper args splitting/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/236 proper args splitting/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/236 proper args splitting/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/236 proper args splitting/meson.build" 2021-10-23 16:50:42.000000000 +0000 @@ -0,0 +1,9 @@ +project('proper args splitting', 'c') + +test( + 'main', + executable( + 'main', + 'main.c', + ) +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/236 proper args splitting/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/236 proper args splitting/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/236 proper args splitting/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/236 proper args splitting/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "matrix": { + "options": { + "c_args": [ + { "val": "-DFOO -DBAR" } + ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/237 fstrings/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/237 fstrings/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/237 fstrings/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/237 fstrings/meson.build" 2021-10-23 16:50:42.000000000 +0000 @@ -0,0 +1,7 @@ +project('meson-test', 'c') + +n = 10 +m = 'bar' +s = f'test @n@ string (@@n@@): @m@' + +assert(s == 'test 10 string (@10@): bar', 'Incorrect string formatting') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/bar/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/bar/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/bar/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/bar/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +baz_dep = dependency('baz', + fallback: ['baz', 'baz_dep'], + include_type: 'system', + method: 'pkg-config', # if we comment this out or change to 'auto' the build is successful + required: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/meson.build" 2021-10-23 16:50:46.000000000 +0000 @@ -0,0 +1,5 @@ +project('test', 'c', 'cpp') + +foo_dep = subproject('foo').get_variable('foo_dep') + +subdir('bar') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/subprojects/baz/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/subprojects/baz/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/subprojects/baz/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/subprojects/baz/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('baz', 'cpp') + +baz_dep = declare_dependency() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/subprojects/baz.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/subprojects/baz.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/subprojects/baz.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/subprojects/baz.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +[wrap-file] +source_url = http://host.invalid/baz.tar.gz +source_filename = baz.tar.gz diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/subprojects/foo/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +project('foo', 'c', 'cpp') + +baz_dep = dependency('baz', + fallback: ['baz', 'baz_dep'], + include_type: 'system', + method: 'pkg-config', + required: false) + +foo_dep = declare_dependency(dependencies: baz_dep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/subprojects/foo.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/subprojects/foo.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/238 dependency include_type inconsistency/subprojects/foo.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/238 dependency include_type inconsistency/subprojects/foo.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +[wrap-file] +source_url = http://host.invalid/foo.tar.gz +source_filename = foo.tar.gz diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/239 includedir violation/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/239 includedir violation/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/239 includedir violation/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/239 includedir violation/meson.build" 2021-10-23 16:50:46.000000000 +0000 @@ -0,0 +1,11 @@ +project('foo', 'c') + +# It is fine to include the root source dir +include_directories('.') +subproject('sub') + +# This is here rather than in failing because this needs a +# transition period to avoid breaking existing projects. +# Once this becomes an error, move this under failing tests. + +inc = include_directories('subprojects/sub/include') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +// Git can not handle empty directories, so there must be something here. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/239 includedir violation/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/239 includedir violation/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/239 includedir violation/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/239 includedir violation/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('subproj', 'c') + +include_directories('.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/239 includedir violation/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/239 includedir violation/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/239 includedir violation/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/239 includedir violation/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "stdout": [ + { + "line": ".*WARNING: include_directories sandbox violation!", + "match": "re", + "count": 1 + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 endian/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 endian/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 endian/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 endian/meson.build" 2021-10-23 16:47:59.000000000 +0000 @@ -0,0 +1,7 @@ +project('endian check', 'c') + +if host_machine.endian() == 'big' + add_global_arguments('-DIS_BE', language : 'c') +endif + +test('endiantest', executable('prog', 'prog.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 endian/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 endian/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 endian/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 endian/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,24 @@ +#include + +int is_big_endian(void) { + uint32_t one = 1; + if(*((uint8_t*) &one) == 1) + return 0; + return 1; +} + + +int main(void) { + int is_be_check = is_big_endian(); + int is_be; +#ifdef IS_BE + is_be = 1; +#else + is_be = 0; +#endif + if(is_be_check && is_be) + return 0; + if(!is_be_check && !is_be) + return 0; + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/lib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/lib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/lib2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/lib2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int retval(void) { - return 43; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int func(void); - -int main(void) { - return func() == 42 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/meson.build" 2020-01-07 21:06:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -project('object extraction', 'c') - -if meson.is_unity() - message('Skipping extraction test because this is a Unity build.') -else - lib1 = shared_library('somelib', 'src/lib.c') - lib2 = shared_library('somelib2', 'lib.c', 'lib2.c') - - obj1 = lib1.extract_objects('src/lib.c') - obj2 = lib2.extract_objects(['lib.c']) - obj3 = lib2.extract_objects(files('lib.c')) - - e1 = executable('main1', 'main.c', objects : obj1) - e2 = executable('main2', 'main.c', objects : obj2) - e3 = executable('main3', 'main.c', objects : obj3) - - test('extraction test 1', e1) - test('extraction test 2', e2) - test('extraction test 3', e3) -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/src/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/src/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/23 object extraction/src/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/23 object extraction/src/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/240 dependency native host == build/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/240 dependency native host == build/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/240 dependency native host == build/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/240 dependency native host == build/meson.build" 2021-10-23 16:50:47.000000000 +0000 @@ -0,0 +1,18 @@ +project('foo', 'c') + +if meson.is_cross_build() + error('MESON_SKIP_TEST Test does not make sense for cross builds') +endif + +dep_zlib = dependency('zlib', required : false) +if not dep_zlib.found() + error('MESON_SKIP_TEST Test requires zlib') +endif +dependency('zlib', native : true, required : false) +dependency('zlib', native : false) + +# `native: true` should not make a difference when doing a native build. +meson.override_dependency('expat', declare_dependency()) +dependency('expat') +dependency('expat', native : true) +dependency('expat', native : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/240 dependency native host == build/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/240 dependency native host == build/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/240 dependency native host == build/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/240 dependency native host == build/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,14 @@ +{ + "stdout": [ + { + "line": "Dependency zlib found: YES .* \\(cached\\)", + "match": "re", + "count": 2 + }, + { + "line": "Dependency expat found: YES .* \\(overridden\\)", + "match": "re", + "count": 3 + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/241 set and get variable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/241 set and get variable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/241 set and get variable/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/241 set and get variable/meson.build" 2021-10-23 16:50:47.000000000 +0000 @@ -0,0 +1,71 @@ +project('set and get') + +var1 = 'test1.txt' +var2 = files('test1.txt')[0] + +# Use is_disabler for accessing variables +assert(var1 == 'test1.txt') +assert(not is_disabler(var2)) + +# Ensure that set variables behave correctly +set_variable('var3', 'test2.txt') +set_variable('var4', files('test2.txt')[0]) + +assert(var3 == 'test2.txt') +assert(not is_disabler(var4)) + +# Test Equality +assert(var1 == get_variable('var1')) +assert(var2 == get_variable('var2')) + +# Test get_variable directly +assert(get_variable('var1') == 'test1.txt') +assert(not is_disabler(get_variable('var2'))) +assert(get_variable('var3') == 'test2.txt') +assert(not is_disabler(get_variable('var4'))) + +# Test get_variable indirectly + +var5 = get_variable('var1') +var6 = get_variable('var2') +var7 = get_variable('var3') +var8 = get_variable('var4') +set_variable('var9', get_variable('var7')) +set_variable('var0', get_variable('var8')) + +assert(var5 == 'test1.txt') +assert(not is_disabler(var6)) +assert(var7 == 'test2.txt') +assert(not is_disabler(var8)) +assert(get_variable('var9') == 'test2.txt') +assert(not is_disabler(get_variable('var0'))) +assert(not is_disabler(get_variable('var0', var8))) +assert(not is_disabler(get_variable('----', var8))) +assert(not is_disabler(get_variable('----', [var8]))) +assert(not is_disabler(get_variable('----', {'asd': var8}))) + +# test dict get +dict = {'a': var2} + +dict_t1 = dict['a'] +dict_t2 = dict.get('a') +dict_t3 = dict.get('a', var2) +dict_t4 = dict.get('b', var2) + +assert(not is_disabler(dict_t1)) +assert(not is_disabler(dict_t2)) +assert(not is_disabler(dict_t3)) +assert(not is_disabler(dict_t4)) + +# test lists +list = [var2] + +list_t1 = list[0] +list_t2 = list.get(0) +list_t3 = list.get(0, var2) +list_t4 = list.get(1, var2) + +assert(not is_disabler(list_t1)) +assert(not is_disabler(list_t2)) +assert(not is_disabler(list_t3)) +assert(not is_disabler(list_t4)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/242 custom target feed/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/242 custom target feed/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/242 custom target feed/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/242 custom target feed/data_source.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/242 custom target feed/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/242 custom target feed/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/242 custom target feed/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/242 custom target feed/meson.build" 2021-10-23 16:50:50.000000000 +0000 @@ -0,0 +1,24 @@ +project('custom target feed', 'c') + +python3 = import('python3').find_python() + +# Note that this will not add a dependency to the compiler executable. +# Code will not be rebuilt if it changes. +comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') + +mytarget = custom_target('bindat', + output : 'data.dat', + input : 'data_source.txt', + feed : true, + command : [python3, comp, '@OUTPUT@'], + install : true, + install_dir : 'subdir' +) + +ct_output_exists = '''import os, sys +if not os.path.exists(sys.argv[1]): + print("could not find {!r} in {!r}".format(sys.argv[1], os.getcwd())) + sys.exit(1) +''' + +test('capture-wrote', python3, args : ['-c', ct_output_exists, mytarget]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/242 custom target feed/my_compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/242 custom target feed/my_compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/242 custom target feed/my_compiler.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/242 custom target feed/my_compiler.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +import sys + +if __name__ == '__main__': + if len(sys.argv) != 2: + print(sys.argv[0], 'output_file') + sys.exit(1) + ifile = sys.stdin.read() + if ifile != 'This is a text only input file.\n': + print('Malformed input') + sys.exit(1) + with open(sys.argv[1], 'w+') as f: + f.write('This is a binary output file.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/242 custom target feed/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/242 custom target feed/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/242 custom target feed/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/242 custom target feed/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/subdir/data.dat"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/243 escape++/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/243 escape++/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/243 escape++/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/243 escape++/meson.build" 2021-10-23 16:50:49.000000000 +0000 @@ -0,0 +1,4 @@ +project('regex escape test', 'c') + +exe = executable('testprog', 'test.c') +test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/243 escape++/test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/243 escape++/test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/243 escape++/test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/243 escape++/test.c" 2021-08-18 11:22:25.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/244 variable scope/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/244 variable scope/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/244 variable scope/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/244 variable scope/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,15 @@ +project('variable scope') + +x = 1 + +assert(is_variable('x')) + +assert(get_variable('x') == 1) + +set_variable('x', 10) + +assert(get_variable('x') == 10) + +unset_variable('x') + +assert(not is_variable('x')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/code_source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/code_source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/code_source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/code_source.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +extern int genfunc(void); + +int genfunc(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/copyfile2.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/copyfile2.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/copyfile2.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/copyfile2.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copyfile(sys.argv[1], sys.argv[2]) +shutil.copyfile(sys.argv[3], sys.argv[4]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/copyfile.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/header_source.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/header_source.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/header_source.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/header_source.h" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +extern int genfunc(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/main.c" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include "gen.h" + +int main(int argc) +{ + assert(argc == 3); + return genfunc(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/245 custom target index source/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/245 custom target index source/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,51 @@ +project('custom target index source', 'c') + +# Test that using a custom target index as a sourcefile works correctly + +copy1 = find_program('copyfile.py') +copy2 = find_program('copyfile2.py') + +step_1 = custom_target('step_1', + input: ['code_source.c', files('header_source.h')], + output: ['step_1.c', 'step_1.h'], + command: [copy2, '@INPUT0@', '@OUTPUT0@', '@INPUT1@', '@OUTPUT1@'], + build_by_default: false) + +# test custom target with a single CustomTargetIndex input +step_2_c = custom_target('step_2_c', + input: step_1[0], + output: 'step_2.c', + command: [copy1, '@INPUT0@', '@OUTPUT0@'], + build_by_default: false) + +step_2_h = custom_target('step_2_h', + input: step_1[1], + output: 'step_2.h', + command: [copy1, '@INPUT0@', '@OUTPUT0@'], + build_by_default: false, +) + +# test custom target with multiple CustomTargetIndex inputs +gen = custom_target('step_3', + input: [step_2_c, step_2_h], + output: ['gen.c', 'gen.h'], + command: [copy2, '@INPUT0@', '@OUTPUT0@', '@INPUT1@', '@OUTPUT1@'], + build_by_default: false) +gen_c = gen[0] +gen_h = gen[1] + +exe_separate = executable('exe_separate', + ['main.c', gen_c, gen_h], + build_by_default: false, + install: false, +) + +exe_together = executable('exe_together', + ['main.c', gen], + build_by_default: false, + install: false, +) + +# also cover passing custom target to tests as arguments +test('exe_separate', exe_separate, args: [gen_c, gen_h]) +test('exe_together', exe_together, args: gen) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/246 dependency fallbacks/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/246 dependency fallbacks/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/246 dependency fallbacks/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/246 dependency fallbacks/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,10 @@ +project('dependency fallbacks', 'c') + +# pkg-config has 'libpng' but cmake has 'png' and we have a 'png' subproject +# for platforms that have neither. +d = dependency('libpng', 'png', 'foo') +assert(d.found()) + +# Check that dependency 'foo' has been implicitly overridden. +d = dependency('foo') +assert(d.found()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/246 dependency fallbacks/subprojects/png/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/246 dependency fallbacks/subprojects/png/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/246 dependency fallbacks/subprojects/png/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/246 dependency fallbacks/subprojects/png/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +project('png') + +meson.override_dependency('libpng', declare_dependency()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/247 deprecated option/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/247 deprecated option/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/247 deprecated option/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/247 deprecated option/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,15 @@ +project('deprecated options', + default_options: [ + 'o1=false', + 'o2=a,b', + 'o3=a,b', + 'o4=true', + 'o5=auto', + ] +) + +assert(get_option('o1') == false) +assert(get_option('o2') == ['a', 'b']) +assert(get_option('o3') == ['c', 'b']) +assert(get_option('o4').enabled()) +assert(get_option('o5') == false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/247 deprecated option/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/247 deprecated option/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/247 deprecated option/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/247 deprecated option/meson_options.txt" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,15 @@ +# Option fully deprecated, it warns when any value is set. +option('o1', type: 'boolean', deprecated: true) + +# One of the choices is deprecated, it warns only when 'a' is in the list of values. +option('o2', type: 'array', choices: ['a', 'b'], deprecated: ['a']) + +# One of the choices is deprecated, it warns only when 'a' is in the list of values +# and replace it by 'c'. +option('o3', type: 'array', choices: ['a', 'b', 'c'], deprecated: {'a': 'c'}) + +# A boolean option has been replaced by a feature, old true/false values are remapped. +option('o4', type: 'feature', deprecated: {'true': 'enabled', 'false': 'disabled'}) + +# A feature option has been replaced by a boolean, enabled/disabled/auto values are remapped. +option('o5', type: 'boolean', deprecated: {'enabled': 'true', 'disabled': 'false', 'auto': 'false'}) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/247 deprecated option/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/247 deprecated option/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/247 deprecated option/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/247 deprecated option/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,29 @@ +{ + "stdout": [ + { + "line": ".*DEPRECATION: Option 'o1' is deprecated", + "match": "re", + "count": 1 + }, + { + "line": ".*DEPRECATION: Option 'o2' value 'a' is deprecated", + "match": "re", + "count": 1 + }, + { + "line": ".*DEPRECATION: Option 'o3' value 'a' is replaced by 'c'", + "match": "re", + "count": 1 + }, + { + "line": ".*DEPRECATION: Option 'o4' value 'true' is replaced by 'enabled'", + "match": "re", + "count": 1 + }, + { + "line": ".*DEPRECATION: Option 'o5' value 'auto' is replaced by 'false'", + "match": "re", + "count": 1 + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/248 install_emptydir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/248 install_emptydir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/248 install_emptydir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/248 install_emptydir/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,4 @@ +project('install_emptydir') + +install_emptydir(get_option('datadir')/'new_directory', install_mode: 'rwx------') +install_emptydir(get_option('datadir')/'new_directory/subdir', install_mode: 'rwxr-----') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/248 install_emptydir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/248 install_emptydir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/248 install_emptydir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/248 install_emptydir/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + { "type": "dir", "file": "usr/share/new_directory" }, + { "type": "dir", "file": "usr/share/new_directory/subdir" } + ] +} + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/249 install_symlink/datafile.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/249 install_symlink/datafile.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/249 install_symlink/datafile.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/249 install_symlink/datafile.dat" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1 @@ +this is a data file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/249 install_symlink/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/249 install_symlink/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/249 install_symlink/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/249 install_symlink/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,9 @@ +project('install_emptydir') + +if build_machine.system() == 'windows' and meson.backend() == 'ninja' + error('MESON_SKIP_TEST windows does not support symlinks unless root or in development mode') +endif + +install_data('datafile.dat', install_dir: 'share/progname/C') +install_symlink('datafile.dat', pointing_to: '../C/datafile.dat', install_dir: 'share/progname/es') +install_symlink('rename_datafile.dat', pointing_to: '../C/datafile.dat', install_dir: 'share/progname/fr') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/249 install_symlink/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/249 install_symlink/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/249 install_symlink/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/249 install_symlink/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "file", "file": "usr/share/progname/C/datafile.dat"}, + {"type": "file", "file": "usr/share/progname/es/datafile.dat"}, + {"type": "file", "file": "usr/share/progname/fr/rename_datafile.dat"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 endian/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 endian/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 endian/meson.build" 2020-01-07 21:06:32.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 endian/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('endian check', 'c') - -if host_machine.endian() == 'big' - add_global_arguments('-DIS_BE', language : 'c') -endif - -test('endiantest', executable('prog', 'prog.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 endian/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 endian/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 endian/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 endian/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#include - -int is_big_endian(void) { - uint32_t one = 1; - if(*((uint8_t*) &one) == 1) - return 0; - return 1; -} - - -int main(void) { - int is_be_check = is_big_endian(); - int is_be; -#ifdef IS_BE - is_be = 1; -#else - is_be = 0; -#endif - if(is_be_check && is_be) - return 0; - if(!is_be_check && !is_be) - return 0; - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 library versions/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 library versions/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 library versions/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 library versions/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC myFunc(void) { + return 55; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 library versions/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 library versions/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 library versions/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 library versions/meson.build" 2021-10-23 16:48:00.000000000 +0000 @@ -0,0 +1,9 @@ +project('library versions', 'c') + +shared_library('somelib', 'lib.c', + name_prefix : 'prefix', + name_suffix : 'suffix', + install_dir : 'lib', + install : true) + +subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 library versions/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 library versions/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 library versions/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 library versions/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +# Test that using files generated with configure_file as sources works. +# We do this inside a subdir so that the path isn't accidentally correct +# because there is no structure in the build dir. +genlib = configure_file(input : '../lib.c', + output : 'genlib.c', + copy: true) +shared_library('genlib', genlib, + install : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 library versions/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 library versions/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/24 library versions/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/24 library versions/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/prefixsomelib.suffix"}, + {"type": "implib", "file": "usr/lib/prefixsomelib"}, + {"type": "pdb", "file": "usr/lib/prefixsomelib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/250 system include dir/lib/lib.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/250 system include dir/lib/lib.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/250 system include dir/lib/lib.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/250 system include dir/lib/lib.hpp" 2022-01-17 10:50:38.000000000 +0000 @@ -0,0 +1,4 @@ +#pragma once + +// This will trigger -Wsign-conversion +inline unsigned convert_to_unsigned(int i) { return i; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/250 system include dir/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/250 system include dir/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/250 system include dir/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/250 system include dir/main.cpp" 2022-01-17 10:50:38.000000000 +0000 @@ -0,0 +1,3 @@ +#include + +int main() { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/250 system include dir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/250 system include dir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/250 system include dir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/250 system include dir/meson.build" 2022-01-17 10:50:38.000000000 +0000 @@ -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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/include/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/include/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/include/config.h.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/include/config.h.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#define RETURN_VALUE @number@ + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/include/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/include/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/include/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/include/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +conf_data = configuration_data() +conf_data.set('number', '0') + +configure_file(input:'config.h.in', output:'config.h', configuration:conf_data) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/meson.build" 2021-10-23 16:48:00.000000000 +0000 @@ -0,0 +1,6 @@ +project('subdirconfig', 'c') + +inc = include_directories('include') + +subdir('include') +subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +exe = executable('prog', 'prog.c', include_directories : inc) +test('subdir config', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/src/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/src/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 config subdir/src/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 config subdir/src/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "config.h" + +int main(void) { + return RETURN_VALUE; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 library versions/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 library versions/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 library versions/installed_files.txt" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 library versions/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/lib/prefixsomelib.suffix -usr/lib/prefixsomelib?implib -?msvc:usr/lib/prefixsomelib.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 library versions/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 library versions/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 library versions/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 library versions/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC myFunc(void) { - return 55; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 library versions/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 library versions/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 library versions/meson.build" 2020-01-07 21:06:34.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 library versions/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('library versions', 'c') - -shared_library('somelib', 'lib.c', - name_prefix : 'prefix', - name_suffix : 'suffix', - install_dir : 'lib', - install : true) - -subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 library versions/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 library versions/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/25 library versions/subdir/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/25 library versions/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -# Test that using files generated with configure_file as sources works. -# We do this inside a subdir so that the path isn't accidentally correct -# because there is no structure in the build dir. -genlib = configure_file(input : '../lib.c', - output : 'genlib.c', - copy: true) -shared_library('genlib', genlib, - install : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/include/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/include/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/include/config.h.in" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/include/config.h.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef CONFIG_H_ -#define CONFIG_H_ - -#define RETURN_VALUE @number@ - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/include/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/include/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/include/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/include/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -conf_data = configuration_data() -conf_data.set('number', '0') - -configure_file(input:'config.h.in', output:'config.h', configuration:conf_data) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/meson.build" 2020-01-07 21:06:34.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -project('subdirconfig', 'c') - -inc = include_directories('include') - -subdir('include') -subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/src/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -exe = executable('prog', 'prog.c', include_directories : inc) -test('subdir config', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/src/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/src/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 config subdir/src/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 config subdir/src/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "config.h" - -int main(void) { - return RETURN_VALUE; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/meson.build" 2021-10-23 16:48:03.000000000 +0000 @@ -0,0 +1,35 @@ +project('find program', 'c') + +if build_machine.system() == 'windows' + # Things Windows does not provide: + # - an executable to copy files without prompting + # - working command line quoting + # - anything that you might actually need + # Because of these reasons we only check that + # the program can be found. + cp = find_program('xcopy') +else + cp = find_program('donotfindme', 'cp') + gen = generator(cp, \ + output : '@BASENAME@.c', \ + arguments : ['@INPUT@', '@OUTPUT@']) + + generated = gen.process('source.in') + e = executable('prog', generated) + test('external exe', e) +endif + +prog = find_program('print-version.py', version : '>=2.0', required : false) +assert(not prog.found(), 'Version should be too old') + +prog = find_program('print-version.py', version : '>=1.0') +assert(prog.found(), 'Program version should match') + +prog = find_program('print-version-with-prefix.py', version : '>=1.0') +assert(prog.found(), 'Program version should match') + +prog = find_program('test_subdir.py', required : false) +assert(not prog.found(), 'Program should not be found') + +prog = find_program('test_subdir.py', dirs : ['/donotexist', meson.current_source_dir() / 'scripts']) +assert(prog.found(), 'Program should be found') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/print-version.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/print-version.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/print-version.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/print-version.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys + +if len(sys.argv) != 2 or sys.argv[1] != '--version': + exit(1) + +print('1.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/print-version-with-prefix.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/print-version-with-prefix.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/print-version-with-prefix.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/print-version-with-prefix.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys + +if len(sys.argv) != 2 or sys.argv[1] != '--version': + exit(1) + +print('Version: 1.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/scripts/test_subdir.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/scripts/test_subdir.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/scripts/test_subdir.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/scripts/test_subdir.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +exit(0) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/source.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/source.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/26 find program/source.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/26 find program/source.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 multiline string/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 multiline string/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 multiline string/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 multiline string/meson.build" 2021-10-23 16:48:03.000000000 +0000 @@ -0,0 +1,37 @@ +project('multiline string', 'c') + +x = '''hello again''' +y = '''hello +again''' + +if x == y + error('Things are wrong.') +endif + +multieol = ''' +''' +singleeol = '\n' + +if multieol != singleeol + error('Newline quoting is broken.') +endif + +# And one more for good measure. +quote1 = ''' ' '''.strip() +quote2 = '\'' + +if quote1 != quote2 + error('Single quote quoting is broken.') +endif + +cc = meson.get_compiler('c') +prog = ''' +#include + +int main(void) { + int num = 1; + printf("%d\n", num); + return 0; +}''' + +assert(cc.compiles(prog), 'multline test compile failed') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/copyrunner.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/copyrunner.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/copyrunner.py" 2019-05-22 21:53:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/copyrunner.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -import sys, subprocess - -prog, infile, outfile = sys.argv[1:] - -subprocess.check_call([prog, infile, outfile]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/filecopier.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/filecopier.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/filecopier.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/filecopier.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -#include -#include - -#define BUFSIZE 1024 - -int main(int argc, char **argv) { - char buffer[BUFSIZE]; - size_t num_read; - size_t num_written; - FILE *fin = fopen(argv[1], "rb"); - FILE *fout; - assert(argc>0); - assert(fin); - num_read = fread(buffer, 1, BUFSIZE, fin); - assert(num_read > 0); - fclose(fin); - fout = fopen(argv[2], "wb"); - assert(fout); - num_written = fwrite(buffer, 1, num_read, fout); - assert(num_written == num_read); - fclose(fout); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/libsrc.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/libsrc.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/libsrc.c.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/libsrc.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/meson.build" 2019-05-22 21:53:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -runner = find_program('copyrunner.py') - -copier = executable('copier', 'filecopier.c', native: true) - -cg = generator(runner, - output: ['@BASENAME@.c'], - arguments: [copier.full_path(), '@INPUT@', '@OUTPUT@'], - depends: copier) - -test('generatordep', - executable('gd', 'prog.c', cg.process('libsrc.c.in'))) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/depends/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/depends/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int func(void); - -int main(void) { - return func() != 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/input_src.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/input_src.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/input_src.dat" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/input_src.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int func(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/meson.build" 2020-01-07 21:06:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -project('pipeline test', 'c') - -# We need to run this executable locally so build it with -# the host compiler. -e1 = executable('srcgen', 'srcgen.c', native : true) - -# Generate a source file that needs to be included in the build. -gen = generator(e1, \ - depfile : '@BASENAME@.d', - output : '@BASENAME@.c', # Line continuation inside arguments should work without needing a "\". - arguments : ['@INPUT@', '@OUTPUT@', '@DEPFILE@']) - -generated = gen.process(['input_src.dat']) - -e2 = executable('prog', 'prog.c', generated) - -test('pipelined', e2) - -# This is in a subdirectory to make sure -# we write proper subdir paths to output. -subdir('src') - -subdir('depends') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int func(void); - -int main(void) { - return func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/src/input_src.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/src/input_src.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/src/input_src.dat" 2019-05-22 21:53:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/src/input_src.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/src/meson.build" 2019-05-22 21:53:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -e1 = executable('srcgen', 'srcgen.c', native : true) - -# Generate a header file that needs to be included. -gen = generator(e1, - output : '@BASENAME@.h', - arguments : ['@INPUT@', '@OUTPUT@']) - -generated = gen.process('input_src.dat') - -e2 = executable('prog', 'prog.c', generated) - -test('pipelined', e2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/src/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/src/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/src/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/src/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#include"input_src.h" - -int main(void) { - void *foo = printf; - if(foo) { - return 0; - } - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/src/srcgen.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/src/srcgen.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/src/srcgen.c" 2019-05-22 21:53:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/src/srcgen.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#include -#include - -#define ARRSIZE 80 - -int main(int argc, char **argv) { - char arr[ARRSIZE]; - char *ifilename; - char *ofilename; - FILE *ifile; - FILE *ofile; - size_t bytes; - - if(argc != 3) { - fprintf(stderr, "%s \n", argv[0]); - return 1; - } - ifilename = argv[1]; - ofilename = argv[2]; - printf("%s\n", ifilename); - ifile = fopen(ifilename, "r"); - if(!ifile) { - fprintf(stderr, "Could not open source file %s.\n", ifilename); - return 1; - } - ofile = fopen(ofilename, "w"); - if(!ofile) { - fprintf(stderr, "Could not open target file %s\n", ofilename); - fclose(ifile); - return 1; - } - bytes = fread(arr, 1, ARRSIZE, ifile); - assert(bytes < 80); - assert(bytes > 0); - fwrite(arr, 1, bytes, ofile); - - fclose(ifile); - fclose(ofile); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/srcgen.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/srcgen.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/27 pipeline/srcgen.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/27 pipeline/srcgen.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -#include -#include -#include - -#define ARRSIZE 80 - -int main(int argc, char **argv) { - char arr[ARRSIZE]; - char *ofilename; - char *ifilename; - char *dfilename; - FILE *ifile; - FILE *ofile; - FILE *depfile; - size_t bytes; - int i; - - if(argc != 4) { - fprintf(stderr, "%s \n", argv[0]); - return 1; - } - ifilename = argv[1]; - ofilename = argv[2]; - dfilename = argv[3]; - ifile = fopen(argv[1], "r"); - if(!ifile) { - fprintf(stderr, "Could not open source file %s.\n", argv[1]); - return 1; - } - ofile = fopen(ofilename, "w"); - if(!ofile) { - fprintf(stderr, "Could not open target file %s\n", ofilename); - fclose(ifile); - return 1; - } - bytes = fread(arr, 1, ARRSIZE, ifile); - assert(bytes < 80); - assert(bytes > 0); - fwrite(arr, 1, bytes, ofile); - - depfile = fopen(dfilename, "w"); - if(!depfile) { - fprintf(stderr, "Could not open depfile %s\n", ofilename); - fclose(ifile); - fclose(ofile); - return 1; - } - for(i=0; i=2.0', required : false) -assert(not prog.found(), 'Version should be too old') - -prog = find_program('print-version.py', version : '>=1.0') -assert(prog.found(), 'Program version should match') - -prog = find_program('print-version-with-prefix.py', version : '>=1.0') -assert(prog.found(), 'Program version should match') - -prog = find_program('test_subdir.py', required : false) -assert(not prog.found(), 'Program should not be found') - -prog = find_program('test_subdir.py', dirs : ['/donotexist', meson.current_source_dir() / 'scripts']) -assert(prog.found(), 'Program should be found') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 find program/print-version.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 find program/print-version.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 find program/print-version.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 find program/print-version.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -if len(sys.argv) != 2 or sys.argv[1] != '--version': - exit(1) - -print('1.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 find program/print-version-with-prefix.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 find program/print-version-with-prefix.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 find program/print-version-with-prefix.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 find program/print-version-with-prefix.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -if len(sys.argv) != 2 or sys.argv[1] != '--version': - exit(1) - -print('Version: 1.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 find program/scripts/test_subdir.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 find program/scripts/test_subdir.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 find program/scripts/test_subdir.py" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 find program/scripts/test_subdir.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/usr/bin/env python3 - -exit(0) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 find program/source.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 find program/source.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 find program/source.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 find program/source.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 try compile/invalid.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 try compile/invalid.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 try compile/invalid.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 try compile/invalid.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +#include +void func(void) { printf("This won't work.\n"); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 try compile/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 try compile/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 try compile/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 try compile/meson.build" 2021-10-23 16:48:05.000000000 +0000 @@ -0,0 +1,27 @@ +project('try compile', 'c', 'cpp') + +code = '''#include +void func(void) { printf("Something.\n"); } +''' + +breakcode = '''#include +void func(void) { printf("This won't work.\n"); } +''' + +foreach compiler : [meson.get_compiler('c'), meson.get_compiler('cpp')] + if compiler.compiles(code, name : 'should succeed') == false + error('Compiler ' + compiler.get_id() + ' is fail.') + endif + + if compiler.compiles(files('valid.c'), name : 'should succeed') == false + error('Compiler ' + compiler.get_id() + ' is fail.') + endif + + if compiler.compiles(breakcode, name : 'should fail') + error('Compiler ' + compiler.get_id() + ' returned true on broken code.') + endif + + if compiler.compiles(files('invalid.c'), name : 'should fail') + error('Compiler ' + compiler.get_id() + ' returned true on broken code.') + endif +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 try compile/valid.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 try compile/valid.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/28 try compile/valid.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/28 try compile/valid.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +#include +void func(void) { printf("Something.\n"); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/29 compiler id/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/29 compiler id/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/29 compiler id/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/29 compiler id/meson.build" 2021-10-23 16:48:07.000000000 +0000 @@ -0,0 +1,15 @@ +project('compiler_id') + +foreach lang : ['c', 'cpp', 'fortran', 'objc', 'objcpp'] + + if not add_languages(lang, required: false) + continue + endif + + comp = meson.get_compiler(lang) + + message(lang + ' compiler name is: ' + comp.get_id()) + + message(lang + ' linker name is: ' + comp.get_linker_id()) + +endforeach \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/29 multiline string/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/29 multiline string/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/29 multiline string/meson.build" 2020-01-07 21:06:37.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/29 multiline string/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -project('multiline string', 'c') - -x = '''hello again''' -y = '''hello -again''' - -if x == y - error('Things are wrong.') -endif - -multieol = ''' -''' -singleeol = '\n' - -if multieol != singleeol - error('Newline quoting is broken.') -endif - -# And one more for good measure. -quote1 = ''' ' '''.strip() -quote2 = '\'' - -if quote1 != quote2 - error('Single quote quoting is broken.') -endif - -cc = meson.get_compiler('c') -prog = ''' -int main(void) { - int num = 1; - printf("%d\n", num); - return 0; -}''' - -assert(cc.compiles(prog), 'multline test compile failed') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/2 cpp/cpp.C" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/2 cpp/cpp.C" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/2 cpp/cpp.C" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/2 cpp/cpp.C" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + std::cout << "C++ seems to be working." << std::endl; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/2 cpp/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/2 cpp/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/2 cpp/meson.build" 2020-01-07 21:06:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/2 cpp/meson.build" 2021-10-23 16:47:45.000000000 +0000 @@ -1,4 +1,4 @@ -project('c++ test', 'cpp') +project('c++ test', 'cpp', version: files('VERSIONFILE')) cpp = meson.get_compiler('cpp') if cpp.get_id() == 'intel' @@ -32,3 +32,10 @@ endif assert(exe_disabled, 'Executable was not disabled.') + +if cpp.get_id() == 'msvc' + exe = executable('cppprog', 'cpp.C', cpp_args : '/TP') +else + exe = executable('cppprog', 'cpp.C') +endif +test('cpptest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/2 cpp/VERSIONFILE" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/2 cpp/VERSIONFILE" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/2 cpp/VERSIONFILE" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/2 cpp/VERSIONFILE" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +1.0.0 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 sizeof/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 sizeof/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 sizeof/config.h.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 sizeof/config.h.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +#define INTSIZE @INTSIZE@ +#define WCHARSIZE @WCHARSIZE@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 sizeof/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 sizeof/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 sizeof/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 sizeof/meson.build" 2021-10-23 16:48:07.000000000 +0000 @@ -0,0 +1,33 @@ +project('sizeof', 'c', 'cpp') + +# Test with C +cc = meson.get_compiler('c') + +intsize = cc.sizeof('int') +wcharsize = cc.sizeof('wchar_t', prefix : '#include') + +cd = configuration_data() +cd.set('INTSIZE', intsize) +cd.set('WCHARSIZE', wcharsize) +cd.set('CONFIG', 'config.h') +configure_file(input : 'config.h.in', output : 'config.h', configuration : cd) +s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd) + +e = executable('prog', s) +test('sizeof test', e) + +# Test with C++ +cpp = meson.get_compiler('cpp') + +intsize = cpp.sizeof('int') +wcharsize = cpp.sizeof('wchar_t', prefix : '#include') + +cdpp = configuration_data() +cdpp.set('INTSIZE', intsize) +cdpp.set('WCHARSIZE', wcharsize) +cdpp.set('CONFIG', 'config.hpp') +configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp) +spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp) + +epp = executable('progpp', spp) +test('sizeof test c++', epp) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 sizeof/prog.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 sizeof/prog.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 sizeof/prog.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 sizeof/prog.c.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#include "@CONFIG@" +#include +#include + +int main(void) { + if(INTSIZE != sizeof(int)) { + fprintf(stderr, "Mismatch: detected int size %d, actual size %d.\n", INTSIZE, (int)sizeof(int)); + return 1; + } + if(WCHARSIZE != sizeof(wchar_t)) { + fprintf(stderr, "Mismatch: detected wchar size %d, actual size %d.\n", WCHARSIZE, (int)sizeof(wchar_t)); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 try compile/invalid.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 try compile/invalid.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 try compile/invalid.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 try compile/invalid.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -#include -void func(void) { printf("This won't work.\n"); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 try compile/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 try compile/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 try compile/meson.build" 2020-01-07 21:06:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 try compile/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -project('try compile', 'c', 'cpp') - -code = '''#include -void func(void) { printf("Something.\n"); } -''' - -breakcode = '''#include -void func(void) { printf("This won't work.\n"); } -''' - -foreach compiler : [meson.get_compiler('c'), meson.get_compiler('cpp')] - if compiler.compiles(code, name : 'should succeed') == false - error('Compiler ' + compiler.get_id() + ' is fail.') - endif - - if compiler.compiles(files('valid.c'), name : 'should succeed') == false - error('Compiler ' + compiler.get_id() + ' is fail.') - endif - - if compiler.compiles(breakcode, name : 'should fail') - error('Compiler ' + compiler.get_id() + ' returned true on broken code.') - endif - - if compiler.compiles(files('invalid.c'), name : 'should fail') - error('Compiler ' + compiler.get_id() + ' returned true on broken code.') - endif -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 try compile/valid.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 try compile/valid.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/30 try compile/valid.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/30 try compile/valid.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -#include -void func(void) { printf("Something.\n"); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/31 compiler id/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/31 compiler id/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/31 compiler id/meson.build" 2020-01-07 21:06:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/31 compiler id/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -project('compiler_id') - -foreach lang : ['c', 'cpp', 'fortran', 'objc', 'objcpp'] - - if not add_languages(lang, required: false) - continue - endif - - comp = meson.get_compiler(lang) - - message(lang + ' compiler name is: ' + comp.get_id()) - - message(lang + ' linker name is: ' + comp.get_linker_id()) - -endforeach \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/31 define10/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/31 define10/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/31 define10/config.h.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/31 define10/config.h.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +#mesondefine ONE +#mesondefine ZERO diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/31 define10/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/31 define10/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/31 define10/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/31 define10/meson.build" 2021-10-23 16:48:05.000000000 +0000 @@ -0,0 +1,12 @@ +project('set10test', 'c') + +conf = configuration_data() +conf.set10('ONE', true) +conf.set10('ZERO', false) + +configure_file(input : 'config.h.in', + output : 'config.h', + configuration : conf) + +exe = executable('prog', 'prog.c') +test('10test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/31 define10/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/31 define10/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/31 define10/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/31 define10/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include +#include"config.h" + +int main(void) { + if(ONE != 1) { + fprintf(stderr, "ONE is not 1.\n"); + return 1; + } + if(ZERO != 0) { + fprintf(stderr, "ZERO is not 0.\n"); + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 has header/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 has header/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 has header/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 has header/meson.build" 2021-10-23 16:48:07.000000000 +0000 @@ -0,0 +1,54 @@ +project('has header', 'c', 'cpp') + +host_system = host_machine.system() + +non_existent_header = 'ouagadougou.h' + +# Copy it into the builddir to ensure that it isn't found even if it's there +configure_file(input : non_existent_header, + output : non_existent_header, + configuration : configuration_data()) + +# Test that the fallback to __has_include also works on all compilers +if host_system != 'darwin' + fallbacks = ['', '\n#undef __has_include'] +else + # On Darwin's clang you can't redefine builtin macros so the above doesn't work + fallbacks = [''] +endif + +foreach fallback : fallbacks + foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')] + assert(comp.has_header('stdio.h', prefix : fallback), 'Stdio missing.') + + # stdio.h doesn't actually need stdlib.h, but just test that setting the + # prefix does not result in an error. + assert(comp.has_header('stdio.h', prefix : '#include ' + fallback), + 'Stdio missing.') + + # XInput.h should not require type definitions from windows.h, but it does + # require macro definitions. Specifically, it requires an arch setting for + # VS2015 at least. + # We only do this check on MSVC because MinGW often defines its own wrappers + # that pre-include windows.h + if comp.get_id() == 'msvc' + assert(comp.has_header('XInput.h', prefix : '#include ' + fallback), + 'XInput.h should not be missing on Windows') + assert(comp.has_header('XInput.h', prefix : '#define _X86_' + fallback), + 'XInput.h should not need windows.h') + endif + + # Test that the following GCC bug doesn't happen: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005 + # https://github.com/mesonbuild/meson/issues/1458 + if host_system == 'linux' + assert(comp.has_header('linux/if.h', prefix : fallback), + 'Could not find ') + endif + + # This header exists in the source and the builddir, but we still must not + # find it since we are looking in the system directories. + assert(not comp.has_header(non_existent_header, prefix : fallback), + 'Found non-existent header.') + endforeach +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 has header/ouagadougou.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 has header/ouagadougou.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 has header/ouagadougou.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 has header/ouagadougou.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#define OMG_THIS_SHOULDNT_BE_FOUND diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 sizeof/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 sizeof/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 sizeof/config.h.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 sizeof/config.h.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -#define INTSIZE @INTSIZE@ -#define WCHARSIZE @WCHARSIZE@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 sizeof/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 sizeof/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 sizeof/meson.build" 2020-01-07 21:06:42.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 sizeof/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -project('sizeof', 'c', 'cpp') - -# Test with C -cc = meson.get_compiler('c') - -intsize = cc.sizeof('int') -wcharsize = cc.sizeof('wchar_t', prefix : '#include') - -cd = configuration_data() -cd.set('INTSIZE', intsize) -cd.set('WCHARSIZE', wcharsize) -cd.set('CONFIG', 'config.h') -configure_file(input : 'config.h.in', output : 'config.h', configuration : cd) -s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd) - -e = executable('prog', s) -test('sizeof test', e) - -# Test with C++ -cpp = meson.get_compiler('cpp') - -intsize = cpp.sizeof('int') -wcharsize = cpp.sizeof('wchar_t', prefix : '#include') - -cdpp = configuration_data() -cdpp.set('INTSIZE', intsize) -cdpp.set('WCHARSIZE', wcharsize) -cdpp.set('CONFIG', 'config.hpp') -configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp) -spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp) - -epp = executable('progpp', spp) -test('sizeof test c++', epp) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 sizeof/prog.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 sizeof/prog.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/32 sizeof/prog.c.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/32 sizeof/prog.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#include "@CONFIG@" -#include -#include - -int main(void) { - if(INTSIZE != sizeof(int)) { - fprintf(stderr, "Mismatch: detected int size %d, actual size %d.\n", INTSIZE, (int)sizeof(int)); - return 1; - } - if(WCHARSIZE != sizeof(wchar_t)) { - fprintf(stderr, "Mismatch: detected wchar size %d, actual size %d.\n", WCHARSIZE, (int)sizeof(wchar_t)); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 define10/config.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 define10/config.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 define10/config.h.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 define10/config.h.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -#mesondefine ONE -#mesondefine ZERO diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 define10/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 define10/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 define10/meson.build" 2020-01-07 21:06:40.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 define10/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -project('set10test', 'c') - -conf = configuration_data() -conf.set10('ONE', true) -conf.set10('ZERO', false) - -configure_file(input : 'config.h.in', - output : 'config.h', - configuration : conf) - -exe = executable('prog', 'prog.c') -test('10test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 define10/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 define10/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 define10/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 define10/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include -#include"config.h" - -int main(void) { - if(ONE != 1) { - fprintf(stderr, "ONE is not 1.\n"); - return 1; - } - if(ZERO != 0) { - fprintf(stderr, "ZERO is not 0.\n"); - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/check-env.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/check-env.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/check-env.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/check-env.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +import os + +assert os.environ['MY_PATH'] == os.pathsep.join(['0', '1', '2']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/get-version.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/get-version.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/get-version.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/get-version.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('1.2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,85 @@ +project('run command', version : run_command('get-version.py', check : true).stdout().strip()) + +if build_machine.system() == 'windows' + c = run_command('cmd', '/c', 'echo', 'hello', check: false) +else + c = run_command('echo', 'hello', check: false) +endif + +correct = 'hello' + +if c.returncode() != 0 + error('Executing echo failed.') +endif + +result = c.stdout().strip() + +if result != correct + error('Getting stdout failed.') +endif + +if c.stderr() != '' + error('Extra text in stderr.') +endif + +# Now the same with a script. + +if build_machine.system() == 'windows' + cs = run_command('scripts/hello.bat', check: false) +else + cs = run_command('scripts/hello.sh', check: false) +endif + +if cs.returncode() != 0 + error('Executing script failed.') +endif + +if cs.stdout().strip() != correct + error('Getting stdout failed (script).') +endif + +if cs.stderr() != '' + error('Extra text in stderr (script).') +endif + +# We should be able to have files() in argument +f = files('meson.build') + +if build_machine.system() == 'windows' + c = run_command('cmd', '/c', 'echo', f, check: false) +else + c = run_command('echo', f, check: false) +endif + +if c.returncode() != 0 + error('Using files() in argument failed.') +endif + +py3 = import('python3').find_python() + +ret = run_command(py3, '-c', 'print("some output")', check: false) +assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr()) +assert(ret.stdout() == 'some output\n', 'failed to run python3') + +ret = run_command(py3, '-c', 'print("some output")', check: false, capture: false) +assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr()) +assert(ret.stdout() == '', 'stdout is "@0@" instead of empty'.format(ret.stdout())) + +c_env = environment() +c_env.append('CUSTOM_ENV_VAR', 'FOOBAR') +ret = run_command(py3, '-c', 'import os; print(os.environ.get("CUSTOM_ENV_VAR"))', env: c_env, check: false) +assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr()) +assert(ret.stdout() == 'FOOBAR\n', 'stdout is "@0@" instead of FOOBAR'.format(ret.stdout())) + +dd = find_program('dd', required : false) +if dd.found() + ret = run_command(dd, 'if=/dev/urandom', 'bs=10', 'count=1', check: false, capture: false) + assert(ret.returncode() == 0, 'failed to run dd: ' + ret.stderr()) + assert(ret.stdout() == '', 'stdout is "@0@" instead of empty'.format(ret.stdout())) +endif + +env = environment() +env.append('MY_PATH', '1') +env.append('MY_PATH', '2') +env.prepend('MY_PATH', '0') +run_command('check-env.py', env: env, check: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/scripts/hello.bat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/scripts/hello.bat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/scripts/hello.bat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/scripts/hello.bat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +@ECHO OFF +ECHO hello diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/scripts/hello.sh" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/scripts/hello.sh" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/33 run program/scripts/hello.sh" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/33 run program/scripts/hello.sh" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/sh + +echo hello diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/34 has header/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/34 has header/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/34 has header/meson.build" 2020-01-07 21:06:42.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/34 has header/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -project('has header', 'c', 'cpp') - -host_system = host_machine.system() - -non_existent_header = 'ouagadougou.h' - -# Copy it into the builddir to ensure that it isn't found even if it's there -configure_file(input : non_existent_header, - output : non_existent_header, - configuration : configuration_data()) - -# Test that the fallback to __has_include also works on all compilers -if host_system != 'darwin' - fallbacks = ['', '\n#undef __has_include'] -else - # On Darwin's clang you can't redefine builtin macros so the above doesn't work - fallbacks = [''] -endif - -foreach fallback : fallbacks - foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')] - assert(comp.has_header('stdio.h', prefix : fallback), 'Stdio missing.') - - # stdio.h doesn't actually need stdlib.h, but just test that setting the - # prefix does not result in an error. - assert(comp.has_header('stdio.h', prefix : '#include ' + fallback), - 'Stdio missing.') - - # XInput.h should not require type definitions from windows.h, but it does - # require macro definitions. Specifically, it requires an arch setting for - # VS2015 at least. - # We only do this check on MSVC because MinGW often defines its own wrappers - # that pre-include windows.h - if comp.get_id() == 'msvc' - assert(comp.has_header('XInput.h', prefix : '#include ' + fallback), - 'XInput.h should not be missing on Windows') - assert(comp.has_header('XInput.h', prefix : '#define _X86_' + fallback), - 'XInput.h should not need windows.h') - endif - - # Test that the following GCC bug doesn't happen: - # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005 - # https://github.com/mesonbuild/meson/issues/1458 - if host_system == 'linux' - assert(comp.has_header('linux/if.h', prefix : fallback), - 'Could not find ') - endif - - # This header exists in the source and the builddir, but we still must not - # find it since we are looking in the system directories. - assert(not comp.has_header(non_existent_header, prefix : fallback), - 'Found non-existent header.') - endforeach -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/34 has header/ouagadougou.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/34 has header/ouagadougou.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/34 has header/ouagadougou.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/34 has header/ouagadougou.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#define OMG_THIS_SHOULDNT_BE_FOUND diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/34 logic ops/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/34 logic ops/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/34 logic ops/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/34 logic ops/meson.build" 2021-10-23 16:48:07.000000000 +0000 @@ -0,0 +1,95 @@ +project('logicopts', 'c') + +t = true +f = false + +if (true) + message('Ok.') +else + error('Not ok.') +endif + +if (false) + error('Not ok.') +else + message('Ok.') +endif + +if (f) + error('Not ok.') +else + message('Ok.') +endif + +if (t) + message('Ok.') +else + error('Not ok.') +endif + +if true and t + message('Ok.') +else + error('Not ok.') +endif + +if t and false + error('Not ok.') +else + message('Ok.') +endif + +if f and t + error('Not ok.') +else + message('Ok.') +endif + +if f or false + error('Not ok.') +else + message('Ok.') +endif + +if true or f + message('Ok.') +else + error('Not ok.') +endif + +if t or true + message('Ok.') +else + error('Not ok.') +endif + +if not true + error('Negation failed.') +else + message('Ok.') +endif + +if not f + message('Ok.') +else + error('Negation failed.') +endif + + +if f or f or f or f or f or f or f or f or t + message('Ok.') +else + error('Chain of ors failed.') +endif + +if t and t and t and t and t and t and t and t and f + error('Chain of ands failed.') +else + message('Ok.') +endif + +if t and t or t + message('Ok.') +else + error('Combination of and-or failed.') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 run program/get-version.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 run program/get-version.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 run program/get-version.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 run program/get-version.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/usr/bin/env python3 - -print('1.2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 run program/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 run program/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 run program/meson.build" 2020-01-07 21:06:42.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 run program/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -project('run command', version : run_command('get-version.py', check : true).stdout().strip()) - -if build_machine.system() == 'windows' - c = run_command('cmd', '/c', 'echo', 'hello') -else - c = run_command('echo', 'hello') -endif - -correct = 'hello' - -if c.returncode() != 0 - error('Executing echo failed.') -endif - -result = c.stdout().strip() - -if result != correct - error('Getting stdout failed.') -endif - -if c.stderr() != '' - error('Extra text in stderr.') -endif - -# Now the same with a script. - -if build_machine.system() == 'windows' - cs = run_command('scripts/hello.bat') -else - cs = run_command('scripts/hello.sh') -endif - -if cs.returncode() != 0 - error('Executing script failed.') -endif - -if cs.stdout().strip() != correct - error('Getting stdout failed (script).') -endif - -if cs.stderr() != '' - error('Extra text in stderr (script).') -endif - -# We should be able to have files() in argument -f = files('meson.build') - -if build_machine.system() == 'windows' - c = run_command('cmd', '/c', 'echo', f) -else - c = run_command('echo', f) -endif - -if c.returncode() != 0 - error('Using files() in argument failed.') -endif - -py3 = import('python3').find_python() - -ret = run_command(py3, '-c', 'print("some output")') -assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr()) -assert(ret.stdout() == 'some output\n', 'failed to run python3') - -ret = run_command(py3, '-c', 'print("some output")', capture : false) -assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr()) -assert(ret.stdout() == '', 'stdout is "@0@" instead of empty'.format(ret.stdout())) - -c_env = environment() -c_env.append('CUSTOM_ENV_VAR', 'FOOBAR') -ret = run_command(py3, '-c', 'import os; print(os.environ.get("CUSTOM_ENV_VAR"))', env : c_env) -assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr()) -assert(ret.stdout() == 'FOOBAR\n', 'stdout is "@0@" instead of FOOBAR'.format(ret.stdout())) - -dd = find_program('dd', required : false) -if dd.found() - ret = run_command(dd, 'if=/dev/urandom', 'bs=10', 'count=1', capture: false) - assert(ret.returncode() == 0, 'failed to run dd: ' + ret.stderr()) - assert(ret.stdout() == '', 'stdout is "@0@" instead of empty'.format(ret.stdout())) -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 run program/scripts/hello.bat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 run program/scripts/hello.bat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 run program/scripts/hello.bat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 run program/scripts/hello.bat" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -@ECHO OFF -ECHO hello diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 run program/scripts/hello.sh" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 run program/scripts/hello.sh" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 run program/scripts/hello.sh" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 run program/scripts/hello.sh" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/sh - -echo hello diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 string operations/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 string operations/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/35 string operations/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/35 string operations/meson.build" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,127 @@ +project('string formatting', 'c') + +templ = '@0@bar@1@' + +assert(templ.format('foo', 'baz') == 'foobarbaz', 'Basic string formatting is broken.') + +assert('@0@'.format(1) == '1', 'String number formatting is broken.') + +assert('@0@'.format(true) == 'true', 'String boolean formatting is broken.') + +templ2 = '@0@' +subs2 = '42' + +assert(templ2.format(subs2) == '42', 'String formatting with variables is broken.') + +assert('@@0@@ @@1@@'.format(1, 2) == '@1@ @2@', 'String format is recursive.') + +long = 'abcde' +prefix = 'abc' +suffix = 'cde' + +assert(long[0] == 'a') +assert(long[2] == 'c') + +assert(long.replace('b', 'd') == 'adcde') +assert(long.replace('z', 'x') == long) +assert(long.replace(prefix, suffix) == 'cdede') + +assert(long.startswith(prefix), 'Prefix.') + +assert(not long.startswith(suffix), 'Not prefix.') + +assert(long.endswith(suffix), 'Suffix.') + +assert(not long.endswith(prefix), 'Not suffix.') + +assert(long.contains(prefix), 'Does not contain prefix') + +assert(long.contains(suffix), 'Does not contain suffix') + +assert(long.contains('bcd'), 'Does not contain middle part') + +assert(not long.contains('dc'), 'Broken contains') + +assert(long.to_upper() == 'ABCDE', 'Broken to_upper') + +assert(long.to_upper().to_lower() == long, 'Broken to_lower') + +assert('struct stat.st_foo'.underscorify() == 'struct_stat_st_foo', 'Broken underscorify') + +assert('#include '.underscorify() == '_include__foo_bar_h_', 'Broken underscorify') + +# case should not change, space should be replaced, numbers are ok too +assert('Do SomeThing 09'.underscorify() == 'Do_SomeThing_09', 'Broken underscorify') + +assert('3'.to_int() == 3, 'String int conversion does not work.') + +assert(true.to_string() == 'true', 'bool string conversion failed') +assert(false.to_string() == 'false', 'bool string conversion failed') +assert(true.to_string('yes', 'no') == 'yes', 'bool string conversion with args failed') +assert(false.to_string('yes', 'no') == 'no', 'bool string conversion with args failed') +assert('@0@'.format(true) == 'true', 'bool string formatting failed') +assert('@0@'.format(['one', 'two']) == '[\'one\', \'two\']', 'list string formatting failed') + +assert(' '.join(['a', 'b', 'c']) == 'a b c', 'join() array broken') +assert(''.join(['a', 'b', 'c']) == 'abc', 'empty join() broken') +assert(' '.join(['a']) == 'a', 'single join broken') +assert(' '.join(['a'], ['b', ['c']], 'd') == 'a b c d', 'varargs join broken') + +version_number = '1.2.8' + +assert(version_number.version_compare('>=1.2.8'), 'Version_compare gt broken') +assert(not version_number.version_compare('>1.2.8'), 'Version_compare greater broken') +assert(not version_number.version_compare('<1.2.8'), 'Version_compare less broken') +assert(version_number.version_compare('<=1.2.8'), 'Version_compare le broken') +assert(version_number.version_compare('==1.2.8'), 'Version_compare eq broken') +assert(not version_number.version_compare('!=1.2.8'), 'Version_compare neq broken') + +assert(version_number.version_compare('<2.0'), 'Version_compare major less broken') +assert(version_number.version_compare('>0.9'), 'Version_compare major greater broken') + +assert(' spaces tabs '.strip() == 'spaces tabs', 'Spaces and tabs badly stripped') +assert(''' +multiline string '''.strip() == '''multiline string''', 'Newlines badly stripped') +assert('"1.1.20"'.strip('"') == '1.1.20', '" badly stripped') +assert('"1.1.20"'.strip('".') == '1.1.20', '". badly stripped') +assert('"1.1.20" '.strip('" ') == '1.1.20', '". badly stripped') + +bs_c = '''\c''' +bs_bs_c = '''\\c''' +nl = ''' +''' +bs_n = '''\n''' +bs_nl = '''\ +''' +bs_bs_n = '''\\n''' +bs_bs_nl = '''\\ +''' +bs_bs = '''\\''' +bs = '''\''' + +assert('\c' == bs_c, 'Single backslash broken') +assert('\\c' == bs_c, 'Double backslash broken') +assert('\\\c' == bs_bs_c, 'Three backslash broken') +assert('\\\\c' == bs_bs_c, 'Four backslash broken') +assert('\n' == nl, 'Newline escape broken') +assert('\\n' == bs_n, 'Double backslash broken before n') +assert('\\\n' == bs_nl, 'Three backslash broken before n') +assert('\\\\n' == bs_bs_n, 'Four backslash broken before n') +assert('\\\\\n' == bs_bs_nl, 'Five backslash broken before n') +assert('\\\\' == bs_bs, 'Double-backslash broken') +assert('\\' == bs, 'Backslash broken') + +mysubstring='foobarbaz' +assert(mysubstring.substring() == 'foobarbaz', 'substring is broken') +assert(mysubstring.substring(0) == 'foobarbaz', 'substring is broken') +assert(mysubstring.substring(1) == 'oobarbaz', 'substring is broken') +assert(mysubstring.substring(-5) == 'arbaz', 'substring is broken') +assert(mysubstring.substring(1, 4) == 'oob', 'substring is broken') +assert(mysubstring.substring(1,-5) == 'oob', 'substring is broken') +assert(mysubstring.substring(1, 0) == '', 'substring is broken') +assert(mysubstring.substring(0, 100) == 'foobarbaz', 'substring is broken') +assert(mysubstring.substring(-1, -5) == '', 'substring is broken') +assert(mysubstring.substring(10, -25) == '', 'substring is broken') +assert(mysubstring.substring(-4, 2) == '', 'substring is broken') +assert(mysubstring.substring(10, 9) == '', 'substring is broken') +assert(mysubstring.substring(8, 10) == 'z', 'substring is broken') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 has function/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 has function/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 has function/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 has function/meson.build" 2021-10-23 16:48:16.000000000 +0000 @@ -0,0 +1,116 @@ +project('has function', 'c', 'cpp') + +host_system = host_machine.system() + +# This is used in the `test_compiler_check_flags_order` unit test +unit_test_args = '-I/tmp' +defines_has_builtin = '''#ifndef __has_builtin +#error "no __has_builtin" +#endif +''' +compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] + +foreach cc : compilers + if not cc.has_function('printf', prefix : '#include', + args : unit_test_args) + error('"printf" function not found (should always exist).') + endif + + # Should also be able to detect it without specifying the header + # We check for a different function here to make sure the result is + # not taken from a cache (ie. the check above) + # On MSVC fprintf is defined as an inline function in the header, so it cannot + # be found without the include. + if not ['msvc', 'intel-cl'].contains(cc.get_id()) + assert(cc.has_function('fprintf', args : unit_test_args), + '"fprintf" function not found without include (on !msvc).') + else + assert(cc.has_function('fprintf', prefix : '#include ', + args : unit_test_args), + '"fprintf" function not found with include (on msvc).') + # Compiler intrinsics + assert(cc.has_function('strcmp'), + 'strcmp intrinsic should have been found on MSVC') + assert(cc.has_function('strcmp', prefix : '#include '), + 'strcmp intrinsic should have been found with #include on MSVC') + endif + + if cc.has_function('hfkerhisadf', prefix : '#include', + args : unit_test_args) + error('Found non-existent function "hfkerhisadf".') + endif + + if cc.has_function('hfkerhisadf', args : unit_test_args) + error('Found non-existent function "hfkerhisadf".') + endif + + # With glibc (before 2.32, see below) on Linux, lchmod is a stub that will + # always return an error, we want to detect that and declare that the + # function is not available. + # We can't check for the C library used here of course, but the main + # alternative Linux C library (musl) doesn't use glibc's stub mechanism; + # also, it has implemented lchmod since 2013, so it should be safe to check + # that lchmod is available on Linux when not using glibc. + if host_system == 'linux' or host_system == 'darwin' + assert (cc.has_function('poll', prefix : '#include ', + args : unit_test_args), + 'couldn\'t detect "poll" when defined by a header') + lchmod_prefix = '#include \n#include ' + has_lchmod = cc.has_function('lchmod', prefix : lchmod_prefix, args : unit_test_args) + + if host_system == 'linux' + # __GLIBC__ macro can be retrieved by including almost any C library header + glibc_major = cc.get_define('__GLIBC__', prefix: '#include ', args: unit_test_args) + # __GLIBC__ will only be set for glibc + if glibc_major != '' + glibc_minor = cc.get_define('__GLIBC_MINOR__', prefix: '#include ', args: unit_test_args) + glibc_vers = '@0@.@1@'.format(glibc_major, glibc_minor) + message('GLIBC version:', glibc_vers) + + # lchmod was implemented in glibc 2.32 (https://sourceware.org/pipermail/libc-announce/2020/000029.html) + if glibc_vers.version_compare('<2.32') + assert (not has_lchmod, '"lchmod" check should have failed') + else + assert (has_lchmod, '"lchmod" check should have succeeded') + endif + else + # Other C libraries for Linux should have lchmod + assert (has_lchmod, '"lchmod" check should have succeeded') + endif + else + # macOS and *BSD have lchmod + assert (has_lchmod, '"lchmod" check should have succeeded') + endif + # Check that built-ins are found properly both with and without headers + assert(cc.has_function('alloca', args : unit_test_args), + 'built-in alloca must be found on ' + host_system) + assert(cc.has_function('alloca', prefix : '#include ', + args : unit_test_args), + 'built-in alloca must be found with #include') + if not cc.compiles(defines_has_builtin, args : unit_test_args) + assert(not cc.has_function('alloca', + prefix : '#include \n#undef alloca', + args : unit_test_args), + 'built-in alloca must not be found with #include and #undef') + endif + endif + + # For some functions one needs to define _GNU_SOURCE before including the + # right headers to get them picked up. Make sure we can detect these functions + # as well without any prefix + if cc.has_header_symbol('sys/socket.h', 'recvmmsg', + prefix : '#define _GNU_SOURCE', + args : unit_test_args) + # We assume that if recvmmsg exists sendmmsg does too + assert (cc.has_function('sendmmsg', args : unit_test_args), + 'Failed to detect function "sendmmsg" (should always exist).') + endif + + # We should be able to find GCC and Clang __builtin functions + if ['gcc', 'clang'].contains(cc.get_id()) + # __builtin_constant_p is documented to exist at least as far back as + # GCC 2.95.3 + assert(cc.has_function('__builtin_constant_p', args : unit_test_args), + '__builtin_constant_p must be found under gcc and clang') + endif +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 tryrun/error.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 tryrun/error.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 tryrun/error.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 tryrun/error.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 tryrun/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 tryrun/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 tryrun/meson.build" 2020-01-07 21:06:46.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 tryrun/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -project('tryrun', 'c', 'cpp') - -# Complex to exercise all code paths. -if meson.is_cross_build() - if meson.has_exe_wrapper() - compilers = [meson.get_compiler('c', native : false), meson.get_compiler('cpp', native : false)] - else - compilers = [meson.get_compiler('c', native : true), meson.get_compiler('cpp', native : true)] - endif -else - compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] -endif - -ok_code = '''#include -int main(void) { - printf("%s\n", "stdout"); - fprintf(stderr, "%s\n", "stderr"); - return 0; -} -''' - -error_code = '''int main(void) { - return 1; -} -''' - -no_compile_code = '''int main(void) { -''' - -INPUTS = [ - ['String', ok_code, error_code, no_compile_code], - ['File', files('ok.c'), files('error.c'), files('no_compile.c')], -] - -foreach cc : compilers - foreach input : INPUTS - type = input[0] - ok = cc.run(input[1], name : type + ' should succeed') - err = cc.run(input[2], name : type + ' should fail') - noc = cc.run(input[3], name : type + ' does not compile') - - if noc.compiled() - error(type + ' compilation fail test failed.') - else - message(type + ' fail detected properly.') - endif - - if ok.compiled() - message(type + ' compilation worked.') - else - error(type + ' compilation did not work.') - endif - - if ok.returncode() == 0 - message(type + ' return code ok.') - else - error(type + ' return code fail') - endif - - if err.returncode() == 1 - message(type + ' bad return code ok.') - else - error(type + ' bad return code fail.') - endif - - if ok.stdout().strip() == 'stdout' - message(type + ' stdout ok.') - else - message(type + ' bad stdout.') - endif - - if ok.stderr().strip() == 'stderr' - message(type + ' stderr ok.') - else - message(type + ' bad stderr.') - endif - endforeach -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 tryrun/no_compile.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 tryrun/no_compile.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 tryrun/no_compile.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 tryrun/no_compile.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(void) { diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 tryrun/ok.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 tryrun/ok.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/36 tryrun/ok.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/36 tryrun/ok.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include - -int main(void) { - printf("%s\n", "stdout"); - fprintf(stderr, "%s\n", "stderr"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/37 has member/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/37 has member/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/37 has member/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/37 has member/meson.build" 2021-10-23 16:48:12.000000000 +0000 @@ -0,0 +1,21 @@ +project('has member', 'c', 'cpp') + +compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] + +foreach cc : compilers + if not cc.has_member('struct tm', 'tm_sec', prefix : '#include') + error('Did not detect member of "struct tm" that exists: "tm_sec"') + endif + + if cc.has_member('struct tm', 'tm_nonexistent', prefix : '#include') + error('Not existing member "tm_nonexistent" found.') + endif + + if not cc.has_members('struct tm', 'tm_sec', 'tm_min', prefix : '#include') + error('Did not detect members of "struct tm" that exist: "tm_sec" "tm_min"') + endif + + if cc.has_members('struct tm', 'tm_sec', 'tm_nonexistent2', prefix : '#include') + error('Not existing member "tm_nonexistent2" found.') + endif +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/37 logic ops/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/37 logic ops/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/37 logic ops/meson.build" 2020-01-07 21:06:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/37 logic ops/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -project('logicopts', 'c') - -t = true -f = false - -if (true) - message('Ok.') -else - error('Not ok.') -endif - -if (false) - error('Not ok.') -else - message('Ok.') -endif - -if (f) - error('Not ok.') -else - message('Ok.') -endif - -if (t) - message('Ok.') -else - error('Not ok.') -endif - -if true and t - message('Ok.') -else - error('Not ok.') -endif - -if t and false - error('Not ok.') -else - message('Ok.') -endif - -if f and t - error('Not ok.') -else - message('Ok.') -endif - -if f or false - error('Not ok.') -else - message('Ok.') -endif - -if true or f - message('Ok.') -else - error('Not ok.') -endif - -if t or true - message('Ok.') -else - error('Not ok.') -endif - -if not true - error('Negation failed.') -else - message('Ok.') -endif - -if not f - message('Ok.') -else - error('Negation failed.') -endif - - -if f or f or f or f or f or f or f or f or t - message('Ok.') -else - error('Chain of ors failed.') -endif - -if t and t and t and t and t and t and t and t and f - error('Chain of ands failed.') -else - message('Ok.') -endif - -if t and t or t - message('Ok.') -else - error('Combination of and-or failed.') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/38 alignment/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/38 alignment/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/38 alignment/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/38 alignment/meson.build" 2021-10-23 16:48:14.000000000 +0000 @@ -0,0 +1,31 @@ +project('alignment', 'c', 'cpp') + +compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] + +foreach cc : compilers + # These tests should return the same value on all + # platforms. If (and when) they don't, fix 'em up. + if cc.alignment('char') != 1 + error('Alignment of char misdetected.') + endif + + ptr_size = cc.sizeof('void*') + dbl_alignment = cc.alignment('double') + + # These tests are not thorough. Doing this properly + # would take a lot of work because it is strongly + # platform and compiler dependent. So just check + # that they produce something fairly sane. + + if ptr_size == 8 or ptr_size == 4 + message('Size of ptr ok.') + else + error('Size of ptr misdetected.') + endif + + if dbl_alignment == 8 or dbl_alignment == 4 + message('Alignment of double ok.') + else + error('Alignment of double misdetected.') + endif +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/38 string operations/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/38 string operations/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/38 string operations/meson.build" 2020-01-07 21:06:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/38 string operations/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -project('string formatting', 'c') - -templ = '@0@bar@1@' - -assert(templ.format('foo', 'baz') == 'foobarbaz', 'Basic string formatting is broken.') - -assert('@0@'.format(1) == '1', 'String number formatting is broken.') - -assert('@0@'.format(true) == 'true', 'String boolean formatting is broken.') - -templ2 = '@0@' -subs2 = '42' - -assert(templ2.format(subs2) == '42', 'String formatting with variables is broken.') - -assert('@@0@@ @@1@@'.format(1, 2) == '@1@ @2@', 'String format is recursive.') - -long = 'abcde' -prefix = 'abc' -suffix = 'cde' - -assert(long.startswith(prefix), 'Prefix.') - -assert(not long.startswith(suffix), 'Not prefix.') - -assert(long.endswith(suffix), 'Suffix.') - -assert(not long.endswith(prefix), 'Not suffix.') - -assert(long.contains(prefix), 'Does not contain prefix') - -assert(long.contains(suffix), 'Does not contain suffix') - -assert(long.contains('bcd'), 'Does not contain middle part') - -assert(not long.contains('dc'), 'Broken contains') - -assert(long.to_upper() == 'ABCDE', 'Broken to_upper') - -assert(long.to_upper().to_lower() == long, 'Broken to_lower') - -assert('struct stat.st_foo'.underscorify() == 'struct_stat_st_foo', 'Broken underscorify') - -assert('#include '.underscorify() == '_include__foo_bar_h_', 'Broken underscorify') - -# case should not change, space should be replaced, numbers are ok too -assert('Do SomeThing 09'.underscorify() == 'Do_SomeThing_09', 'Broken underscorify') - -assert('3'.to_int() == 3, 'String int conversion does not work.') - -assert(true.to_string() == 'true', 'bool string conversion failed') -assert(false.to_string() == 'false', 'bool string conversion failed') -assert(true.to_string('yes', 'no') == 'yes', 'bool string conversion with args failed') -assert(false.to_string('yes', 'no') == 'no', 'bool string conversion with args failed') -assert('@0@'.format(true) == 'true', 'bool string formatting failed') - -assert(' '.join(['a', 'b', 'c']) == 'a b c', 'join() array broken') -assert(''.join(['a', 'b', 'c']) == 'abc', 'empty join() broken') -assert(' '.join(['a']) == 'a', 'single join broken') - -version_number = '1.2.8' - -assert(version_number.version_compare('>=1.2.8'), 'Version_compare gt broken') -assert(not version_number.version_compare('>1.2.8'), 'Version_compare greater broken') -assert(not version_number.version_compare('<1.2.8'), 'Version_compare less broken') -assert(version_number.version_compare('<=1.2.8'), 'Version_compare le broken') -assert(version_number.version_compare('==1.2.8'), 'Version_compare eq broken') -assert(not version_number.version_compare('!=1.2.8'), 'Version_compare neq broken') - -assert(version_number.version_compare('<2.0'), 'Version_compare major less broken') -assert(version_number.version_compare('>0.9'), 'Version_compare major greater broken') - -assert(' spaces tabs '.strip() == 'spaces tabs', 'Spaces and tabs badly stripped') -assert(''' -multiline string '''.strip() == '''multiline string''', 'Newlines badly stripped') -assert('"1.1.20"'.strip('"') == '1.1.20', '" badly stripped') -assert('"1.1.20"'.strip('".') == '1.1.20', '". badly stripped') -assert('"1.1.20" '.strip('" ') == '1.1.20', '". badly stripped') - -bs_c = '''\c''' -bs_bs_c = '''\\c''' -nl = ''' -''' -bs_n = '''\n''' -bs_nl = '''\ -''' -bs_bs_n = '''\\n''' -bs_bs_nl = '''\\ -''' -bs_bs = '''\\''' -bs = '''\''' - -assert('\c' == bs_c, 'Single backslash broken') -assert('\\c' == bs_c, 'Double backslash broken') -assert('\\\c' == bs_bs_c, 'Three backslash broken') -assert('\\\\c' == bs_bs_c, 'Four backslash broken') -assert('\n' == nl, 'Newline escape broken') -assert('\\n' == bs_n, 'Double backslash broken before n') -assert('\\\n' == bs_nl, 'Three backslash broken before n') -assert('\\\\n' == bs_bs_n, 'Four backslash broken before n') -assert('\\\\\n' == bs_bs_nl, 'Five backslash broken before n') -assert('\\\\' == bs_bs, 'Double-backslash broken') -assert('\\' == bs, 'Backslash broken') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 has function/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 has function/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 has function/meson.build" 2020-01-07 21:06:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 has function/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -project('has function', 'c', 'cpp') - -host_system = host_machine.system() - -# This is used in the `test_compiler_check_flags_order` unit test -unit_test_args = '-I/tmp' -defines_has_builtin = '''#ifndef __has_builtin -#error "no __has_builtin" -#endif -''' -compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] - -foreach cc : compilers - if not cc.has_function('printf', prefix : '#include', - args : unit_test_args) - error('"printf" function not found (should always exist).') - endif - - # Should also be able to detect it without specifying the header - # We check for a different function here to make sure the result is - # not taken from a cache (ie. the check above) - # On MSVC fprintf is defined as an inline function in the header, so it cannot - # be found without the include. - if not ['msvc', 'intel-cl'].contains(cc.get_id()) - assert(cc.has_function('fprintf', args : unit_test_args), - '"fprintf" function not found without include (on !msvc).') - else - assert(cc.has_function('fprintf', prefix : '#include ', - args : unit_test_args), - '"fprintf" function not found with include (on msvc).') - # Compiler intrinsics - assert(cc.has_function('strcmp'), - 'strcmp intrinsic should have been found on MSVC') - assert(cc.has_function('strcmp', prefix : '#include '), - 'strcmp intrinsic should have been found with #include on MSVC') - endif - - if cc.has_function('hfkerhisadf', prefix : '#include', - args : unit_test_args) - error('Found non-existent function "hfkerhisadf".') - endif - - if cc.has_function('hfkerhisadf', args : unit_test_args) - error('Found non-existent function "hfkerhisadf".') - endif - - # With glibc on Linux lchmod is a stub that will always return an error, - # we want to detect that and declare that the function is not available. - # We can't check for the C library used here of course, but if it's not - # implemented in glibc it's probably not implemented in any other 'slimmer' - # C library variants either, so the check should be safe either way hopefully. - if host_system == 'linux' or host_system == 'darwin' - assert (cc.has_function('poll', prefix : '#include ', - args : unit_test_args), - 'couldn\'t detect "poll" when defined by a header') - lchmod_prefix = '#include \n#include ' - if host_system == 'linux' - assert (not cc.has_function('lchmod', prefix : lchmod_prefix, - args : unit_test_args), - '"lchmod" check should have failed') - else - # macOS and *BSD have lchmod - assert (cc.has_function('lchmod', prefix : lchmod_prefix, - args : unit_test_args), - '"lchmod" check should have succeeded') - endif - # Check that built-ins are found properly both with and without headers - assert(cc.has_function('alloca', args : unit_test_args), - 'built-in alloca must be found on ' + host_system) - assert(cc.has_function('alloca', prefix : '#include ', - args : unit_test_args), - 'built-in alloca must be found with #include') - if not cc.compiles(defines_has_builtin, args : unit_test_args) - assert(not cc.has_function('alloca', - prefix : '#include \n#undef alloca', - args : unit_test_args), - 'built-in alloca must not be found with #include and #undef') - endif - endif - - # For some functions one needs to define _GNU_SOURCE before including the - # right headers to get them picked up. Make sure we can detect these functions - # as well without any prefix - if cc.has_header_symbol('sys/socket.h', 'recvmmsg', - prefix : '#define _GNU_SOURCE', - args : unit_test_args) - # We assume that if recvmmsg exists sendmmsg does too - assert (cc.has_function('sendmmsg', args : unit_test_args), - 'Failed to detect function "sendmmsg" (should always exist).') - endif -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int libfun(void); + +int main(void) { + return libfun(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/meson.build" 2021-10-23 16:48:13.000000000 +0000 @@ -0,0 +1,5 @@ +project('libchain', 'c') + +subdir('subdir') +e = executable('prog', 'main.c', link_with : lib1, install : true) +test('tst', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/lib1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/lib1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/lib1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/lib1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +int lib2fun(void); +int lib3fun(void); + +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC libfun(void) { + return lib2fun() + lib3fun(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +subdir('subdir2') +subdir('subdir3') + +lib1 = shared_library('lib1', 'lib1.c', install : false, link_with : [lib2, lib3]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/subdir2/lib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/subdir2/lib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/subdir2/lib2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/subdir2/lib2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC lib2fun(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/subdir2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/subdir2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/subdir2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/subdir2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +lib2 = shared_library('lib2', 'lib2.c', install : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/subdir3/lib3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/subdir3/lib3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/subdir3/lib3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/subdir3/lib3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC lib3fun(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/subdir3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/subdir3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/subdir/subdir3/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/subdir/subdir3/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +lib3 = shared_library('lib3', 'lib3.c', install : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/39 library chain/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/39 library chain/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/3 static/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/3 static/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/3 static/meson.build" 2020-01-07 21:06:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/3 static/meson.build" 2021-10-23 16:47:44.000000000 +0000 @@ -2,7 +2,7 @@ lib = static_library('mylib', get_option('source'), link_args : '-THISMUSTNOBEUSED') # Static linker needs to ignore all link args. - +assert(lib.name() == 'mylib') has_not_changed = false if is_disabler(lib) has_not_changed = true diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/40 has member/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/40 has member/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/40 has member/meson.build" 2020-01-07 21:06:49.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/40 has member/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -project('has member', 'c', 'cpp') - -compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] - -foreach cc : compilers - if not cc.has_member('struct tm', 'tm_sec', prefix : '#include') - error('Did not detect member of "struct tm" that exists: "tm_sec"') - endif - - if cc.has_member('struct tm', 'tm_nonexistent', prefix : '#include') - error('Not existing member "tm_nonexistent" found.') - endif - - if not cc.has_members('struct tm', 'tm_sec', 'tm_min', prefix : '#include') - error('Did not detect members of "struct tm" that exist: "tm_sec" "tm_min"') - endif - - if cc.has_members('struct tm', 'tm_sec', 'tm_nonexistent2', prefix : '#include') - error('Not existing member "tm_nonexistent2" found.') - endif -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/40 options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/40 options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/40 options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/40 options/meson.build" 2021-10-23 16:48:12.000000000 +0000 @@ -0,0 +1,45 @@ +project('options', 'c') + +if get_option('testoption') != 'optval' + error('Incorrect value to test option') +endif + +if get_option('other_one') != false + error('Incorrect value to boolean option.') +endif + +if get_option('combo_opt') != 'combo' + error('Incorrect value to combo option.') +endif + +if get_option('array_opt') != ['one', 'two'] + message(get_option('array_opt')) + error('Incorrect value for array option') +endif + +# If the default changes, update test cases/unit/13 reconfigure +if get_option('b_lto') != false + error('Incorrect value in base option.') +endif + +if get_option('includedir') != 'include' + error('Incorrect value in builtin option.') +endif + +if get_option('integer_opt') != 3 + error('Incorrect value in integer option.') +endif + +if get_option('neg_int_opt') != -3 + error('Incorrect value in negative integer option.') +endif + +if get_option('CaseSenSiTivE') != 'Some CAPS' + error('Incorrect value in mixed caps option.') +endif + +if get_option('CASESENSITIVE') != 'ALL CAPS' + error('Incorrect value in all caps option.') +endif + +assert(get_option('wrap_mode') == 'default', 'Wrap mode option is broken.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/40 options/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/40 options/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/40 options/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/40 options/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +option('testoption', type : 'string', value : 'optval', description : 'An option ' + 'to do something') +option('other_one', type : 'boolean', value : not (not (not (not false)))) +option('combo_opt', type : 'co' + 'mbo', choices : ['one', 'two', 'combo'], value : 'combo') +option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two']) +option('free_array_opt', type : 'array') +option('integer_opt', type : 'integer', min : 0, max : -(-5), value : 3) +option('neg' + '_' + 'int' + '_' + 'opt', type : 'integer', min : -5, max : 5, value : -3) +option('CaseSenSiTivE', type : 'string', value: 'Some CAPS', description : 'An option with mixed capitaliziation') +option('CASESENSITIVE', type : 'string', value: 'ALL CAPS', description : 'An option with all caps') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 alignment/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 alignment/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 alignment/meson.build" 2020-01-07 21:06:51.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 alignment/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -project('alignment', 'c', 'cpp') - -compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] - -foreach cc : compilers - # These tests should return the same value on all - # platforms. If (and when) they don't, fix 'em up. - if cc.alignment('char') != 1 - error('Alignment of char misdetected.') - endif - - ptr_size = cc.sizeof('void*') - dbl_alignment = cc.alignment('double') - - # These tests are not thorough. Doing this properly - # would take a lot of work because it is strongly - # platform and compiler dependent. So just check - # that they produce something fairly sane. - - if ptr_size == 8 or ptr_size == 4 - message('Size of ptr ok.') - else - error('Size of ptr misdetected.') - endif - - if dbl_alignment == 8 or dbl_alignment == 4 - message('Alignment of double ok.') - else - error('Alignment of double misdetected.') - endif -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/cmd_args.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/cmd_args.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/cmd_args.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/cmd_args.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#include +#include + +int main(int argc, char **argv) { + if(argc != 3) { + fprintf(stderr, "Incorrect number of arguments.\n"); + return 1; + } + if(strcmp(argv[1], "first") != 0) { + fprintf(stderr, "First argument is wrong.\n"); + return 1; + } + if(strcmp(argv[2], "second") != 0) { + fprintf(stderr, "Second argument is wrong.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/copyfile.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/env2vars.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/env2vars.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/env2vars.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/env2vars.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,23 @@ +#include +#include +#include + +int main(void) { + if(strcmp(getenv("first"), "something-else") != 0) { + fprintf(stderr, "First envvar is wrong. %s\n", getenv("first")); + return 1; + } + if(strcmp(getenv("second"), "val2") != 0) { + fprintf(stderr, "Second envvar is wrong.\n"); + return 1; + } + if(strcmp(getenv("third"), "val3:and_more") != 0) { + fprintf(stderr, "Third envvar is wrong.\n"); + return 1; + } + if(strstr(getenv("PATH"), "fakepath:") != NULL) { + fprintf(stderr, "Third envvar is wrong.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/envvars.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/envvars.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/envvars.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/envvars.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,23 @@ +#include +#include +#include + +int main(void) { + if(strcmp(getenv("first"), "val1") != 0) { + fprintf(stderr, "First envvar is wrong. %s\n", getenv("first")); + return 1; + } + if(strcmp(getenv("second"), "val2") != 0) { + fprintf(stderr, "Second envvar is wrong.\n"); + return 1; + } + if(strcmp(getenv("third"), "val3:and_more") != 0) { + fprintf(stderr, "Third envvar is wrong.\n"); + return 1; + } + if(strstr(getenv("PATH"), "fakepath:") != NULL) { + fprintf(stderr, "Third envvar is wrong.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/meson.build" 2021-10-23 16:48:12.000000000 +0000 @@ -0,0 +1,35 @@ +project('test features', 'c') + +e1 = executable('cmd_args', 'cmd_args.c') +e2 = executable('envvars', 'envvars.c') +e3 = executable('env2vars', 'env2vars.c') + +env = environment() +env.set('first', 'val1') +env.set('second', 'val2') +env.set('third', 'val3', 'and_more', separator: ':') +env.append('PATH', 'fakepath', separator: ':') + +# Make sure environment objects are copied on assignment and we can +# change the copy without affecting the original environment object. +env2 = env +env2.set('first', 'something-else') + +test('command line arguments', e1, args : ['first', 'second']) +test('environment variables', e2, env : env) +test('environment variables 2', e3, env : env2) + +# https://github.com/mesonbuild/meson/issues/2211#issuecomment-327741571 +env_array = ['MESONTESTING=picklerror'] +testfile = files('testfile.txt') +testerpy = find_program('tester.py') +test('file arg', testerpy, args : testfile, env : [env_array, 'TEST_LIST_FLATTENING=1']) + +copy = find_program('copyfile.py') +tester = executable('tester', 'tester.c') +testfilect = custom_target('testfile', + input : testfile, + output : 'outfile.txt', + build_by_default : true, + command : [copy, '@INPUT@', '@OUTPUT@']) +test('custom target arg', tester, args : testfilect, env : env_array) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/tester.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/tester.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/tester.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/tester.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +#endif + +int main(int argc, char **argv) { + char data[10]; + int fd, size; + + if (argc != 2) { + fprintf(stderr, "Incorrect number of arguments, got %i\n", argc); + return 1; + } + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + fprintf(stderr, "First argument is wrong.\n"); + return 1; + } + + size = read(fd, data, 8); + if (size < 0) { + fprintf(stderr, "Failed to read: %s\n", strerror(errno)); + return 1; + } + if (strncmp(data, "contents", 8) != 0) { + fprintf(stderr, "Contents don't match, got %s\n", data); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/tester.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/tester.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/tester.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/tester.py" 2021-06-07 17:35:22.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import sys +import os + +assert os.environ['MESONTESTING'] == 'picklerror' +assert os.environ['TEST_LIST_FLATTENING'] == '1' + +with open(sys.argv[1]) as f: + if f.read() != 'contents\n': + sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/testfile.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/testfile.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/41 test args/testfile.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/41 test args/testfile.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +contents diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int libfun(void); - -int main(void) { - return libfun(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/meson.build" 2020-01-07 21:06:52.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('libchain', 'c') - -subdir('subdir') -e = executable('prog', 'main.c', link_with : lib1, install : true) -test('tst', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/lib1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/lib1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/lib1.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/lib1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -int lib2fun(void); -int lib3fun(void); - -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC libfun(void) { - return lib2fun() + lib3fun(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -subdir('subdir2') -subdir('subdir3') - -lib1 = shared_library('lib1', 'lib1.c', install : false, link_with : [lib2, lib3]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/subdir2/lib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/subdir2/lib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/subdir2/lib2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/subdir2/lib2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC lib2fun(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/subdir2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/subdir2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/subdir2/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/subdir2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -lib2 = shared_library('lib2', 'lib2.c', install : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/subdir3/lib3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/subdir3/lib3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/subdir3/lib3.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/subdir3/lib3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC lib3fun(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/subdir3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/subdir3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 library chain/subdir/subdir3/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 library chain/subdir/subdir3/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -lib3 = shared_library('lib3', 'lib3.c', install : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,28 @@ +project('subproj user', 'c', + version : '2.3.4', + license : 'mylicense') + +assert(meson.project_name() == 'subproj user', 'Incorrect project name') + +sub = subproject('sublib', version : '1.0.0') + +if meson.project_version() != '2.3.4' + error('Incorrect master project version string:' + meson.project_version()) +endif + +if meson.is_subproject() + error('Claimed to be a subproject even though we are the master project.') +endif + +inc = sub.get_variable('i') +lib = sub.get_variable('l') + +e = executable('user', 'user.c', include_directories : inc, link_with : lib, install : true) +test('subdirtest', e) + +meson.install_dependency_manifest('share/sublib/sublib.depmf') + +unknown_var = sub.get_variable('does-not-exist', []) +if unknown_var != [] + error ('unexpetced fallback value for subproject.get_variable()') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/subprojects/sublib/include/subdefs.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/subprojects/sublib/include/subdefs.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/subprojects/sublib/include/subdefs.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/subprojects/sublib/include/subdefs.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,21 @@ +#ifndef SUBDEFS_H_ +#define SUBDEFS_H_ + +#if defined _WIN32 || defined __CYGWIN__ +#if defined BUILDING_SUB + #define DLL_PUBLIC __declspec(dllexport) +#else + #define DLL_PUBLIC __declspec(dllimport) +#endif +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC subfunc(void); + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/subprojects/sublib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/subprojects/sublib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/subprojects/sublib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/subprojects/sublib/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,19 @@ +project('subproject', 'c', + version : '1.0.0', + license : ['sublicense1', 'sublicense2']) + +if not meson.is_subproject() + error('Claimed to be master project even though we are a subproject.') +endif + +assert(meson.project_name() == 'subproject', 'Incorrect subproject name') + +if meson.project_version() != '1.0.0' + error('Incorrect version string in subproject.') +endif + +i = include_directories('include') +l = shared_library('sublib', 'sublib.c', include_directories : i, install : false, + c_args : '-DBUILDING_SUB=2') +t = executable('simpletest', 'simpletest.c', include_directories : i, link_with : l) +test('plain', t) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/subprojects/sublib/simpletest.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/subprojects/sublib/simpletest.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/subprojects/sublib/simpletest.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/subprojects/sublib/simpletest.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int main(void) { + return subfunc() == 42 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/subprojects/sublib/sublib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/subprojects/sublib/sublib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/subprojects/sublib/sublib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/subprojects/sublib/sublib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int DLL_PUBLIC subfunc(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/user"}, + {"type": "pdb", "file": "usr/bin/user"}, + {"type": "file", "file": "usr/share/sublib/sublib.depmf"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/user.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/user.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/42 subproject/user.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/42 subproject/user.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#include +#include + + +int main(void) { + int res; + printf("Calling into sublib now.\n"); + res = subfunc(); + if(res == 42) { + printf("Everything is fine.\n"); + return 0; + } else { + printf("Something went wrong.\n"); + return 1; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 options/meson.build" 2020-01-07 21:06:51.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 options/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -project('options', 'c') - -if get_option('testoption') != 'optval' - error('Incorrect value to test option') -endif - -if get_option('other_one') != false - error('Incorrect value to boolean option.') -endif - -if get_option('combo_opt') != 'combo' - error('Incorrect value to combo option.') -endif - -if get_option('array_opt') != ['one', 'two'] - message(get_option('array_opt')) - error('Incorrect value for array option') -endif - -# If the default changes, update test cases/unit/13 reconfigure -if get_option('b_lto') != false - error('Incorrect value in base option.') -endif - -if get_option('includedir') != 'include' - error('Incorrect value in builtin option.') -endif - -if get_option('integer_opt') != 3 - error('Incorrect value in integer option.') -endif - -assert(get_option('wrap_mode') == 'default', 'Wrap mode option is broken.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 options/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 options/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 options/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 options/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -option('testoption', type : 'string', value : 'optval', description : 'An option to do something') -option('other_one', type : 'boolean', value : false) -option('combo_opt', type : 'combo', choices : ['one', 'two', 'combo'], value : 'combo') -option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two']) -option('free_array_opt', type : 'array') -option('integer_opt', type : 'integer', min : 0, max : 5, value : 3) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 subproject options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 subproject options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 subproject options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 subproject options/meson.build" 2021-10-23 16:48:12.000000000 +0000 @@ -0,0 +1,7 @@ +project('suboptions', 'c') + +subproject('subproject') + +if not get_option('opt') + error('option unset when it should be set') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 subproject options/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 subproject options/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 subproject options/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 subproject options/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +option('opt', type : 'boolean', value : true, description : 'main project option') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 subproject options/subprojects/subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 subproject options/subprojects/subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 subproject options/subprojects/subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 subproject options/subprojects/subproject/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +project('subproject', 'c') + +if get_option('opt') + error('option set when it should be unset.') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 subproject options/subprojects/subproject/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 subproject options/subprojects/subproject/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/43 subproject options/subprojects/subproject/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/43 subproject options/subprojects/subproject/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +option('opt', type : 'boolean', value : false, description : 'subproject option') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/answer.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/answer.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/answer.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/answer.c" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,3 @@ +int answer_to_life_the_universe_and_everything(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/custom.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/custom.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/custom.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/custom.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int custom_function(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/exposed.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/exposed.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/exposed.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/exposed.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int exposed_function(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/internal.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/internal.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/internal.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/internal.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int internal_function(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include + +#ifndef LIBFOO +#error LIBFOO should be defined in pkgconfig cflags +#endif + +int main(int argc, char *argv[]) +{ + return simple_function() == 42 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/dependencies/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/dependencies/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,62 @@ +project('pkgconfig-gen-dependencies', 'c', version: '1.0') + +pkgg = import('pkgconfig') + +# libmain internally use libinternal and expose libexpose in its API +exposed_lib = shared_library('libexposed', 'exposed.c') +internal_lib = shared_library('libinternal', 'internal.c') +main_lib = both_libraries('libmain', link_with : [exposed_lib, internal_lib]) +custom_lib = shared_library('custom', 'custom.c') + +pkgg.generate(exposed_lib) + +# Declare a few different Dependency objects +pc_dep = dependency('libfoo', version : '>=1.0') +pc_dep_dup = dependency('libfoo', version : '>= 1.0') +notfound_dep = dependency('notfound', required : false) +threads_dep = dependency('threads') +custom_dep = declare_dependency(link_with : custom_lib, compile_args : ['-DCUSTOM']) +custom2_dep = declare_dependency(link_args : ['-lcustom2'], compile_args : ['-DCUSTOM2']) + +exe = executable('test1', 'main.c', dependencies : [pc_dep]) +test('Test1', exe) + +# Generate a PC file: +# - Having libmain in libraries should pull implicitly libexposed and libinternal in Libs.private +# - Having libexposed in libraries should remove it from Libs.private +# - We generated a pc file for libexposed so it should be in Requires instead of Libs +# - Having threads_dep in libraries should add '-pthread' in both Libs and Cflags +# - Having custom_dep in libraries and libraries_private should only add it in Libs +# - Having custom2_dep in libraries_private should not add its Cflags +# - Having pc_dep in libraries_private should add it in Requires.private +# - pc_dep_dup is the same library and same version, should be ignored +# - notfound_dep is not required so it shouldn't appear in the pc file. +pkgg.generate(libraries : [main_lib, exposed_lib, threads_dep, threads_dep, custom_dep, custom_dep, '-pthread'], + libraries_private : [custom_dep, custom2_dep, custom2_dep, pc_dep, pc_dep_dup, notfound_dep], + version : '1.0', + name : 'dependency-test', + filebase : 'dependency-test', + description : 'A dependency test.' +) + +pkgg.generate( + name : 'requires-test', + version : '1.0', + description : 'Dependency Requires field test.', + requires : [exposed_lib, pc_dep, 'libhello'], +) + +pkgg.generate( + name : 'requires-private-test', + version : '1.0', + description : 'Dependency Requires.private field test.', + requires_private : [exposed_lib, pc_dep, 'libhello', notfound_dep], +) + +# Verify that if we promote internal_lib as public dependency, it comes after +# the main library. +main_lib2 = both_libraries('libmain2', link_with : internal_lib) +pkgg.generate(main_lib2, + libraries : internal_lib, + filebase : 'pub-lib-order', +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/foo.c" 2021-12-26 16:24:25.000000000 +0000 @@ -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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,151 @@ +project('pkgconfig-gen', 'c') + +# Some CI runners does not have zlib, just skip them as we need some common +# external dependency. +cc = meson.get_compiler('c') +if not cc.find_library('z', required: false).found() + error('MESON_SKIP_TEST: zlib missing') +endif + +# First check we have pkg-config >= 0.29 +pkgconfig = find_program('pkg-config', required: false) +if not pkgconfig.found() + error('MESON_SKIP_TEST: pkg-config not found') +endif + +v = run_command(pkgconfig, '--version', check: true).stdout().strip() +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') +libver = '1.0' +h = install_headers('simple.h') + +pkgg.generate( + libraries : [lib, '-lz'], + subdirs : '.', + version : libver, + name : 'libsimple', + filebase : 'simple', + description : 'A simple demo library.', + requires : 'glib-2.0', # Not really, but only here to test that this works. + requires_private : ['gio-2.0', 'gobject-2.0'], + libraries_private : [lib, '-lz'], +) + +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', 'foo.c', + link_with: answerlib, + name_prefix : '', + version : libver) + +pkgg.generate(lib2, + libraries : [lib2, answerlib], + name : 'libfoo', + version : libver, + description : 'A foo library.', + variables : ['foo=bar', 'datadir=${prefix}/data'], + extra_cflags : ['-DLIBFOO'], +) + +pkgg.generate( + name : 'libhello', + description : 'A minimalistic pkgconfig file.', + version : libver, +) + +pkgg.generate( + name : 'libhello_nolib', + description : 'A minimalistic pkgconfig file.', + version : libver, + dataonly: true, + variables : { + 'foo': 'bar', + # prefix is not set by default for dataonly pc files, but it is allowed to + # define it manually. + 'prefix': get_option('prefix'), + 'escaped_var': 'hello world', + }, + unescaped_variables: { + 'unescaped_var': 'hello world', + } +) + +# Regression test for 2 cases: +# - link_whole from InternalDependency used to be ignored, but we should still +# recurse to add libraries they link to. In this case it must add `-lsimple1` +# in generated pc file. +# - dependencies from InternalDependency used to be ignored. In this it must add +# `-lz` in generated pc file. +simple1 = shared_library('simple1', 'simple.c') +stat1 = static_library('stat1', 'simple.c', link_with: simple1) +dep = declare_dependency(link_whole: stat1, dependencies: cc.find_library('z')) +simple2 = library('simple2', 'simple.c') +pkgg.generate(simple2, libraries: dep) + +# Regression test: as_system() does a deepcopy() of the InternalDependency object +# which caused `-lsimple3` to be duplicated because generator used to compare +# Target instances instead of their id. +simple3 = shared_library('simple3', 'simple.c') +dep1 = declare_dependency(link_with: simple3) +dep2 = dep1.as_system() +pkgg.generate(libraries: [dep1, dep2], + name: 'simple3', + description: 'desc') + +# Regression test: stat2 is both link_with and link_whole, it should not appear +# in generated pc file. +stat2 = static_library('stat2', 'simple.c', install: true) +simple4 = library('simple4', 'simple.c', link_with: stat2) +simple5 = library('simple5', 'simple5.c', link_with: simple4, link_whole: stat2) +pkgg.generate(simple5) + +# Test passing a linkable CustomTarget and CustomTargetIndex to generator. +# Do this only with gcc/clang to not have to deal with other compiler command +# line specificities. +if cc.get_id() in ['gcc', 'clang'] + ct = custom_target('ct', + input: 'simple.c', + output: 'libct.so', + command: [cc.cmd_array(), '@INPUT@', '-shared', '-o', '@OUTPUT@'], + ) + pkgg.generate(libraries: ct, + name: 'ct', + description: 'custom target' + ) + pkgg.generate(libraries: ct[0], + name: 'ct0', + 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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/simple5.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/simple5.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/simple5.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/simple5.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int simple5(void); + +int simple5(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/simple.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/simple.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/simple.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/simple.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"simple.h" + +int simple_function(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/simple.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/simple.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/simple.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/simple.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef SIMPLE_H_ +#define SIMPLE_H_ + +int simple_function(void); + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 pkgconfig-gen/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 pkgconfig-gen/test.json" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,17 @@ +{ + "installed": [ + {"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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/cmd_args.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/cmd_args.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/cmd_args.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/cmd_args.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#include -#include - -int main(int argc, char **argv) { - if(argc != 3) { - fprintf(stderr, "Incorrect number of arguments.\n"); - return 1; - } - if(strcmp(argv[1], "first") != 0) { - fprintf(stderr, "First argument is wrong.\n"); - return 1; - } - if(strcmp(argv[2], "second") != 0) { - fprintf(stderr, "Second argument is wrong.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/copyfile.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import shutil - -shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/env2vars.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/env2vars.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/env2vars.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/env2vars.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -#include -#include -#include - -int main(void) { - if(strcmp(getenv("first"), "something-else") != 0) { - fprintf(stderr, "First envvar is wrong. %s\n", getenv("first")); - return 1; - } - if(strcmp(getenv("second"), "val2") != 0) { - fprintf(stderr, "Second envvar is wrong.\n"); - return 1; - } - if(strcmp(getenv("third"), "val3:and_more") != 0) { - fprintf(stderr, "Third envvar is wrong.\n"); - return 1; - } - if(strstr(getenv("PATH"), "fakepath:") != NULL) { - fprintf(stderr, "Third envvar is wrong.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/envvars.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/envvars.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/envvars.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/envvars.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -#include -#include -#include - -int main(void) { - if(strcmp(getenv("first"), "val1") != 0) { - fprintf(stderr, "First envvar is wrong. %s\n", getenv("first")); - return 1; - } - if(strcmp(getenv("second"), "val2") != 0) { - fprintf(stderr, "Second envvar is wrong.\n"); - return 1; - } - if(strcmp(getenv("third"), "val3:and_more") != 0) { - fprintf(stderr, "Third envvar is wrong.\n"); - return 1; - } - if(strstr(getenv("PATH"), "fakepath:") != NULL) { - fprintf(stderr, "Third envvar is wrong.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/meson.build" 2020-01-07 21:06:53.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -project('test features', 'c') - -e1 = executable('cmd_args', 'cmd_args.c') -e2 = executable('envvars', 'envvars.c') -e3 = executable('env2vars', 'env2vars.c') - -env = environment() -env.set('first', 'val1') -env.set('second', 'val2') -env.set('third', 'val3', 'and_more', separator: ':') -env.append('PATH', 'fakepath', separator: ':') - -# Make sure environment objects are copied on assignment and we can -# change the copy without affecting the original environment object. -env2 = env -env2.set('first', 'something-else') - -test('command line arguments', e1, args : ['first', 'second']) -test('environment variables', e2, env : env) -test('environment variables 2', e3, env : env2) - -# https://github.com/mesonbuild/meson/issues/2211#issuecomment-327741571 -env_array = ['MESONTESTING=picklerror'] -testfile = files('testfile.txt') -testerpy = find_program('tester.py') -test('file arg', testerpy, args : testfile, env : env_array) - -copy = find_program('copyfile.py') -tester = executable('tester', 'tester.c') -testfilect = custom_target('testfile', - input : testfile, - output : 'outfile.txt', - build_by_default : true, - command : [copy, '@INPUT@', '@OUTPUT@']) -test('custom target arg', tester, args : testfilect, env : env_array) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/tester.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/tester.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/tester.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/tester.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -#include -#include -#include -#include - -#ifndef _MSC_VER -#include -#endif - -int main(int argc, char **argv) { - char data[10]; - int fd, size; - - if (argc != 2) { - fprintf(stderr, "Incorrect number of arguments, got %i\n", argc); - return 1; - } - fd = open(argv[1], O_RDONLY); - if (fd < 0) { - fprintf(stderr, "First argument is wrong.\n"); - return 1; - } - - size = read(fd, data, 8); - if (size < 0) { - fprintf(stderr, "Failed to read: %s\n", strerror(errno)); - return 1; - } - if (strncmp(data, "contents", 8) != 0) { - fprintf(stderr, "Contents don't match, got %s\n", data); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/tester.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/tester.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/tester.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/tester.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -with open(sys.argv[1]) as f: - if f.read() != 'contents\n': - sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/testfile.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/testfile.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/44 test args/testfile.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/44 test args/testfile.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -contents diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/datafile.cat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/datafile.cat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/datafile.cat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/datafile.cat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Installed cat is installed. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/meson.build" 2021-10-23 16:48:16.000000000 +0000 @@ -0,0 +1,11 @@ +project('custom install dirs', 'c') +executable('prog', 'prog.c', install : true, install_dir : 'dib/dab/dub') +executable('prog2', 'prog.c', install : true, install_dir : get_option('prefix') + '/dib/dab/dub2') +install_headers('sample.h', install_dir : 'some/dir') +install_headers('sample.h', install_dir : get_option('prefix') + '/some/dir2') +install_man('prog.1', install_dir : 'woman') +install_man('prog.1', install_dir : get_option('prefix') + '/woman2') +install_data('datafile.cat', install_dir : 'meow') +install_data('datafile.cat', install_dir : get_option('prefix') + '/meow2') +install_subdir('subdir', install_dir : 'woof') +install_subdir('subdir', install_dir : get_option('prefix') + '/woof2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/prog.1" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/prog.1" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/prog.1" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/prog.1" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Man up, you. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/sample.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/sample.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/sample.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/sample.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef SAMPLE_H +#define SAMPLE_H + +int wackiness(); + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/subdir/datafile.dog" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/subdir/datafile.dog" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/subdir/datafile.dog" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/subdir/datafile.dog" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Installed dog is installed. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 custom install dirs/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 custom install dirs/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/dib/dab/dub/prog"}, + {"type": "pdb", "file": "usr/dib/dab/dub/prog"}, + {"type": "exe", "file": "usr/dib/dab/dub2/prog2"}, + {"type": "pdb", "file": "usr/dib/dab/dub2/prog2"}, + {"type": "file", "file": "usr/some/dir/sample.h"}, + {"type": "file", "file": "usr/some/dir2/sample.h"}, + {"type": "file", "file": "usr/woman/prog.1"}, + {"type": "file", "file": "usr/woman2/prog.1"}, + {"type": "file", "file": "usr/meow/datafile.cat"}, + {"type": "file", "file": "usr/meow2/datafile.cat"}, + {"type": "file", "file": "usr/woof/subdir/datafile.dog"}, + {"type": "file", "file": "usr/woof2/subdir/datafile.dog"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/bin/user?exe -?msvc:usr/bin/user.pdb -usr/share/sublib/sublib.depmf diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/meson.build" 2020-01-07 21:06:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -project('subproj user', 'c', - version : '2.3.4', - license : 'mylicense') - -assert(meson.project_name() == 'subproj user', 'Incorrect project name') - -sub = subproject('sublib', version : '1.0.0') - -if meson.project_version() != '2.3.4' - error('Incorrect master project version string:' + meson.project_version()) -endif - -if meson.is_subproject() - error('Claimed to be a subproject even though we are the master project.') -endif - -inc = sub.get_variable('i') -lib = sub.get_variable('l') - -e = executable('user', 'user.c', include_directories : inc, link_with : lib, install : true) -test('subdirtest', e) - -meson.install_dependency_manifest('share/sublib/sublib.depmf') - -unknown_var = sub.get_variable('does-not-exist', []) -if unknown_var != [] - error ('unexpetced fallback value for subproject.get_variable()') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/subprojects/sublib/include/subdefs.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/subprojects/sublib/include/subdefs.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/subprojects/sublib/include/subdefs.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/subprojects/sublib/include/subdefs.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#ifndef SUBDEFS_H_ -#define SUBDEFS_H_ - -#if defined _WIN32 || defined __CYGWIN__ -#if defined BUILDING_SUB - #define DLL_PUBLIC __declspec(dllexport) -#else - #define DLL_PUBLIC __declspec(dllimport) -#endif -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC subfunc(void); - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/subprojects/sublib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/subprojects/sublib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/subprojects/sublib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/subprojects/sublib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -project('subproject', 'c', - version : '1.0.0', - license : ['sublicense1', 'sublicense2']) - -if not meson.is_subproject() - error('Claimed to be master project even though we are a subproject.') -endif - -assert(meson.project_name() == 'subproject', 'Incorrect subproject name') - -if meson.project_version() != '1.0.0' - error('Incorrect version string in subproject.') -endif - -i = include_directories('include') -l = shared_library('sublib', 'sublib.c', include_directories : i, install : false, - c_args : '-DBUILDING_SUB=2') -t = executable('simpletest', 'simpletest.c', include_directories : i, link_with : l) -test('plain', t) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/subprojects/sublib/simpletest.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/subprojects/sublib/simpletest.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/subprojects/sublib/simpletest.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/subprojects/sublib/simpletest.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -int main(void) { - return subfunc() == 42 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/subprojects/sublib/sublib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/subprojects/sublib/sublib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/subprojects/sublib/sublib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/subprojects/sublib/sublib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -int DLL_PUBLIC subfunc(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/user.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/user.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/45 subproject/user.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/45 subproject/user.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#include -#include - - -int main(void) { - int res; - printf("Calling into sublib now.\n"); - res = subfunc(); - if(res == 42) { - printf("Everything is fine.\n"); - return 0; - } else { - printf("Something went wrong.\n"); - return 1; - } -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject options/meson.build" 2020-01-07 21:06:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject options/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('suboptions', 'c') - -subproject('subproject') - -if not get_option('opt') - error('option unset when it should be set') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject options/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject options/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject options/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject options/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -option('opt', type : 'boolean', value : true, description : 'main project option') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject options/subprojects/subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject options/subprojects/subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject options/subprojects/subproject/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject options/subprojects/subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('subproject', 'c') - -if get_option('opt') - error('option set when it should be unset.') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject options/subprojects/subproject/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject options/subprojects/subproject/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject options/subprojects/subproject/meson_options.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject options/subprojects/subproject/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -option('opt', type : 'boolean', value : false, description : 'subproject option') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/meson.build" 2021-10-23 16:48:21.000000000 +0000 @@ -0,0 +1,11 @@ +project('sub sub', 'c') + +a = subproject('a') +lib = a.get_variable('l') + +dependency('not-found-dep', required : false, + version : '>=1', + fallback : ['c', 'notfound_dep']) + +exe = executable('prog', 'prog.c', link_with : lib) +test('basic', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int func(void); + +int main(void) { + return func() == 42 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/a/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/a/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/a/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/a/a.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,14 @@ +int func2(void); + +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC func(void) { return func2(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/a/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('a', 'c') + +b = subproject('b') +l = shared_library('a', 'a.c', link_with : b.get_variable('lb')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/b/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/b/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/b/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/b/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +int DLL_PUBLIC func2(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/b/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/b/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/b/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/b/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('b', 'c') + +lb = shared_library('b', 'b.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/c/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/c/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/46 subproject subproject/subprojects/c/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/46 subproject subproject/subprojects/c/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('not-found-dep-subproj', 'c', version : '1.0') + +notfound_dep = dependency('', required : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/dependencies/custom.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/dependencies/custom.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/dependencies/custom.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/dependencies/custom.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int custom_function(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/dependencies/exposed.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/dependencies/exposed.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/dependencies/exposed.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/dependencies/exposed.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int exposed_function(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/dependencies/internal.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/dependencies/internal.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/dependencies/internal.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/dependencies/internal.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int internal_function(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/dependencies/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/dependencies/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/dependencies/meson.build" 2019-09-28 23:52:33.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/dependencies/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -project('pkgconfig-gen-dependencies', 'c', version: '1.0') - -pkgg = import('pkgconfig') - -# libmain internally use libinternal and expose libexpose in its API -exposed_lib = shared_library('libexposed', 'exposed.c') -internal_lib = shared_library('libinternal', 'internal.c') -main_lib = both_libraries('libmain', link_with : [exposed_lib, internal_lib]) -custom_lib = shared_library('custom', 'custom.c') - -pkgg.generate(exposed_lib) - -# Declare a few different Dependency objects -pc_dep = dependency('libfoo', version : '>=1.0') -pc_dep_dup = dependency('libfoo', version : '>= 1.0') -notfound_dep = dependency('notfound', required : false) -threads_dep = dependency('threads') -custom_dep = declare_dependency(link_with : custom_lib, compile_args : ['-DCUSTOM']) -custom2_dep = declare_dependency(link_args : ['-lcustom2'], compile_args : ['-DCUSTOM2']) - -# Generate a PC file: -# - Having libmain in libraries should pull implicitly libexposed and libinternal in Libs.private -# - Having libexposed in libraries should remove it from Libs.private -# - We generated a pc file for libexposed so it should be in Requires instead of Libs -# - Having threads_dep in libraries should add '-pthread' in both Libs and Cflags -# - Having custom_dep in libraries and libraries_private should only add it in Libs -# - Having custom2_dep in libraries_private should not add its Cflags -# - Having pc_dep in libraries_private should add it in Requires.private -# - pc_dep_dup is the same library and same version, should be ignored -# - notfound_dep is not required so it shouldn't appear in the pc file. -pkgg.generate(libraries : [main_lib, exposed_lib, threads_dep, threads_dep, custom_dep, custom_dep, '-pthread'], - libraries_private : [custom_dep, custom2_dep, custom2_dep, pc_dep, pc_dep_dup, notfound_dep], - version : '1.0', - name : 'dependency-test', - filebase : 'dependency-test', - description : 'A dependency test.' -) - -pkgg.generate( - name : 'requires-test', - version : '1.0', - description : 'Dependency Requires field test.', - requires : [exposed_lib, pc_dep, 'libhello'], -) - -pkgg.generate( - name : 'requires-private-test', - version : '1.0', - description : 'Dependency Requires.private field test.', - requires_private : [exposed_lib, pc_dep, 'libhello', notfound_dep], -) - -# Verify that if we promote internal_lib as public dependency, it comes after -# the main library. -main_lib2 = both_libraries('libmain2', link_with : internal_lib) -pkgg.generate(main_lib2, - libraries : internal_lib, - filebase : 'pub-lib-order', -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -usr/include/simple.h -usr/lib/pkgconfig/simple.pc -usr/lib/pkgconfig/libfoo.pc -usr/lib/pkgconfig/libhello.pc diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/meson.build" 2020-01-07 21:06:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -project('pkgconfig-gen', 'c') - -# First check we have pkg-config >= 0.29 - -pkgconfig = find_program('pkg-config', required: false) -if not pkgconfig.found() - error('MESON_SKIP_TEST: pkg-config not found') -endif - -v = run_command(pkgconfig, '--version').stdout().strip() -if v.version_compare('<0.29') - error('MESON_SKIP_TEST: pkg-config version \'' + v + '\' too old') -endif - -pkgg = import('pkgconfig') - -lib = shared_library('simple', 'simple.c') -libver = '1.0' -h = install_headers('simple.h') - -pkgg.generate( - libraries : [lib, '-lz'], - subdirs : '.', - version : libver, - name : 'libsimple', - filebase : 'simple', - description : 'A simple demo library.', - requires : 'glib-2.0', # Not really, but only here to test that this works. - requires_private : ['gio-2.0', 'gobject-2.0'], - libraries_private : [lib, '-lz'], -) - -test('pkgconfig-validation', pkgconfig, - args: ['--validate', 'simple'], - env: [ 'PKG_CONFIG_PATH=' + meson.current_build_dir() + '/meson-private' ]) - -# Test that name_prefix='' and name='libfoo' results in '-lfoo' -lib2 = shared_library('libfoo', 'simple.c', - name_prefix : '', - version : libver) - -pkgg.generate( - libraries : lib2, - name : 'libfoo', - version : libver, - description : 'A foo library.', - variables : ['foo=bar', 'datadir=${prefix}/data'] -) - -pkgg.generate( - name : 'libhello', - description : 'A minimalistic pkgconfig file.', - version : libver, -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/simple.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/simple.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/simple.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/simple.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"simple.h" - -int simple_function(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/simple.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/simple.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 pkgconfig-gen/simple.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 pkgconfig-gen/simple.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef SIMPLE_H_ -#define SIMPLE_H_ - -int simple_function(void); - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 same file name/d1/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 same file name/d1/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 same file name/d1/file.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 same file name/d1/file.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int func1(void) { return 42; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 same file name/d2/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 same file name/d2/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 same file name/d2/file.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 same file name/d2/file.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int func2(void) { return 42; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 same file name/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 same file name/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 same file name/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 same file name/meson.build" 2021-10-23 16:48:18.000000000 +0000 @@ -0,0 +1,3 @@ +project('samefile', 'c') + +test('basic', executable('prog', 'prog.c', 'd1/file.c', 'd2/file.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 same file name/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 same file name/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/47 same file name/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/47 same file name/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func1(void); +int func2(void); + +int main(void) { + return func1() - func2(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/datafile.cat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/datafile.cat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/datafile.cat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/datafile.cat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Installed cat is installed. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -usr/dib/dab/dub/prog?exe -?msvc:usr/dib/dab/dub/prog.pdb -usr/dib/dab/dub2/prog2?exe -?msvc:usr/dib/dab/dub2/prog2.pdb -usr/some/dir/sample.h -usr/some/dir2/sample.h -usr/woman/prog.1 -usr/woman2/prog.1 -usr/meow/datafile.cat -usr/meow2/datafile.cat -usr/woof/subdir/datafile.dog -usr/woof2/subdir/datafile.dog diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/meson.build" 2020-01-07 21:06:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('custom install dirs', 'c') -executable('prog', 'prog.c', install : true, install_dir : 'dib/dab/dub') -executable('prog2', 'prog.c', install : true, install_dir : get_option('prefix') + '/dib/dab/dub2') -install_headers('sample.h', install_dir : 'some/dir') -install_headers('sample.h', install_dir : get_option('prefix') + '/some/dir2') -install_man('prog.1', install_dir : 'woman') -install_man('prog.1', install_dir : get_option('prefix') + '/woman2') -install_data('datafile.cat', install_dir : 'meow') -install_data('datafile.cat', install_dir : get_option('prefix') + '/meow2') -install_subdir('subdir', install_dir : 'woof') -install_subdir('subdir', install_dir : get_option('prefix') + '/woof2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/prog.1" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/prog.1" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/prog.1" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/prog.1" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Man up, you. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/sample.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/sample.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/sample.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/sample.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#ifndef SAMPLE_H -#define SAMPLE_H - -int wackiness(); - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/subdir/datafile.dog" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/subdir/datafile.dog" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 custom install dirs/subdir/datafile.dog" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 custom install dirs/subdir/datafile.dog" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Installed dog is installed. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/a.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int funca(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int funcb(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/c.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/c.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int funcc(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/grabber2.bat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/grabber2.bat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/grabber2.bat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/grabber2.bat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +@ECHO OFF +echo suba.c +echo subb.c +echo subc.c +echo subprog.c diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/grabber.bat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/grabber.bat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/grabber.bat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/grabber.bat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +@ECHO OFF +echo a.c +echo b.c +echo c.c +echo prog.c diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/grabber.sh" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/grabber.sh" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/grabber.sh" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/grabber.sh" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#!/bin/sh + +for i in *.c; do + echo $i +done diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,35 @@ +project('grabber', 'c') + +# What this script does is NOT reliable. Simply adding a file in this directory +# will NOT make it automatically appear in the build. You have to manually +# re-invoke Meson (not just Ninja) for that to happen. The simplest way +# is to touch meson-private/coredata.dat. + +# This is not the recommended way to do things, but if the tradeoffs are +# acceptable to you, then we're certainly not going to stop you. Just don't +# file bugs when it fails. :) + +if build_machine.system() == 'windows' + c = run_command('grabber.bat', check: false) + grabber = find_program('grabber2.bat') +else + c = run_command('grabber.sh', check: false) + grabber = find_program('grabber.sh') +endif + + +# First test running command explicitly. +if c.returncode() != 0 + error('Executing script failed.') +endif + +newline = ''' +''' + +sources = c.stdout().strip().split(newline) + +e = executable('prog', sources) +test('grabtest', e) + +# Then test using program with find_program +subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +int funca(void); +int funcb(void); +int funcc(void); + +int main(void) { + return funca() + funcb() + funcc(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,5 @@ +sc = run_command(grabber, check: true) +subsources = sc.stdout().strip().split(newline) + +se = executable('subprog', subsources) +test('subgrabtest', se) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/suba.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/suba.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/suba.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/suba.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int funca(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/subb.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/subb.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/subb.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/subb.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int funcb(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/subc.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/subc.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/subc.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/subc.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int funcc(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/subprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/subprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/48 file grabber/subdir/subprog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/48 file grabber/subdir/subprog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +int funca(void); +int funcb(void); +int funcc(void); + +int main(void) { + return funca() + funcb() + funcc(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/data_source.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/depfile/dep.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/depfile/dep.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/depfile/dep.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/depfile/dep.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import sys, os +from glob import glob + +_, srcdir, depfile, output = sys.argv + +depfiles = glob(os.path.join(srcdir, '*')) + +quoted_depfiles = [x.replace(' ', r'\ ') for x in depfiles] + +with open(output, 'w') as f: + f.write('I am the result of globbing.') +with open(depfile, 'w') as f: + f.write('{}: {}\n'.format(output, ' '.join(quoted_depfiles))) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/depfile/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/depfile/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/depfile/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/depfile/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ + + +mytarget = custom_target('depfile', + output : 'dep.dat', + depfile : 'dep.dat.d', + command : [find_program('dep.py'), meson.current_source_dir(), '@DEPFILE@', '@OUTPUT@'], +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,73 @@ +project('custom target', 'c') + +python = find_program('python3', required : false) +if not python.found() + python = find_program('python') +endif + +# Note that this will not add a dependency to the compiler executable. +# Code will not be rebuilt if it changes. +comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') +# Test that files() in command: works. The compiler just discards it. +useless = files('test.json') + +mytarget = custom_target('bindat', +output : 'data.dat', +input : 'data_source.txt', +command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', useless], +env: {'MY_COMPILER_ENV': 'value'}, +install : true, +install_dir : 'subdir' +) + +has_not_changed = false +if is_disabler(mytarget) + has_not_changed = true +else + has_not_changed = true +endif +assert(has_not_changed, 'Custom target has changed.') + +assert(not is_disabler(mytarget), 'Custom target is a disabler.') + +mytarget_disabler = custom_target('bindat', +output : 'data.dat', +input : 'data_source.txt', +command : [disabler(), comp, '--input=@INPUT@', '--output=@OUTPUT@', useless], +install : true, +install_dir : 'subdir' +) + +if mytarget_disabler.found() + mytarget_disabled = false +else + mytarget_disabled = true +endif + +assert(mytarget_disabled, 'Disabled custom target should not be found.') + +mytarget_ci = custom_target('bindat_ci', +output : 'data_ci.dat', +input : 'data_source.txt', +command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', mytarget.to_list()], +) + +mytarget_disabler = custom_target('bindat', +output : 'data.dat', +input : disabler(), +command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', useless], +install : true, +install_dir : 'subdir' +) + +assert(is_disabler(mytarget_disabler), 'Disabled custom target is not a disabler.') + +if mytarget_disabler.found() + mytarget_disabled = false +else + mytarget_disabled = true +endif + +assert(mytarget_disabled, 'Disabled custom target should not be found.') + +subdir('depfile') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/my_compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/my_compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/my_compiler.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/my_compiler.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +import os +import sys + +assert os.path.exists(sys.argv[3]) + +args = sys.argv[:-1] + +if __name__ == '__main__': + assert os.environ['MY_COMPILER_ENV'] == 'value' + if len(args) != 3 or not args[1].startswith('--input') or \ + not args[2].startswith('--output'): + print(args[0], '--input=input_file --output=output_file') + sys.exit(1) + with open(args[1].split('=')[1]) as f: + ifile = f.read() + if ifile != 'This is a text only input file.\n': + print('Malformed input') + sys.exit(1) + with open(args[2].split('=')[1], 'w') as ofile: + ofile.write('This is a binary output file.\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 custom target/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 custom target/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/subdir/data.dat"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/meson.build" 2020-01-07 21:07:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('sub sub', 'c') - -a = subproject('a') -lib = a.get_variable('l') - -dependency('not-found-dep', required : false, - version : '>=1', - fallback : ['c', 'notfound_dep']) - -exe = executable('prog', 'prog.c', link_with : lib) -test('basic', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int func(void); - -int main(void) { - return func() == 42 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/a/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/a/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/a/a.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/a/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -int func2(void); - -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC func(void) { return func2(); } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/a/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('a', 'c') - -b = subproject('b') -l = shared_library('a', 'a.c', link_with : b.get_variable('lb')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/b/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/b/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/b/b.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/b/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -int DLL_PUBLIC func2(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/b/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/b/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/b/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/b/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('b', 'c') - -lb = shared_library('b', 'b.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/c/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/c/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/49 subproject subproject/subprojects/c/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/49 subproject subproject/subprojects/c/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('not-found-dep-subproj', 'c', version : '1.0') - -notfound_dep = dependency('', required : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/data_source.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/meson.build" 2021-10-23 16:48:20.000000000 +0000 @@ -0,0 +1,34 @@ +project('custom target', 'c') + +python = find_program('python3', required : false) +if not python.found() + python = find_program('python') +endif + +# files() is the correct way to do this, but some people +# do this so test that it works. +comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') +comp2 = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler2.py') +infile = files('data_source.txt')[0] + +mytarget = custom_target('bindat', + output : 'data.dat', + command : [python, comp, infile, '@OUTPUT@'], +) + +mytarget2 = custom_target('bindat2', + output : 'data2.dat', + command : [python, comp2, mytarget, '@OUTPUT@'], + install : true, + install_dir : 'subdir' +) + +mytarget3 = custom_target('bindat3', + output : 'data3.dat', + input : [mytarget], + command : [python, comp2, '@INPUT@', '@OUTPUT@'], + install : true, + install_dir : 'subdir' +) + +subdir('usetarget') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/my_compiler2.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/my_compiler2.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/my_compiler2.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/my_compiler2.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import sys + +if __name__ == '__main__': + if len(sys.argv) != 3: + print(sys.argv[0], 'input_file output_file') + sys.exit(1) + with open(sys.argv[1]) as f: + ifile = f.read() + if ifile != 'This is a binary output file.\n': + print('Malformed input') + sys.exit(1) + with open(sys.argv[2], 'w') as ofile: + ofile.write('This is a different binary output file.\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/my_compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/my_compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/my_compiler.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/my_compiler.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import sys + +if __name__ == '__main__': + if len(sys.argv) != 3: + print(sys.argv[0], 'input_file output_file') + sys.exit(1) + with open(sys.argv[1]) as f: + ifile = f.read() + if ifile != 'This is a text only input file.\n': + print('Malformed input') + sys.exit(1) + with open(sys.argv[2], 'w') as ofile: + ofile.write('This is a binary output file.\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "file", "file": "usr/subdir/data2.dat"}, + {"type": "file", "file": "usr/subdir/data3.dat"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/usetarget/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/usetarget/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/usetarget/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/usetarget/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +e = executable('myexe', 'myexe.c') +subexe = find_program('subcomp.py') + +custom_target('use_exe', + input : e, + output : 'subout.res', + command : [subexe, '@INPUT@', '@OUTPUT@'], +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/usetarget/myexe.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/usetarget/myexe.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/usetarget/myexe.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/usetarget/myexe.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I am myexe.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/usetarget/subcomp.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/usetarget/subcomp.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 custom target chain/usetarget/subcomp.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 custom target chain/usetarget/subcomp.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys + +with open(sys.argv[1], 'rb') as ifile: + with open(sys.argv[2], 'w') as ofile: + ofile.write('Everything ok.\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 same file name/d1/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 same file name/d1/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 same file name/d1/file.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 same file name/d1/file.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int func1(void) { return 42; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 same file name/d2/file.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 same file name/d2/file.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 same file name/d2/file.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 same file name/d2/file.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int func2(void) { return 42; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 same file name/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 same file name/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 same file name/meson.build" 2020-01-07 21:06:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 same file name/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('samefile', 'c') - -test('basic', executable('prog', 'prog.c', 'd1/file.c', 'd2/file.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 same file name/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 same file name/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/50 same file name/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/50 same file name/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func1(void); -int func2(void); - -int main(void) { - return func1() - func2(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/a.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int funca(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/b.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int funcb(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/c.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/c.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int funcc(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/grabber2.bat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/grabber2.bat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/grabber2.bat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/grabber2.bat" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -@ECHO OFF -echo suba.c -echo subb.c -echo subc.c -echo subprog.c diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/grabber.bat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/grabber.bat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/grabber.bat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/grabber.bat" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -@ECHO OFF -echo a.c -echo b.c -echo c.c -echo prog.c diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/grabber.sh" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/grabber.sh" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/grabber.sh" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/grabber.sh" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#!/bin/sh - -for i in *.c; do - echo $i -done diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/meson.build" 2020-01-07 21:06:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -project('grabber', 'c') - -# What this script does is NOT reliable. Simply adding a file in this directory -# will NOT make it automatically appear in the build. You have to manually -# re-invoke Meson (not just Ninja) for that to happen. The simplest way -# is to touch meson-private/coredata.dat. - -# This is not the recommended way to do things, but if the tradeoffs are -# acceptable to you, then we're certainly not going to stop you. Just don't -# file bugs when it fails. :) - -if build_machine.system() == 'windows' - c = run_command('grabber.bat') - grabber = find_program('grabber2.bat') -else - c = run_command('grabber.sh') - grabber = find_program('grabber.sh') -endif - - -# First test running command explicitly. -if c.returncode() != 0 - error('Executing script failed.') -endif - -newline = ''' -''' - -sources = c.stdout().strip().split(newline) - -e = executable('prog', sources) -test('grabtest', e) - -# Then test using program with find_program -subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -int funca(void); -int funcb(void); -int funcc(void); - -int main(void) { - return funca() + funcb() + funcc(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -sc = run_command(grabber) -subsources = sc.stdout().strip().split(newline) - -se = executable('subprog', subsources) -test('subgrabtest', se) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/suba.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/suba.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/suba.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/suba.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int funca(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/subb.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/subb.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/subb.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/subb.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int funcb(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/subc.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/subc.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/subc.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/subc.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int funcc(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/subprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/subprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 file grabber/subdir/subprog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 file grabber/subdir/subprog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -int funca(void); -int funcb(void); -int funcc(void); - -int main(void) { - return funca() + funcb() + funcc(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/check-env.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/check-env.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/check-env.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/check-env.py" 2021-11-02 19:58:13.000000000 +0000 @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import os, sys +from pathlib import Path + +assert 'MESON_SOURCE_ROOT' in os.environ +assert 'MESON_BUILD_ROOT' in os.environ +assert 'MESON_SUBDIR' in os.environ +assert 'MESONINTROSPECT' in os.environ +assert 'MY_ENV' in os.environ + +# Environment has absolute paths and argv has relative paths when using ninja +# backend and absolute paths when using vs backend. What matters is once +# resolved they point to same location. +env_source_root = Path(os.environ['MESON_SOURCE_ROOT']).resolve() +env_build_root = Path(os.environ['MESON_BUILD_ROOT']).resolve() +env_current_source_dir = Path(env_source_root, os.environ['MESON_SUBDIR']).resolve() + +print(sys.argv) +argv_paths = [Path(i).resolve() for i in sys.argv[1:]] +source_root, build_root, current_source_dir = argv_paths + +print(f'{source_root} == {env_source_root}') +assert source_root == env_source_root +print(f'{build_root} == {env_build_root}') +assert build_root == env_build_root +print(f'{current_source_dir} == {env_current_source_dir}') +assert current_source_dir == env_current_source_dir diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/check_exists.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/check_exists.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/check_exists.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/check_exists.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import os +import sys + +if not os.path.isfile(sys.argv[1]): + raise Exception("Couldn't find {!r}".format(sys.argv[1])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/configure.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/configure.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/configure.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/configure.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('Success') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/converter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/converter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/converter.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/converter.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys + +with open(sys.argv[1], 'rb') as ifile, open(sys.argv[2], 'wb') as ofile: + ofile.write(ifile.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/fakeburner.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/fakeburner.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/fakeburner.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/fakeburner.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + + +import sys + +plain_arg = sys.argv[1] +_, filename, _ = plain_arg.split(':') +try: + with open(filename, 'rb') as f: + content = f.read() +except FileNotFoundError: + print('Could not open file. Missing dependency?') + sys.exit(1) +print('File opened, pretending to send it somewhere.') +print(len(content), 'bytes uploaded') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/helloprinter.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/helloprinter.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/helloprinter.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/helloprinter.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include + +int main(int argc, char **argv) { + if(argc != 2) { + printf("I can not haz argument.\n"); + return 1; + } else { + printf("I can haz argument: %s\n", argv[1]); + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/meson.build" 2021-10-23 16:48:21.000000000 +0000 @@ -0,0 +1,107 @@ +project('run target', 'c') + +# Make it possible to run built programs. +# In cross builds exe_wrapper should be added if it exists. + +exe = executable('helloprinter', 'helloprinter.c') + +if not meson.is_cross_build() or meson.can_run_host_binaries() + run_target('runhello', + command : [exe, 'argument']) +endif + +converter = find_program('converter.py') + +hex = custom_target('exe.hex', + input : exe, + output : 'exe.hex', + command : [converter, '@INPUT@', '@OUTPUT@', + ], +) + +fakeburner = find_program('fakeburner.py') + +# These emulates the Arduino flasher application. It sandwiches the filename inside +# a packed argument. Thus we need to declare it manually. +run_target('upload', + command : [fakeburner, 'x:@0@:y'.format(exe.full_path())], + depends : exe, +) + +run_target('upload2', + command : [fakeburner, 'x:@0@:y'.format(hex.full_path())], + depends : hex, +) + +python3 = find_program('python3', required : false) +if not python3.found() + python3 = find_program('python') +endif + +run_target('py3hi', + command : [python3, '-c', 'print("I am Python3.")']) + +run_target('check_exists', + command : [find_program('check_exists.py'), files('helloprinter.c')]) + +run_target('check_exists', + command : [find_program('check_exists.py'), files('helloprinter.c')], + depends : disabler(), +) + +run_target('check_exists', + command : [disabler(), files('helloprinter.c')]) + +# What if the output of a custom_target is the command to +# execute. Obviously this will not work as hex is not an +# executable but test that the output is generated correctly. +run_target('donotrunme', + command : hex) + +# Ensure configure files can be passed +conf = configure_file( + input: 'configure.in', + output: 'configure', + configuration: configuration_data() +) + +run_target('configure_script', + command : conf +) + +custom_target('configure_script_ct', + command: conf, + output: 'dummy.txt', + capture: true) + +# Target names that clash with potential builtin functionality. +run_target('ctags', + command : converter) + +run_target('clang-format', + command : converter) + +# Check we can pass env to the program. Also check some string substitutions +# that were added in 0.57.0 but not documented. This is documented behaviour +# since 0.57.1. +run_target('check-env', + command: [find_program('check-env.py'), '@SOURCE_ROOT@', '@BUILD_ROOT@', + '@CURRENT_SOURCE_DIR@'], + env: {'MY_ENV': '1'}, +) + +# Check some string substitutions that has always been done but never documented. +# Some projects have been relying on this implementation detail. This is +# documented behaviour since 0.57.1. +custom_target('check-env-ct', + command: [find_program('check-env.py'), '@SOURCE_ROOT@', '@BUILD_ROOT@', + '@CURRENT_SOURCE_DIR@'], + env: {'MESON_SOURCE_ROOT': meson.source_root(), + 'MESON_BUILD_ROOT': meson.build_root(), + 'MESON_SUBDIR': meson.current_source_dir(), + 'MESONINTROSPECT': 'fake value', + 'MY_ENV': '1'}, + output: 'check-env-ct', +) + +run_target('textprinter', command: ['subdir/textprinter.py']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/subdir/textprinter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/subdir/textprinter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/51 run target/subdir/textprinter.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/51 run target/subdir/textprinter.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('I am a script. Being run.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/data_source.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/depfile/dep.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/depfile/dep.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/depfile/dep.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/depfile/dep.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os -from glob import glob - -_, srcdir, depfile, output = sys.argv - -depfiles = glob(os.path.join(srcdir, '*')) - -quoted_depfiles = [x.replace(' ', r'\ ') for x in depfiles] - -with open(output, 'w') as f: - f.write('I am the result of globbing.') -with open(depfile, 'w') as f: - f.write('%s: %s\n' % (output, ' '.join(quoted_depfiles))) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/depfile/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/depfile/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/depfile/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/depfile/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ - - -mytarget = custom_target('depfile', - output : 'dep.dat', - depfile : 'dep.dat.d', - command : [find_program('dep.py'), meson.current_source_dir(), '@DEPFILE@', '@OUTPUT@'], -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/subdir/data.dat diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/meson.build" 2020-01-07 21:07:01.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -project('custom target', 'c') - -python = find_program('python3', required : false) -if not python.found() - python = find_program('python') -endif - -# Note that this will not add a dependency to the compiler executable. -# Code will not be rebuilt if it changes. -comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') -# Test that files() in command: works. The compiler just discards it. -useless = files('installed_files.txt') - -mytarget = custom_target('bindat', -output : 'data.dat', -input : 'data_source.txt', -command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', useless], -install : true, -install_dir : 'subdir' -) - -has_not_changed = false -if is_disabler(mytarget) - has_not_changed = true -else - has_not_changed = true -endif -assert(has_not_changed, 'Custom target has changed.') - -assert(not is_disabler(mytarget), 'Custom target is a disabler.') - -mytarget_disabler = custom_target('bindat', -output : 'data.dat', -input : 'data_source.txt', -command : [disabler(), comp, '--input=@INPUT@', '--output=@OUTPUT@', useless], -install : true, -install_dir : 'subdir' -) - -if mytarget_disabler.found() - mytarget_disabled = false -else - mytarget_disabled = true -endif - -assert(mytarget_disabled, 'Disabled custom target should not be found.') - -mytarget_disabler = custom_target('bindat', -output : 'data.dat', -input : disabler(), -command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', useless], -install : true, -install_dir : 'subdir' -) - -assert(is_disabler(mytarget_disabler), 'Disabled custom target is not a disabler.') - -if mytarget_disabler.found() - mytarget_disabled = false -else - mytarget_disabled = true -endif - -assert(mytarget_disabled, 'Disabled custom target should not be found.') - -subdir('depfile') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/my_compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/my_compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 custom target/my_compiler.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 custom target/my_compiler.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -assert(os.path.exists(sys.argv[3])) - -args = sys.argv[:-1] - -if __name__ == '__main__': - if len(args) != 3 or not args[1].startswith('--input') or \ - not args[2].startswith('--output'): - print(args[0], '--input=input_file --output=output_file') - sys.exit(1) - with open(args[1].split('=')[1]) as f: - ifile = f.read() - if ifile != 'This is a text only input file.\n': - print('Malformed input') - sys.exit(1) - with open(args[2].split('=')[1], 'w') as ofile: - ofile.write('This is a binary output file.\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/meson.build" 2021-10-23 16:48:22.000000000 +0000 @@ -0,0 +1,34 @@ +project('object generator', 'c') + +python = find_program('python3', required : false) +if not python.found() + python = find_program('python') +endif + +# Note that this will not add a dependency to the compiler executable. +# Code will not be rebuilt if it changes. +comp = '@0@/@1@'.format(meson.current_source_dir(), 'obj_generator.py') + +if host_machine.system() == 'windows' + outputname = '@BASENAME@.obj' +else + outputname = '@BASENAME@.o' +endif + +cc = meson.get_compiler('c').cmd_array().get(-1) +# Generate an object file manually. +gen = generator(python, + output : outputname, + arguments : [comp, cc, '@INPUT@', '@OUTPUT@']) + +generated = gen.process(['source.c', 'source2.c']) + +# Generate an object file with indexed OUTPUT replacement. +gen2 = generator(python, + output : outputname, + arguments : [comp, cc, '@INPUT@', '@OUTPUT0@']) +generated2 = gen2.process(['source3.c']) + +e = executable('prog', 'prog.c', generated, generated2) + +test('objgen', e) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/obj_generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/obj_generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/obj_generator.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/obj_generator.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# Mimic a binary that generates an object file (e.g. windres). + +import sys, subprocess + +if __name__ == '__main__': + if len(sys.argv) != 4: + print(sys.argv[0], 'compiler input_file output_file') + sys.exit(1) + compiler = sys.argv[1] + ifile = sys.argv[2] + ofile = sys.argv[3] + if compiler.endswith('cl'): + cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] + else: + cmd = [compiler, '-c', ifile, '-o', ofile] + sys.exit(subprocess.call(cmd)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +int func1_in_obj(void); +int func2_in_obj(void); +int func3_in_obj(void); + +int main(void) { + return func1_in_obj() + func2_in_obj() + func3_in_obj(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/source2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/source2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/source2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/source2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func2_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/source3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/source3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/source3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/source3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func3_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/52 object generator/source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/52 object generator/source.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func1_in_obj(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/data_source.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/data_source.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/data_source.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/data_source.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a text only input file. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/subdir/data2.dat -usr/subdir/data3.dat diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/meson.build" 2020-01-07 21:07:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -project('custom target', 'c') - -python = find_program('python3', required : false) -if not python.found() - python = find_program('python') -endif - -# files() is the correct way to do this, but some people -# do this so test that it works. -comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') -comp2 = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler2.py') -infile = files('data_source.txt')[0] - -mytarget = custom_target('bindat', - output : 'data.dat', - command : [python, comp, infile, '@OUTPUT@'], -) - -mytarget2 = custom_target('bindat2', - output : 'data2.dat', - command : [python, comp2, mytarget, '@OUTPUT@'], - install : true, - install_dir : 'subdir' -) - -mytarget3 = custom_target('bindat3', - output : 'data3.dat', - input : [mytarget], - command : [python, comp2, '@INPUT@', '@OUTPUT@'], - install : true, - install_dir : 'subdir' -) - -subdir('usetarget') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/my_compiler2.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/my_compiler2.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/my_compiler2.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/my_compiler2.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -if __name__ == '__main__': - if len(sys.argv) != 3: - print(sys.argv[0], 'input_file output_file') - sys.exit(1) - with open(sys.argv[1]) as f: - ifile = f.read() - if ifile != 'This is a binary output file.\n': - print('Malformed input') - sys.exit(1) - with open(sys.argv[2], 'w') as ofile: - ofile.write('This is a different binary output file.\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/my_compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/my_compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/my_compiler.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/my_compiler.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -if __name__ == '__main__': - if len(sys.argv) != 3: - print(sys.argv[0], 'input_file output_file') - sys.exit(1) - with open(sys.argv[1]) as f: - ifile = f.read() - if ifile != 'This is a text only input file.\n': - print('Malformed input') - sys.exit(1) - with open(sys.argv[2], 'w') as ofile: - ofile.write('This is a binary output file.\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/usetarget/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/usetarget/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/usetarget/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/usetarget/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -e = executable('myexe', 'myexe.c') -subexe = find_program('subcomp.py') - -custom_target('use_exe', - input : e, - output : 'subout.res', - command : [subexe, '@INPUT@', '@OUTPUT@'], -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/usetarget/myexe.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/usetarget/myexe.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/usetarget/myexe.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/usetarget/myexe.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I am myexe.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/usetarget/subcomp.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/usetarget/subcomp.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 custom target chain/usetarget/subcomp.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 custom target chain/usetarget/subcomp.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -with open(sys.argv[1], 'rb') as ifile: - with open(sys.argv[2], 'w') as ofile: - ofile.write('Everything ok.\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/customtarget.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/customtarget.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/customtarget.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/customtarget.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +import argparse +import os + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('dirname') + args = parser.parse_args() + + with open(os.path.join(args.dirname, '1.txt'), 'w') as f: + f.write('') + with open(os.path.join(args.dirname, '2.txt'), 'w') as f: + f.write('') + + +if __name__ == "__main__": + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/meson.build" 2021-10-23 16:48:24.000000000 +0000 @@ -0,0 +1,45 @@ +project('custom install script', 'c') + +meson.add_install_script('myinstall.py', 'diiba/daaba', 'file.dat') +meson.add_install_script('myinstall.py', 'this/should', 'also-work.dat') + +subdir('src') + +meson.add_install_script('myinstall.py', 'dir', afile, '--mode=copy') + +data = configuration_data() +data.set10('foo', true) +conf = configure_file( + configuration : data, + output : 'conf.txt' +) + +meson.add_install_script('myinstall.py', 'dir', conf, '--mode=copy') + +t = custom_target( + 'ct', + command : [find_program('customtarget.py'), '@OUTDIR@'], + output : ['1.txt', '2.txt'], +) + +meson.add_install_script('myinstall.py', 'customtarget', t, '--mode=copy') +meson.add_install_script('myinstall.py', 'customtargetindex', t[0], '--mode=copy') + +installer = configure_file( + input : 'myinstall.py', + output : 'myinstall_copy.py', + copy : true, +) + +meson.add_install_script(installer, 'otherdir', afile, '--mode=copy') + +# This executable links on a library built in src/ directory. On Windows this +# means meson must add src/ into $PATH to find the DLL when running it as +# install script. +myexe = executable('prog', 'prog.c', + link_with: mylib, + install : true, +) +if meson.can_run_host_binaries() + meson.add_install_script(myexe) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/myinstall.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/myinstall.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/myinstall.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/myinstall.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import argparse +import os +import shutil + +prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX'] + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('dirname') + parser.add_argument('files', nargs='+') + parser.add_argument('--mode', action='store', default='create', choices=['create', 'copy']) + args = parser.parse_args() + + dirname = os.path.join(prefix, args.dirname) + if not os.path.exists(dirname): + os.makedirs(dirname) + + if args.mode == 'create': + for name in args.files: + with open(os.path.join(dirname, name), 'w') as f: + f.write('') + else: + for name in args.files: + shutil.copy(name, dirname) + + +if __name__ == "__main__": + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#include + +#ifdef _WIN32 + #define DO_IMPORT __declspec(dllimport) +#else + #define DO_IMPORT +#endif + +DO_IMPORT int foo(void); + +int main(void) { + printf("This is text.\n"); + return foo(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/src/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/src/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/src/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/src/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#ifdef _WIN32 + #define DO_EXPORT __declspec(dllexport) +#else + #define DO_EXPORT +#endif + +DO_EXPORT int foo(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +meson.add_install_script('myinstall.py', 'this/does', 'something-different.dat') + +afile = files('a file.txt') + +mylib = shared_library('mylib', 'foo.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/src/myinstall.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/src/myinstall.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/src/myinstall.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/src/myinstall.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +import os +import sys + +prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX'] + +dirname = os.path.join(prefix, sys.argv[1]) + +if not os.path.exists(dirname): + os.makedirs(dirname) + +with open(os.path.join(dirname, sys.argv[2] + '.in'), 'w') as f: + f.write('') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/53 install script/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/53 install script/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/diiba/daaba/file.dat"}, + {"type": "file", "file": "usr/this/should/also-work.dat"}, + {"type": "file", "file": "usr/this/does/something-different.dat.in"}, + {"type": "file", "file": "usr/dir/a file.txt"}, + {"type": "file", "file": "usr/dir/conf.txt"}, + {"type": "file", "file": "usr/otherdir/a file.txt"}, + {"type": "file", "file": "usr/customtarget/1.txt"}, + {"type": "file", "file": "usr/customtarget/2.txt"}, + {"type": "file", "file": "usr/customtargetindex/1.txt"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 custom target source output/generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 custom target source output/generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 custom target source output/generator.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 custom target source output/generator.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 + +import sys, os + +if len(sys.argv) != 2: + print(sys.argv[0], '') + +odir = sys.argv[1] + +with open(os.path.join(odir, 'mylib.h'), 'w') as f: + f.write('int func(void);\n') +with open(os.path.join(odir, 'mylib.c'), 'w') as f: + f.write('''int func(void) { + return 0; +} +''') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 custom target source output/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 custom target source output/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 custom target source output/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 custom target source output/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"mylib.h" + +int main(void) { + return func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 custom target source output/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 custom target source output/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 custom target source output/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 custom target source output/meson.build" 2021-10-23 16:48:23.000000000 +0000 @@ -0,0 +1,9 @@ +project('source generation', 'c') + +ct = custom_target('gen', +output : ['mylib.h', 'mylib.c'], +command : [find_program('generator.py'), '@OUTDIR@'], +) + +e = executable('prog', 'main.c', ct) +test('gentest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/check_exists.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/check_exists.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/check_exists.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/check_exists.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -if not os.path.isfile(sys.argv[1]): - raise Exception("Couldn't find {!r}".format(sys.argv[1])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/configure.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/configure.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/configure.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/configure.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/usr/bin/env python3 - -print('Success') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/converter.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/converter.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/converter.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/converter.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -with open(sys.argv[1], 'rb') as ifile, open(sys.argv[2], 'wb') as ofile: - ofile.write(ifile.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/fakeburner.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/fakeburner.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/fakeburner.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/fakeburner.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import print_function - -import sys - -plain_arg = sys.argv[1] -_, filename, _ = plain_arg.split(':') -try: - with open(filename, 'rb') as f: - content = f.read() -except FileNotFoundError: - print('Could not open file. Missing dependency?') - sys.exit(1) -print('File opened, pretending to send it somewhere.') -print(len(content), 'bytes uploaded') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/helloprinter.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/helloprinter.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/helloprinter.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/helloprinter.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include - -int main(int argc, char **argv) { - if(argc != 2) { - printf("I can not haz argument.\n"); - return 1; - } else { - printf("I can haz argument: %s\n", argv[1]); - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/54 run target/meson.build" 2020-01-07 21:07:03.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/54 run target/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -project('run target', 'c') - -# Make it possible to run built programs. -# In cross builds exe_wrapper should be added if it exists. - -exe = executable('helloprinter', 'helloprinter.c') -run_target('runhello', - command : [exe, 'argument']) - -converter = find_program('converter.py') - -hex = custom_target('exe.hex', - input : exe, - output : 'exe.hex', - command : [converter, '@INPUT@', '@OUTPUT@', - ], -) - -fakeburner = find_program('fakeburner.py') - -# These emulates the Arduino flasher application. It sandwiches the filename inside -# a packed argument. Thus we need to declare it manually. -run_target('upload', - command : [fakeburner, 'x:@0@:y'.format(exe.full_path())], - depends : exe, -) - -run_target('upload2', - command : [fakeburner, 'x:@0@:y'.format(hex.full_path())], - depends : hex, -) - -python3 = find_program('python3', required : false) -if not python3.found() - python3 = find_program('python') -endif - -run_target('py3hi', - command : [python3, '-c', 'print("I am Python3.")']) - -run_target('check_exists', - command : [find_program('check_exists.py'), files('helloprinter.c')]) - -run_target('check_exists', - command : [find_program('check_exists.py'), files('helloprinter.c')], - depends : disabler(), -) - -run_target('check_exists', - command : [disabler(), files('helloprinter.c')]) - -# What if the output of a custom_target is the command to -# execute. Obviously this will not work as hex is not an -# executable but test that the output is generated correctly. -run_target('donotrunme', - command : hex) - -# Ensure configure files can be passed -conf = configure_file( - input: 'configure.in', - output: 'configure', - configuration: configuration_data() -) - -run_target('configure_script', - command : conf -) - -# Target names that clash with potential builtin functionality. -run_target('ctags', - command : converter) - -run_target('clang-format', - command : converter) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/meson.build" 2021-10-23 16:48:26.000000000 +0000 @@ -0,0 +1,15 @@ +project('statchain', 'c') + +subdir('subdir') +# Test that -fPIC in c_args is also accepted (on platforms where it's permitted) +picflag = [] +if not ['darwin', 'windows'].contains(host_machine.system()) + picflag = ['-fPIC'] +endif +statlib2 = static_library('stat2', 'stat2.c', c_args : picflag, pic : false) +# Test that pic is needed for both direct and indirect static library +# dependencies of shared libraries (on Linux and BSD) +statlib = static_library('stat', 'stat.c', link_with : [shlib, statlib2], pic : true) +shlib2 = shared_library('shr2', 'shlib2.c', link_with : statlib) +exe = executable('prog', 'prog.c', link_with : shlib2) +test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +int shlibfunc2(void); +int statlibfunc(void); + +int main(void) { + if (statlibfunc() != 42) + return 1; + if (shlibfunc2() != 24) + return 1; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/shlib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/shlib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/shlib2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/shlib2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include "subdir/exports.h" + +int statlibfunc(void); +int statlibfunc2(void); + +int DLL_PUBLIC shlibfunc2(void) { + return statlibfunc() - statlibfunc2(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/stat2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/stat2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/stat2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/stat2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int statlibfunc2(void) { + return 18; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/stat.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/stat.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/stat.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/stat.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include "subdir/exports.h" + +int shlibfunc(void); + +int DLL_PUBLIC statlibfunc(void) { + return shlibfunc(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/subdir/exports.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/subdir/exports.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/subdir/exports.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/subdir/exports.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +#pragma once + +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +shlib = shared_library('shar', 'shlib.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/subdir/shlib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/subdir/shlib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 exe static shared/subdir/shlib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 exe static shared/subdir/shlib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "exports.h" + +int DLL_PUBLIC shlibfunc(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/meson.build" 2020-01-07 21:07:04.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -project('object generator', 'c') - -python = find_program('python3', required : false) -if not python.found() - python = find_program('python') -endif - -# Note that this will not add a dependency to the compiler executable. -# Code will not be rebuilt if it changes. -comp = '@0@/@1@'.format(meson.current_source_dir(), 'obj_generator.py') - -if host_machine.system() == 'windows' - outputname = '@BASENAME@.obj' -else - outputname = '@BASENAME@.o' -endif - -cc = meson.get_compiler('c').cmd_array().get(-1) -# Generate an object file manually. -gen = generator(python, - output : outputname, - arguments : [comp, cc, '@INPUT@', '@OUTPUT@']) - -generated = gen.process(['source.c', 'source2.c']) - -# Generate an object file with indexed OUTPUT replacement. -gen2 = generator(python, - output : outputname, - arguments : [comp, cc, '@INPUT@', '@OUTPUT0@']) -generated2 = gen2.process(['source3.c']) - -e = executable('prog', 'prog.c', generated, generated2) - -test('objgen', e) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/obj_generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/obj_generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/obj_generator.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/obj_generator.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 - -# Mimic a binary that generates an object file (e.g. windres). - -import sys, subprocess - -if __name__ == '__main__': - if len(sys.argv) != 4: - print(sys.argv[0], 'compiler input_file output_file') - sys.exit(1) - compiler = sys.argv[1] - ifile = sys.argv[2] - ofile = sys.argv[3] - if compiler.endswith('cl'): - cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] - else: - cmd = [compiler, '-c', ifile, '-o', ofile] - sys.exit(subprocess.call(cmd)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -int func1_in_obj(void); -int func2_in_obj(void); -int func3_in_obj(void); - -int main(void) { - return func1_in_obj() + func2_in_obj() + func3_in_obj(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/source2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/source2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/source2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/source2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func2_in_obj(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/source3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/source3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/source3.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/source3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func3_in_obj(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/55 object generator/source.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/55 object generator/source.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func1_in_obj(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 array methods/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 array methods/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 array methods/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 array methods/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,70 @@ +project('array methods', 'c') + +empty = [] +one = ['abc'] +two = ['def', 'ghi'] +combined = [empty, one, two] + +file_list = files('a.txt', 'b.txt') +file_a = files('a.txt') +file_c = files('c.txt') + +if file_a[0] != file_list[0] + error('Files are not equal') +endif + +if not file_list.contains(file_a[0]) + error('Contains with ObjectHolder lists does not work') +endif + +if file_list.contains(file_c[0]) + error('Contains with ObjectHolder lists found non existent object') +endif + +if empty.contains('abc') + error('Empty is not empty.') +endif + +if one.contains('a') + error('One claims to contain a') +endif + +if not one.contains('abc') + error('One claims to not contain abc.') +endif + +if one.contains('abcd') + error('One claims to contain abcd.') +endif + +if two.contains('abc') + error('Two claims to contain abc.') +endif + +if not two.contains('def') + error('Two claims not to contain def.') +endif + +if not two.contains('ghi') + error('Two claims not to contain ghi.') +endif + +if two.contains('defg') + error('Two claims to contain defg.') +endif + +if not combined.contains('abc') + error('Combined claims not to contain abc.') +endif + +if not combined.contains(one) + error('Combined claims not to contain [abc].') +endif + +if not combined.contains(two) + error('Combined claims not to contain [def, ghi].') +endif + +if not combined.contains('ghi') + error('Combined claims not to contain ghi.') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb -usr/diiba/daaba/file.dat -usr/this/should/also-work.dat -usr/this/does/something-different.dat.in diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/meson.build" 2020-01-07 21:07:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('custom install script', 'c') - -executable('prog', 'prog.c', install : true) -meson.add_install_script('myinstall.py', 'diiba/daaba', 'file.dat') -meson.add_install_script('myinstall.py', 'this/should', 'also-work.dat') - -subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/myinstall.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/myinstall.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/myinstall.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/myinstall.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX'] - -dirname = os.path.join(prefix, sys.argv[1]) - -os.makedirs(dirname) -with open(os.path.join(dirname, sys.argv[2]), 'w') as f: - f.write('') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("This is text.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/src/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -meson.add_install_script('myinstall.py', 'this/does', 'something-different.dat') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/src/myinstall.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/src/myinstall.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/56 install script/src/myinstall.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/56 install script/src/myinstall.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX'] - -dirname = os.path.join(prefix, sys.argv[1]) - -os.makedirs(dirname) -with open(os.path.join(dirname, sys.argv[2] + '.in'), 'w') as f: - f.write('') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom header generator/input.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom header generator/input.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom header generator/input.def" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom header generator/input.def" 2021-10-23 16:41:44.000000000 +0000 @@ -0,0 +1 @@ +0 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom header generator/makeheader.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom header generator/makeheader.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom header generator/makeheader.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom header generator/makeheader.py" 2021-10-23 16:41:44.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +# NOTE: this file does not have the executable bit set. This tests that +# Meson can automatically parse shebang lines. + +import sys + +template = '#define RET_VAL %s\n' +with open(sys.argv[1]) as f: + output = template % (f.readline().strip(), ) +with open(sys.argv[2], 'w') as f: + f.write(output) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom header generator/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom header generator/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom header generator/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom header generator/meson.build" 2021-10-23 16:48:26.000000000 +0000 @@ -0,0 +1,21 @@ +project('custom header generator', 'c') + +cc_id = meson.get_compiler('c').get_id() +cc_ver = meson.get_compiler('c').version() + +if cc_id == 'intel' or (cc_id == 'lcc' and cc_ver.version_compare('<=1.23.08')) + # ICC and LCC <= 1.23.08 do not escape spaces in paths in the dependency file, so Ninja + # (correctly) thinks that the rule has multiple outputs and errors out: + # 'depfile has multiple output paths' + error('MESON_SKIP_TEST: Skipping test because your compiler is known to generate broken dependency files') +endif + +gen = find_program('makeheader.py') + +generated_h = custom_target('makeheader.py', + output : 'myheader.lh', # Suffix not .h to ensure this works with custom suffixes, too. + input : 'input.def', + command : [gen, '@INPUT0@', '@OUTPUT0@', files('somefile.txt')]) + +prog = executable('prog', 'prog.c', generated_h) +test('gentest', prog) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom header generator/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom header generator/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom header generator/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom header generator/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"myheader.lh" + +int main(void) { + return RET_VAL; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom target source output/generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom target source output/generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom target source output/generator.py" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom target source output/generator.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os - -if len(sys.argv) != 2: - print(sys.argv[0], '') - -odir = sys.argv[1] - -with open(os.path.join(odir, 'mylib.h'), 'w') as f: - f.write('int func(void);\n') -with open(os.path.join(odir, 'mylib.c'), 'w') as f: - f.write('''int func(void) { - return 0; -} -''') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom target source output/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom target source output/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom target source output/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom target source output/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"mylib.h" - -int main(void) { - return func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom target source output/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom target source output/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/57 custom target source output/meson.build" 2020-01-07 21:07:07.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/57 custom target source output/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('source generation', 'c') - -ct = custom_target('gen', -output : ['mylib.h', 'mylib.c'], -command : [find_program('generator.py'), '@OUTDIR@'], -) - -e = executable('prog', 'main.c', ct) -test('gentest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/meson.build" 2020-01-07 21:07:08.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -project('statchain', 'c') - -subdir('subdir') -# Test that -fPIC in c_args is also accepted (on platforms where it's permitted) -picflag = [] -if not ['darwin', 'windows'].contains(host_machine.system()) - picflag = ['-fPIC'] -endif -statlib2 = static_library('stat2', 'stat2.c', c_args : picflag, pic : false) -# Test that pic is needed for both direct and indirect static library -# dependencies of shared libraries (on Linux and BSD) -statlib = static_library('stat', 'stat.c', link_with : [shlib, statlib2], pic : true) -shlib2 = shared_library('shr2', 'shlib2.c', link_with : statlib) -exe = executable('prog', 'prog.c', link_with : shlib2) -test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -int shlibfunc2(void); -int statlibfunc(void); - -int main(void) { - if (statlibfunc() != 42) - return 1; - if (shlibfunc2() != 24) - return 1; - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/shlib2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/shlib2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/shlib2.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/shlib2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include "subdir/exports.h" - -int statlibfunc(void); -int statlibfunc2(void); - -int DLL_PUBLIC shlibfunc2(void) { - return statlibfunc() - statlibfunc2(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/stat2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/stat2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/stat2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/stat2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int statlibfunc2(void) { - return 18; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/stat.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/stat.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/stat.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/stat.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include "subdir/exports.h" - -int shlibfunc(void); - -int DLL_PUBLIC statlibfunc(void) { - return shlibfunc(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/subdir/exports.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/subdir/exports.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/subdir/exports.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/subdir/exports.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#pragma once - -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -shlib = shared_library('shar', 'shlib.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/subdir/shlib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/subdir/shlib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 exe static shared/subdir/shlib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 exe static shared/subdir/shlib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "exports.h" - -int DLL_PUBLIC shlibfunc(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/data2.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/data2.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/data2.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/data2.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +2 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include"source1.h" +#include"source2.h" + +int main(void) { + return func1() + func2(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/meson.build" 2021-10-23 16:48:26.000000000 +0000 @@ -0,0 +1,13 @@ +project('trickier generator', 'cpp') + +comp = find_program('mygen.py') +subdir('subdir') + +generated2 = custom_target('generated2', + output : ['source2.h', 'source2.cpp'], + input : 'data2.dat', + command : [comp, '@INPUT0@', '@OUTDIR@']) + +exe = executable('prog', 'main.cpp', generated, generated2, + include_directories : include_directories('subdir')) + test('generated test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/mygen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/mygen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/mygen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/mygen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +import sys, os + +if len(sys.argv) != 3: + print("You is fail.") + sys.exit(1) + +with open(sys.argv[1]) as f: + val = f.read().strip() +outdir = sys.argv[2] + +outhdr = os.path.join(outdir, 'source%s.h' % val) +outsrc = os.path.join(outdir, 'source%s.cpp' % val) + +with open(outhdr, 'w') as f: + f.write('int func%s();\n' % val) +with open(outsrc, 'w') as f: + f.write('''int func%s() { + return 0; +} +''' % val) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/subdir/data.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/subdir/data.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/subdir/data.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/subdir/data.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +1 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/58 multiple generators/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/58 multiple generators/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +generated = custom_target('generated', +output : ['source1.h', 'source1.cpp'], +input : 'data.dat', +command : [comp, '@INPUT0@', '@OUTDIR@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 array methods/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 array methods/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 array methods/meson.build" 2020-01-07 21:07:07.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 array methods/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -project('array methods', 'c') - -empty = [] -one = ['abc'] -two = ['def', 'ghi'] -combined = [empty, one, two] - -if empty.contains('abc') - error('Empty is not empty.') -endif - -if one.contains('a') - error('One claims to contain a') -endif - -if not one.contains('abc') - error('One claims to not contain abc.') -endif - -if one.contains('abcd') - error('One claims to contain abcd.') -endif - -if two.contains('abc') - error('Two claims to contain abc.') -endif - -if not two.contains('def') - error('Two claims not to contain def.') -endif - -if not two.contains('ghi') - error('Two claims not to contain ghi.') -endif - -if two.contains('defg') - error('Two claims to contain defg.') -endif - -if not combined.contains('abc') - error('Combined claims not to contain abc.') -endif - -if not combined.contains('ghi') - error('Combined claims not to contain ghi.') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/meson.build" 2021-10-23 16:48:26.000000000 +0000 @@ -0,0 +1,21 @@ +project('install a whole subdir', 'c', + default_options : ['install_umask=preserve']) + +# A subdir with an exclusion: +install_subdir('sub2', + exclude_files : ['excluded-three.dat'], + exclude_directories : ['excluded'], + install_dir : 'share') + +subdir('subdir') +# A subdir with write perms only for the owner +# and read-list perms for owner and group +install_subdir('sub1', install_dir : 'share', install_mode : ['rwxr-x--t', 'root']) +install_subdir('sub/sub1', install_dir : 'share') + +# strip_directory +install_subdir('sub_elided', install_dir : 'share', strip_directory : true) +install_subdir('nested_elided/sub', install_dir : 'share', strip_directory : true) + +# Create new empty directory that doesn't exist in the source tree +install_subdir('new_directory', install_dir : 'share') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/nested_elided/sub/dircheck/ninth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/nested_elided/sub/dircheck/ninth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/nested_elided/sub/dircheck/ninth.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/nested_elided/sub/dircheck/ninth.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Nested file under nested elided directory. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/nested_elided/sub/eighth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/nested_elided/sub/eighth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/nested_elided/sub/eighth.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/nested_elided/sub/eighth.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +File in nested elided directory. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/sub/sub1/third.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/sub/sub1/third.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/sub/sub1/third.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/sub/sub1/third.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +This is a third data file for sub1 dir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/sub1/second.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/sub1/second.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/sub1/second.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/sub1/second.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Test that multiple install_subdirs meld their results. \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +install_subdir('sub1', install_dir : 'share', + # This mode will be overridden by the mode set in the outer install_subdir + install_mode : 'rwxr-x---') + +install_subdir('sub_elided', install_dir : 'share', strip_directory : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/sub1/data1.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/sub1/data1.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/sub1/data1.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/sub1/data1.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +This is a data file in a subdir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/sub1/sub2/data2.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/sub1/sub2/data2.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/sub1/sub2/data2.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/sub1/sub2/data2.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +This is a data file in a deeper subdir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/sub_elided/dircheck/seventh.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/sub_elided/dircheck/seventh.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/sub_elided/dircheck/seventh.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/sub_elided/dircheck/seventh.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Nested file in a subdir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/sub_elided/sixth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/sub_elided/sixth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/subdir/sub_elided/sixth.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/subdir/sub_elided/sixth.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Elide test file in a subdir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/sub_elided/dircheck/fifth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/sub_elided/dircheck/fifth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/sub_elided/dircheck/fifth.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/sub_elided/dircheck/fifth.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Data file in a subdir of elided directory. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/sub_elided/fourth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/sub_elided/fourth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/sub_elided/fourth.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/sub_elided/fourth.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Test that this file is installed directly into install_dir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/59 install subdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/59 install subdir/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +{ + "installed": [ + {"type": "file", "file": "usr/share/dircheck/fifth.dat"}, + {"type": "file", "file": "usr/share/dircheck/seventh.dat"}, + {"type": "file", "file": "usr/share/dircheck/ninth.dat"}, + {"type": "file", "file": "usr/share/eighth.dat"}, + {"type": "file", "file": "usr/share/fourth.dat"}, + {"type": "file", "file": "usr/share/sixth.dat"}, + {"type": "file", "file": "usr/share/sub1/data1.dat"}, + {"type": "file", "file": "usr/share/sub1/second.dat"}, + {"type": "file", "file": "usr/share/sub1/third.dat"}, + {"type": "file", "file": "usr/share/sub1/sub2/data2.dat"}, + {"type": "file", "file": "usr/share/sub2/one.dat"}, + {"type": "file", "file": "usr/share/sub2/dircheck/excluded-three.dat"}, + {"type": "dir", "file": "usr/share/new_directory"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 custom header generator/input.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 custom header generator/input.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 custom header generator/input.def" 2020-01-07 21:00:12.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 custom header generator/input.def" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -0 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 custom header generator/makeheader.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 custom header generator/makeheader.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 custom header generator/makeheader.py" 2020-01-07 21:00:12.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 custom header generator/makeheader.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#!/usr/bin/env python3 - -# NOTE: this file does not have the executable bit set. This tests that -# Meson can automatically parse shebang lines. - -import sys - -template = '#define RET_VAL %s\n' -with open(sys.argv[1]) as f: - output = template % (f.readline().strip(), ) -with open(sys.argv[2], 'w') as f: - f.write(output) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 custom header generator/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 custom header generator/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 custom header generator/meson.build" 2020-01-07 21:07:08.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 custom header generator/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -project('custom header generator', 'c') - -cc_id = meson.get_compiler('c').get_id() -cc_ver = meson.get_compiler('c').version() - -if cc_id == 'intel' or (cc_id == 'lcc' and cc_ver.version_compare('<=1.23.08')) - # ICC and LCC <= 1.23.08 do not escape spaces in paths in the dependency file, so Ninja - # (correctly) thinks that the rule has multiple outputs and errors out: - # 'depfile has multiple output paths' - error('MESON_SKIP_TEST: Skipping test because your compiler is known to generate broken dependency files') -endif - -gen = find_program('makeheader.py') - -generated_h = custom_target('makeheader.py', - output : 'myheader.lh', # Suffix not .h to ensure this works with custom suffixes, too. - input : 'input.def', - command : [gen, '@INPUT0@', '@OUTPUT0@', files('somefile.txt')]) - -prog = executable('prog', 'prog.c', generated_h) -test('gentest', prog) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 custom header generator/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 custom header generator/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 custom header generator/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 custom header generator/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"myheader.lh" - -int main(void) { - return RET_VAL; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/meson.build" 2021-10-23 16:48:27.000000000 +0000 @@ -0,0 +1,53 @@ +project('foreach', 'c') + +tests = [['test1', 'prog1', 'prog1.c'], + ['test2', 'prog2', 'prog2.c', 'fallback'], + ['test3', 'prog3', 'prog3.c', 'urgh']] + +assert(tests[0].get(3, 'fallbck') == 'fallbck', 'array #1 fallback did not match') +assert(tests[1].get(3, 'failbk') == 'fallback', 'array #2 value did not match') +assert(tests[2].get(3, 'urgh') == 'urgh', 'array #3 value did not match') + +foreach i : tests + test(i.get(0), executable(i.get(1), i.get(2), install : true)) + + # Ensure that changing the tests variable does not + # affect ongoing iteration in the foreach loop. + # + # Being able to do that would make Meson Turing complete and + # we definitely don't want that. + tests = ['test4', 'prog4', 'prog4.c'] +endforeach + +items = ['a', 'continue', 'b', 'break', 'c'] +result = [] +foreach i : items + if i == 'continue' + continue + elif i == 'break' + break + endif + result += i +endforeach + +assert(result == ['a', 'b'], 'Continue or break in foreach failed') + +items = [] +iter = range(2) +foreach i : iter + items += i +endforeach +assert(items == [0, 1]) +assert(iter[1] == 1) + +items = [] +foreach i : range(1, 2) + items += i +endforeach +assert(items == [1]) + +items = [] +foreach i : range(1, 10, 2) + items += i +endforeach +assert(items == [1, 3, 5, 7, 9]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/prog1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/prog1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/prog1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/prog1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("This is test #1.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/prog2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/prog2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/prog2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/prog2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("This is test #2.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/prog3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/prog3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/prog3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/prog3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("This is test #3.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/60 foreach/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/60 foreach/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog1"}, + {"type": "pdb", "file": "usr/bin/prog1"}, + {"type": "exe", "file": "usr/bin/prog2"}, + {"type": "pdb", "file": "usr/bin/prog2"}, + {"type": "exe", "file": "usr/bin/prog3"}, + {"type": "pdb", "file": "usr/bin/prog3"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/data2.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/data2.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/data2.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/data2.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -2 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/main.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include"source1.h" -#include"source2.h" - -int main(void) { - return func1() + func2(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/meson.build" 2020-01-07 21:07:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('trickier generator', 'cpp') - -comp = find_program('mygen.py') -subdir('subdir') - -generated2 = custom_target('generated2', - output : ['source2.h', 'source2.cpp'], - input : 'data2.dat', - command : [comp, '@INPUT0@', '@OUTDIR@']) - -exe = executable('prog', 'main.cpp', generated, generated2, - include_directories : include_directories('subdir')) - test('generated test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/mygen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/mygen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/mygen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/mygen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os - -if len(sys.argv) != 3: - print("You is fail.") - sys.exit(1) - -with open(sys.argv[1]) as f: - val = f.read().strip() -outdir = sys.argv[2] - -outhdr = os.path.join(outdir, 'source%s.h' % val) -outsrc = os.path.join(outdir, 'source%s.cpp' % val) - -with open(outhdr, 'w') as f: - f.write('int func%s();\n' % val) -with open(outsrc, 'w') as f: - f.write('''int func%s() { - return 0; -} -''' % val) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/subdir/data.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/subdir/data.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/subdir/data.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/subdir/data.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -1 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 multiple generators/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 multiple generators/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -generated = custom_target('generated', -output : ['source1.h', 'source1.cpp'], -input : 'data.dat', -command : [comp, '@INPUT0@', '@OUTDIR@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 number arithmetic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 number arithmetic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/61 number arithmetic/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/61 number arithmetic/meson.build" 2021-10-23 16:48:29.000000000 +0000 @@ -0,0 +1,76 @@ +project('number arithmetic', 'c') + +if 6 + 4 != 10 + error('Number addition is broken') +endif +if 6 - 4 != 2 + error('Number subtraction is broken') +endif + +if 6 * 4 != 24 + error('Number multiplication is broken') +endif +if 16 / 4 != 4 + error('Number division is broken') +endif + +#if (1 / 3) * 3 != 1 +# error('Float interconversion broken') +#endif +if (5 / 3) * 3 != 3 + error('Integer division is broken') +endif + +assert((5 % 2) == 1, 'Integer modulo (odd) is broken') +assert((4 % 2) == 0, 'Integer modulo (even) is broken') + +if 2 * 1 % 2 != 0 + error('Modulo precedence with multiplication is broken') +endif +if 2 + 1 % 2 != 3 + error('Modulo precedence with addition is broken') +endif +if 9 / 9 % 2 != 1 + error('Modulo precedence with division is broken') +endif +if 9 - 9 % 2 != 8 + error('Modulo precedence with subtraction is broken') +endif + +assert(2.is_even(), 'int is_even() broken for even value') +assert(not(2.is_odd()), 'int is_odd() broken for even value') +assert(not(3.is_even()), 'int is_even() broken for odd value') +assert(3.is_odd(), 'int is_odd() broken for odd value') + +assert(3 < 4, 'Lt broken') +assert(not(4 < 3), 'Lt broken') +assert(3 <= 4, 'Lte broken') +assert(not(4 <= 3), 'Lte broken') +assert(3 <= 3, 'Lte broken') + +assert(4 > 3, 'Gt broken') +assert(not(3 > 4), 'Gt broken') +assert(4 >= 3, 'Gte broken') +assert(not(3 >= 4), 'Gte broken') +assert(3 >= 3, 'Gte broken') + +assert(true.to_int() == 1,'bool to_int() broken') +assert(false.to_int() == 0,'bool to_int() broken') + +hex_255 = 0xff +hex2_255 = 0XFF + +assert(hex_255 == 255, 'Hex parsing is broken.') +assert(hex2_255 == 255, 'Uppercase hex parsing is broken.') + +bin_123 = 0b1111011 +bin2_123 = 0B1111011 + +assert(bin_123 == 123, 'Bin number parsing is broken.') +assert(bin2_123 == 123, 'Uppercase bin number parsing is broken.') + +oct_493 = 0o755 +oct2_493 = 0O755 + +assert(oct_493 == 493, 'Oct number parsing is broken.') +assert(oct2_493 == 493, 'Uppercase oct number parsing is broken.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/installed_files.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -usr/share/dircheck/fifth.dat -usr/share/dircheck/seventh.dat -usr/share/dircheck/ninth.dat -usr/share/eighth.dat -usr/share/fourth.dat -usr/share/sixth.dat -usr/share/sub1/data1.dat -usr/share/sub1/second.dat -usr/share/sub1/third.dat -usr/share/sub1/sub2/data2.dat -usr/share/sub2/one.dat -usr/share/sub2/dircheck/excluded-three.dat diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/meson.build" 2020-01-07 21:07:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -project('install a whole subdir', 'c', - default_options : ['install_umask=preserve']) - -# A subdir with an exclusion: -install_subdir('sub2', - exclude_files : ['excluded-three.dat'], - exclude_directories : ['excluded'], - install_dir : 'share') - -subdir('subdir') -# A subdir with write perms only for the owner -# and read-list perms for owner and group -install_subdir('sub1', install_dir : 'share', install_mode : ['rwxr-x--t', 'root']) -install_subdir('sub/sub1', install_dir : 'share') - -# strip_directory -install_subdir('sub_elided', install_dir : 'share', strip_directory : true) -install_subdir('nested_elided/sub', install_dir : 'share', strip_directory : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/nested_elided/sub/dircheck/ninth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/nested_elided/sub/dircheck/ninth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/nested_elided/sub/dircheck/ninth.dat" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/nested_elided/sub/dircheck/ninth.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Nested file under nested elided directory. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/nested_elided/sub/eighth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/nested_elided/sub/eighth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/nested_elided/sub/eighth.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/nested_elided/sub/eighth.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -File in nested elided directory. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/sub/sub1/third.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/sub/sub1/third.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/sub/sub1/third.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/sub/sub1/third.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a third data file for sub1 dir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/sub1/second.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/sub1/second.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/sub1/second.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/sub1/second.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Test that multiple install_subdirs meld their results. \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -install_subdir('sub1', install_dir : 'share', - # This mode will be overridden by the mode set in the outer install_subdir - install_mode : 'rwxr-x---') - -install_subdir('sub_elided', install_dir : 'share', strip_directory : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/sub1/data1.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/sub1/data1.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/sub1/data1.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/sub1/data1.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a data file in a subdir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/sub1/sub2/data2.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/sub1/sub2/data2.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/sub1/sub2/data2.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/sub1/sub2/data2.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a data file in a deeper subdir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/sub_elided/dircheck/seventh.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/sub_elided/dircheck/seventh.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/sub_elided/dircheck/seventh.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/sub_elided/dircheck/seventh.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Nested file in a subdir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/sub_elided/sixth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/sub_elided/sixth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/subdir/sub_elided/sixth.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/subdir/sub_elided/sixth.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Elide test file in a subdir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/sub_elided/dircheck/fifth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/sub_elided/dircheck/fifth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/sub_elided/dircheck/fifth.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/sub_elided/dircheck/fifth.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Data file in a subdir of elided directory. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/sub_elided/fourth.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/sub_elided/fourth.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 install subdir/sub_elided/fourth.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 install subdir/sub_elided/fourth.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Test that this file is installed directly into install_dir. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 string arithmetic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 string arithmetic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/62 string arithmetic/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/62 string arithmetic/meson.build" 2021-10-23 16:48:30.000000000 +0000 @@ -0,0 +1,16 @@ +project('string arithmetic', 'c') + +if 'foo' + 'bar' != 'foobar' + error('String concatenation is broken') +endif + +if 'foo' + 'bar' + 'baz' != 'foobarbaz' + error('Many-string concatenation is broken') +endif + +a = 'a' +b = 'b' + +if a + b + 'c' != 'abc' + error('String concat with variables is broken.') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 array arithmetic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 array arithmetic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 array arithmetic/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 array arithmetic/meson.build" 2021-10-23 16:48:30.000000000 +0000 @@ -0,0 +1,15 @@ +project('array arithmetic', 'c') + +array1 = ['foo', 'bar'] +array2 = ['qux', 'baz'] + +if array1 + array2 != ['foo', 'bar', 'qux', 'baz'] + error('Array concatenation is broken') +endif +if array2 + array1 != ['qux', 'baz', 'foo', 'bar'] + error('Array concatenation is broken') +endif + +if array1 + array1 + array1 != ['foo', 'bar', 'foo', 'bar', 'foo', 'bar'] + error('Many-array concatenation is broken') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/installed_files.txt" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -usr/bin/prog1?exe -?msvc:usr/bin/prog1.pdb -usr/bin/prog2?exe -?msvc:usr/bin/prog2.pdb -usr/bin/prog3?exe -?msvc:usr/bin/prog3.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/meson.build" 2020-01-07 21:07:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -project('foreach', 'c') - -tests = [['test1', 'prog1', 'prog1.c'], - ['test2', 'prog2', 'prog2.c', 'fallback'], - ['test3', 'prog3', 'prog3.c', 'urgh']] - -assert(tests[0].get(3, 'fallbck') == 'fallbck', 'array #1 fallback did not match') -assert(tests[1].get(3, 'failbk') == 'fallback', 'array #2 value did not match') -assert(tests[2].get(3, 'urgh') == 'urgh', 'array #3 value did not match') - -foreach i : tests - test(i.get(0), executable(i.get(1), i.get(2), install : true)) - - # Ensure that changing the tests variable does not - # affect ongoing iteration in the foreach loop. - # - # Being able to do that would make Meson Turing complete and - # we definitely don't want that. - tests = ['test4', 'prog4', 'prog4.c'] -endforeach - -items = ['a', 'continue', 'b', 'break', 'c'] -result = [] -foreach i : items - if i == 'continue' - continue - elif i == 'break' - break - endif - result += i -endforeach - -assert(result == ['a', 'b'], 'Continue or break in foreach failed') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/prog1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/prog1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/prog1.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/prog1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("This is test #1.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/prog2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/prog2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/prog2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/prog2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("This is test #2.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/prog3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/prog3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/63 foreach/prog3.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/63 foreach/prog3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("This is test #3.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/64 arithmetic bidmas/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/64 arithmetic bidmas/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/64 arithmetic bidmas/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/64 arithmetic bidmas/meson.build" 2021-10-23 16:48:30.000000000 +0000 @@ -0,0 +1,15 @@ +project('arithmetic bidmas', 'c') + +if 5 * 3 - 6 / 2 + 1 != 13 + error('Arithmetic bidmas broken') +endif +if 5 * (3 - 6 / 2) + 1 != 1 + error('Arithmetic bidmas with brackets broken') +endif + +if 5 * 12 / 2 * 3 != 90 + error('Sequential multiplication and division broken') +endif +if 5 * (12 / (2 * 3)) != 10 + error('Sequential multiplication and division with brackets broken') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/64 number arithmetic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/64 number arithmetic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/64 number arithmetic/meson.build" 2020-01-07 21:07:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/64 number arithmetic/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -project('number arithmetic', 'c') - -if 6 + 4 != 10 - error('Number addition is broken') -endif -if 6 - 4 != 2 - error('Number subtraction is broken') -endif - -if 6 * 4 != 24 - error('Number multiplication is broken') -endif -if 16 / 4 != 4 - error('Number division is broken') -endif - -#if (1 / 3) * 3 != 1 -# error('Float interconversion broken') -#endif -if (5 / 3) * 3 != 3 - error('Integer division is broken') -endif - -assert((5 % 2) == 1, 'Integer modulo (odd) is broken') -assert((4 % 2) == 0, 'Integer modulo (even) is broken') - -if 2 * 1 % 2 != 0 - error('Modulo precedence with multiplication is broken') -endif -if 2 + 1 % 2 != 3 - error('Modulo precedence with addition is broken') -endif -if 9 / 9 % 2 != 1 - error('Modulo precedence with division is broken') -endif -if 9 - 9 % 2 != 8 - error('Modulo precedence with subtraction is broken') -endif - -assert(2.is_even(), 'int is_even() broken for even value') -assert(not(2.is_odd()), 'int is_odd() broken for even value') -assert(not(3.is_even()), 'int is_even() broken for odd value') -assert(3.is_odd(), 'int is_odd() broken for odd value') - -assert(3 < 4, 'Lt broken') -assert(not(4 < 3), 'Lt broken') -assert(3 <= 4, 'Lte broken') -assert(not(4 <= 3), 'Lte broken') -assert(3 <= 3, 'Lte broken') - -assert(4 > 3, 'Gt broken') -assert(not(3 > 4), 'Gt broken') -assert(4 >= 3, 'Gte broken') -assert(not(3 >= 4), 'Gte broken') -assert(3 >= 3, 'Gte broken') - -assert(true.to_int() == 1,'bool to_int() broken') -assert(false.to_int() == 0,'bool to_int() broken') - -hex_255 = 0xff -hex2_255 = 0XFF - -assert(hex_255 == 255, 'Hex parsing is broken.') -assert(hex2_255 == 255, 'Uppercase hex parsing is broken.') - -bin_123 = 0b1111011 -bin2_123 = 0B1111011 - -assert(bin_123 == 123, 'Bin number parsing is broken.') -assert(bin2_123 == 123, 'Uppercase bin number parsing is broken.') - -oct_493 = 0o755 -oct2_493 = 0O755 - -assert(oct_493 == 493, 'Oct number parsing is broken.') -assert(oct2_493 == 493, 'Uppercase oct number parsing is broken.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include +#include"version.h" + +int main(void) { + printf("Version is %s.\n", version_string); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/meson.build" 2021-10-23 16:48:32.000000000 +0000 @@ -0,0 +1,14 @@ +project('run always', 'c') + +version = '1.0.0' + +vgen = find_program('version_gen.py') + +version_src = custom_target('Version string', +input : 'version.c.in', +output : 'version.c', +command : [vgen, '@INPUT@', '@OUTPUT@', version], +build_always : true, +) + +executable('versionprinter', 'main.c', version_src) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/version.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/version.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/version.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/version.c.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#include"version.h" + +const char *version_string = "@VERSION@"; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/version_gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/version_gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/version_gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/version_gen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +import sys, os, subprocess + +def generate(infile, outfile, fallback): + workdir = os.path.split(infile)[0] + if workdir == '': + workdir = '.' + try: + version = subprocess.check_output(['git', 'describe'], cwd=workdir).decode().strip() + except (subprocess.CalledProcessError, OSError, UnicodeDecodeError): + version = fallback + with open(infile) as f: + newdata = f.read().replace('@VERSION@', version) + try: + with open(outfile) as f: + olddata = f.read() + if olddata == newdata: + return + except OSError: + pass + with open(outfile, 'w') as f: + f.write(newdata) + +if __name__ == '__main__': + infile = sys.argv[1] + outfile = sys.argv[2] + fallback = sys.argv[3] + generate(infile, outfile, fallback) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/version.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/version.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 build always/version.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 build always/version.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +extern const char *version_string; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 string arithmetic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 string arithmetic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/65 string arithmetic/meson.build" 2020-01-07 21:07:13.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/65 string arithmetic/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -project('string arithmetic', 'c') - -if 'foo' + 'bar' != 'foobar' - error('String concatenation is broken') -endif - -if 'foo' + 'bar' + 'baz' != 'foobarbaz' - error('Many-string concatenation is broken') -endif - -a = 'a' -b = 'b' - -if a + b + 'c' != 'abc' - error('String concat with variables is broken.') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/66 array arithmetic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/66 array arithmetic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/66 array arithmetic/meson.build" 2020-01-07 21:07:14.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/66 array arithmetic/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -project('array arithmetic', 'c') - -array1 = ['foo', 'bar'] -array2 = ['qux', 'baz'] - -if array1 + array2 != ['foo', 'bar', 'qux', 'baz'] - error('Array concatenation is broken') -endif -if array2 + array1 != ['qux', 'baz', 'foo', 'bar'] - error('Array concatenation is broken') -endif - -if array1 + array1 + array1 != ['foo', 'bar', 'foo', 'bar', 'foo', 'bar'] - error('Many-array concatenation is broken') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/66 vcstag/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/66 vcstag/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/66 vcstag/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/66 vcstag/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,17 @@ +project('vcstag', 'c') + +version_src = vcs_tag(input : 'vcstag.c.in', +output : 'vcstag.c', +fallback : '1.0.0') + +version_src_custom = vcs_tag(input : 'vcstag.c.in', +output : 'vcstag-custom.c', +command : ['git', 'show-ref', '-s', 'refs/heads/master'], +fallback : '1.0.0') + +version_src_fallback = vcs_tag(input : 'vcstag.c.in', +output : 'vcstag-fallback.c') + +executable('tagprog', 'tagprog.c', version_src) +executable('tagprog-custom', 'tagprog.c', version_src_custom) +executable('tagprog-fallback', 'tagprog.c', version_src_fallback) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/66 vcstag/tagprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/66 vcstag/tagprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/66 vcstag/tagprog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/66 vcstag/tagprog.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +extern const char *vcstag; + +int main(void) { + printf("Version is %s\n", vcstag); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/66 vcstag/vcstag.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/66 vcstag/vcstag.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/66 vcstag/vcstag.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/66 vcstag/vcstag.c.in" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +const char *vcstag = "@VCS_TAG@"; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/67 arithmetic bidmas/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/67 arithmetic bidmas/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/67 arithmetic bidmas/meson.build" 2020-01-07 21:07:14.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/67 arithmetic bidmas/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -project('arithmetic bidmas', 'c') - -if 5 * 3 - 6 / 2 + 1 != 13 - error('Arithmetic bidmas broken') -endif -if 5 * (3 - 6 / 2) + 1 != 1 - error('Arithmetic bidmas with brackets broken') -endif - -if 5 * 12 / 2 * 3 != 90 - error('Sequential multiplication and division broken') -endif -if 5 * (12 / (2 * 3)) != 10 - error('Sequential multiplication and division with brackets broken') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/67 modules/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/67 modules/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/67 modules/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/67 modules/meson.build" 2021-10-23 16:48:32.000000000 +0000 @@ -0,0 +1,14 @@ +project('module test', 'c') + +modtest = import('modtest') +modtest.print_hello() +assert(modtest.found()) + +modtest = import('modtest', required : get_option('disabled')) +assert(not modtest.found()) + +notfound = import('not-found', required : false) +assert(not notfound.found()) + +disabled = import('not-found', required : false, disabler : true) +assert(is_disabler(disabled)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/67 modules/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/67 modules/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/67 modules/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/67 modules/meson_options.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +option( + 'disabled', + type : 'feature', + value : 'disabled', + description : 'test disabled' +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include -#include"version.h" - -int main(void) { - printf("Version is %s.\n", version_string); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/meson.build" 2020-01-07 21:07:15.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('run always', 'c') - -version = '1.0.0' - -vgen = find_program('version_gen.py') - -version_src = custom_target('Version string', -input : 'version.c.in', -output : 'version.c', -command : [vgen, '@INPUT@', '@OUTPUT@', version], -build_always : true, -) - -executable('versionprinter', 'main.c', version_src) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/version.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/version.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/version.c.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/version.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#include"version.h" - -const char *version_string = "@VERSION@"; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/version_gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/version_gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/version_gen.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/version_gen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os, subprocess - -def generate(infile, outfile, fallback): - workdir = os.path.split(infile)[0] - if workdir == '': - workdir = '.' - try: - version = subprocess.check_output(['git', 'describe'], cwd=workdir).decode().strip() - except (subprocess.CalledProcessError, OSError, UnicodeDecodeError): - version = fallback - with open(infile) as f: - newdata = f.read().replace('@VERSION@', version) - try: - with open(outfile) as f: - olddata = f.read() - if olddata == newdata: - return - except OSError: - pass - with open(outfile, 'w') as f: - f.write(newdata) - -if __name__ == '__main__': - infile = sys.argv[1] - outfile = sys.argv[2] - fallback = sys.argv[3] - generate(infile, outfile, fallback) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/version.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/version.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 build always/version.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 build always/version.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#pragma once - -const char *version_string; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 should fail/failing.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 should fail/failing.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 should fail/failing.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 should fail/failing.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 should fail/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 should fail/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/68 should fail/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/68 should fail/meson.build" 2021-10-23 16:48:32.000000000 +0000 @@ -0,0 +1,4 @@ +project('should fail', 'c') + +exe = executable('prog', 'failing.c') +test('failing', exe, should_fail : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/inc/confdata.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/inc/confdata.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/inc/confdata.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/inc/confdata.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +@VALUE@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/inc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/inc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/inc/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/inc/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +cdata = configuration_data() +cdata.set('VALUE', '42') + +cfile = configure_file(input : 'confdata.in', +output : 'confdata', +configuration : cdata) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/meson.build" 2021-10-23 16:48:34.000000000 +0000 @@ -0,0 +1,4 @@ +project('conf file in custom target', 'c') + +subdir('inc') +subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +custom_target('thing', +output : 'final.dat', +input : cfile, +command : [find_program('mycompiler.py'), '@INPUT@', '@OUTPUT@']) + +# Test usage of a `configure_file` as part of the command list +py3 = find_program('python3', required : false) +if not py3.found() + # Maybe 'python' is Python 3 + py3 = find_program('python') +endif + +compiler = configure_file(input : 'mycompiler.py', + output : 'mycompiler2.py', + copy: true) + +custom_target('thing2', +output : 'final2.dat', +input : cfile, +command : [py3, compiler, '@INPUT@', '@OUTPUT@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/src/mycompiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/src/mycompiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 configure file in custom target/src/mycompiler.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 configure file in custom target/src/mycompiler.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys + +with open(sys.argv[1]) as ifile: + if ifile.readline().strip() != '42': + print('Incorrect input') +with open(sys.argv[2], 'w') as ofile: + ofile.write('Success\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 vcstag/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 vcstag/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 vcstag/meson.build" 2020-01-07 21:07:17.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 vcstag/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -project('vcstag', 'c') - -version_src = vcs_tag(input : 'vcstag.c.in', -output : 'vcstag.c', -fallback : '1.0.0') - -version_src_custom = vcs_tag(input : 'vcstag.c.in', -output : 'vcstag-custom.c', -command : ['git', 'show-ref', '-s', 'refs/heads/master'], -fallback : '1.0.0') - -version_src_fallback = vcs_tag(input : 'vcstag.c.in', -output : 'vcstag-fallback.c') - -executable('tagprog', 'tagprog.c', version_src) -executable('tagprog-custom', 'tagprog.c', version_src_custom) -executable('tagprog-fallback', 'tagprog.c', version_src_fallback) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 vcstag/tagprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 vcstag/tagprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 vcstag/tagprog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 vcstag/tagprog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#include - -const char *vcstag; - -int main(void) { - printf("Version is %s\n", vcstag); - return 0; -} - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 vcstag/vcstag.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 vcstag/vcstag.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/69 vcstag/vcstag.c.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/69 vcstag/vcstag.c.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -const char *vcstag = "@VCS_TAG@"; - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/cpplib.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/cpplib.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/cpplib.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/cpplib.cpp" 2021-08-18 11:22:15.000000000 +0000 @@ -1,8 +1,5 @@ -#if defined _WIN32 - #define DLL_PUBLIC __declspec(dllexport) -#else - #define DLL_PUBLIC __attribute__ ((visibility ("default"))) -#endif +#define BUILDING_DLL +#include "cpplib.h" int DLL_PUBLIC cppfunc(void) { return 42; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/cpplib.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/cpplib.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/cpplib.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/cpplib.h" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,12 @@ +/* See http://gcc.gnu.org/wiki/Visibility#How_to_use_the_new_C.2B-.2B-_visibility_support */ +#if defined(_WIN32) || defined(__CYGWIN__) + #ifdef BUILDING_DLL + #define DLL_PUBLIC __declspec(dllexport) + #else + #define DLL_PUBLIC __declspec(dllimport) + #endif +#else + #define DLL_PUBLIC __attribute__ ((visibility ("default"))) +#endif + +int DLL_PUBLIC cppfunc(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/cppmain.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/cppmain.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/cppmain.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/cppmain.cpp" 2021-08-18 11:22:15.000000000 +0000 @@ -1,4 +1,4 @@ -int cppfunc(void); +#include "cpplib.h" int main(void) { return cppfunc() != 42; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/6 linkshared/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/6 linkshared/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + { "type": "exe", "file": "usr/bin/prog" }, + { "type": "pdb", "file": "usr/bin/prog" } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/70 external test program/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/70 external test program/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/70 external test program/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/70 external test program/meson.build" 2021-10-23 16:48:35.000000000 +0000 @@ -0,0 +1,3 @@ +project('test is external', 'c') + +test('external', find_program('mytest.py'), args : ['correct']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/70 external test program/mytest.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/70 external test program/mytest.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/70 external test program/mytest.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/70 external test program/mytest.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + + +import sys + +if sys.argv[1] == 'correct': + print('Argument is correct.') + sys.exit(0) +print('Argument is incorrect:', sys.argv[1]) +sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/70 modules/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/70 modules/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/70 modules/meson.build" 2020-01-07 21:07:17.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/70 modules/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('module test', 'c') - -modtest = import('modtest') -modtest.print_hello() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 ctarget dependency/gen1.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 ctarget dependency/gen1.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 ctarget dependency/gen1.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 ctarget dependency/gen1.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import time, sys + +# Make sure other script runs first if dependency +# is missing. +time.sleep(0.5) + +with open(sys.argv[1]) as f: + contents = f.read() +with open(sys.argv[2], 'w') as f: + f.write(contents) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 ctarget dependency/gen2.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 ctarget dependency/gen2.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 ctarget dependency/gen2.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 ctarget dependency/gen2.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +import sys, os +from glob import glob + +files = glob(os.path.join(sys.argv[1], '*.tmp')) +assert len(files) == 1 + +with open(files[0]) as ifile, open(sys.argv[2], 'w') as ofile: + ofile.write(ifile.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 ctarget dependency/input.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 ctarget dependency/input.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 ctarget dependency/input.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 ctarget dependency/input.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +This is a piece of text. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 ctarget dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 ctarget dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 ctarget dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 ctarget dependency/meson.build" 2021-10-23 16:48:35.000000000 +0000 @@ -0,0 +1,20 @@ +project('custom target dependency', 'c') + +# Sometimes custom targets do not take input files +# but instead do globbing or some similar wackiness. +# In this case we need to be able to specify a +# manual dependency between two custom targets, +# if one needs to be run before the other. + +g1 = find_program('gen1.py') +g2 = find_program('gen2.py') + +c1 = custom_target('medput', +input : 'input.dat', +output : 'medput.tmp', +command : [g1, '@INPUT@', '@OUTPUT@']) + +custom_target('output', +output : 'output.dat', +command : [g2, '@OUTDIR@', '@OUTPUT@'], +depends : c1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 should fail/failing.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 should fail/failing.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 should fail/failing.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 should fail/failing.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 should fail/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 should fail/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/71 should fail/meson.build" 2020-01-07 21:07:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/71 should fail/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('should fail', 'c') - -exe = executable('prog', 'failing.c') -test('failing', exe, should_fail : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/inc/confdata.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/inc/confdata.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/inc/confdata.in" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/inc/confdata.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -@VALUE@ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/inc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/inc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/inc/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/inc/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -cdata = configuration_data() -cdata.set('VALUE', '42') - -cfile = configure_file(input : 'confdata.in', -output : 'confdata', -configuration : cdata) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/meson.build" 2020-01-07 21:07:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('conf file in custom target', 'c') - -subdir('inc') -subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/src/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -custom_target('thing', -output : 'final.dat', -input : cfile, -command : [find_program('mycompiler.py'), '@INPUT@', '@OUTPUT@']) - -# Test usage of a `configure_file` as part of the command list -py3 = find_program('python3', required : false) -if not py3.found() - # Maybe 'python' is Python 3 - py3 = find_program('python') -endif - -compiler = configure_file(input : 'mycompiler.py', - output : 'mycompiler2.py', - copy: true) - -custom_target('thing2', -output : 'final2.dat', -input : cfile, -command : [py3, compiler, '@INPUT@', '@OUTPUT@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/src/mycompiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/src/mycompiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 configure file in custom target/src/mycompiler.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 configure file in custom target/src/mycompiler.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -with open(sys.argv[1]) as ifile: - if ifile.readline().strip() != '42': - print('Incorrect input') -with open(sys.argv[2], 'w') as ofile: - ofile.write('Success\n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/a.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include +char func_b(void); +char func_c(void); + +int main(void) { + if(func_b() != 'b') { + return 1; + } + if(func_c() != 'c') { + return 2; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/meson.build" 2021-10-23 16:48:37.000000000 +0000 @@ -0,0 +1,10 @@ +project('A', 'c') + +B = subproject('B') +b = B.get_variable('b') + +C = subproject('C') +c = C.get_variable('c') + +a = executable('a', 'a.c', link_with : [b, c]) +test('a test', a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/subprojects/B/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/subprojects/B/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/subprojects/B/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/subprojects/B/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,21 @@ +#include +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + + +char func_c(void); + +char DLL_PUBLIC func_b(void) { + if(func_c() != 'c') { + exit(3); + } + return 'b'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/subprojects/B/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/subprojects/B/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/subprojects/B/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/subprojects/B/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('B', 'c') +C = subproject('C') +c = C.get_variable('c') +b = library('b', 'b.c', link_with : c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/subprojects/C/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/subprojects/C/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/subprojects/C/c.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/subprojects/C/c.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +char DLL_PUBLIC func_c(void) { + return 'c'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/subprojects/C/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/subprojects/C/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/72 shared subproject/subprojects/C/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/72 shared subproject/subprojects/C/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('C', 'c') +c = library('c', 'c.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 external test program/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 external test program/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 external test program/meson.build" 2020-01-07 21:07:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 external test program/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('test is external', 'c') - -test('external', find_program('mytest.py'), args : ['correct']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 external test program/mytest.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 external test program/mytest.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 external test program/mytest.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 external test program/mytest.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import print_function - -import sys - -if sys.argv[1] == 'correct': - print('Argument is correct.') - sys.exit(0) -print('Argument is incorrect:', sys.argv[1]) -sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/a.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include +char func_b(void); +char func_c(void); + +int main(void) { + if(func_b() != 'b') { + return 1; + } + if(func_c() != 'c') { + return 2; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/meson.build" 2021-10-23 16:48:40.000000000 +0000 @@ -0,0 +1,13 @@ +project('A', 'c') + +# Same as the previous test but use C and B in +# the opposite order. + +C = subproject('C') +c = C.get_variable('c') + +B = subproject('B') +b = B.get_variable('b') + +a = executable('a', 'a.c', link_with : [b, c]) +test('a test', a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/subprojects/B/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/subprojects/B/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/subprojects/B/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/subprojects/B/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +#include +char func_c(void); + +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +char DLL_PUBLIC func_b(void) { + if(func_c() != 'c') { + exit(3); + } + return 'b'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/subprojects/B/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/subprojects/B/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/subprojects/B/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/subprojects/B/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('B', 'c') +C = subproject('C') +c = C.get_variable('c') +b = library('b', 'b.c', link_with : c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/subprojects/C/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/subprojects/C/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/subprojects/C/c.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/subprojects/C/c.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +char DLL_PUBLIC func_c(void) { + return 'c'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/subprojects/C/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/subprojects/C/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/73 shared subproject 2/subprojects/C/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/73 shared subproject 2/subprojects/C/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('C', 'c') +c = library('c', 'c.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 ctarget dependency/gen1.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 ctarget dependency/gen1.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 ctarget dependency/gen1.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 ctarget dependency/gen1.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#!/usr/bin/env python3 - -import time, sys - -# Make sure other script runs first if dependency -# is missing. -time.sleep(0.5) - -with open(sys.argv[1], 'r') as f: - contents = f.read() -with open(sys.argv[2], 'w') as f: - f.write(contents) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 ctarget dependency/gen2.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 ctarget dependency/gen2.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 ctarget dependency/gen2.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 ctarget dependency/gen2.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os -from glob import glob - -files = glob(os.path.join(sys.argv[1], '*.tmp')) -assert(len(files) == 1) - -with open(files[0], 'r') as ifile, open(sys.argv[2], 'w') as ofile: - ofile.write(ifile.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 ctarget dependency/input.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 ctarget dependency/input.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 ctarget dependency/input.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 ctarget dependency/input.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a piece of text. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 ctarget dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 ctarget dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 ctarget dependency/meson.build" 2020-01-07 21:07:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 ctarget dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -project('custom target dependency', 'c') - -# Sometimes custom targets do not take input files -# but instead do globbing or some similar wackiness. -# In this case we need to be able to specify a -# manual dependency between two custom targets, -# if one needs to be run before the other. - -g1 = find_program('gen1.py') -g2 = find_program('gen2.py') - -c1 = custom_target('medput', -input : 'input.dat', -output : 'medput.tmp', -command : [g1, '@INPUT@', '@OUTPUT@']) - -custom_target('output', -output : 'output.dat', -command : [g2, '@OUTDIR@', '@OUTPUT@'], -depends : c1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,8 @@ +project('file object', 'c') + +prog0 = files('prog.c') +lib0 = files('lib.c') +test('fobj', executable('fobj', prog0, lib0)) + +subdir('subdir1') +subdir('subdir2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include + +int func(void); /* Files in different subdirs return different values. */ + +int main(void) { + if(func() == 0) { + printf("Iz success.\n"); + } else { + printf("Iz fail.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir1/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir1/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir1/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir1/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +prog1 = files('prog.c') +lib1 = files('lib.c') + +test('subdir0', executable('subdir0', prog0, lib1), should_fail : true) +test('subdir1', executable('subdir1', prog1, lib0), should_fail : true) + +test('subdir2', executable('subdir2', prog1, lib1)) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir1/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir1/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir1/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir1/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include + +int func(void); + +int main(void) { + if(func() == 1) { + printf("Iz success.\n"); + } else { + printf("Iz fail.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir2/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir2/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir2/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir2/lib.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 2; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +prog2 = files('prog.c') +lib2 = files('lib.c') + +test('subdir3', executable('subdir3', prog1, lib2), should_fail : true) +test('subdir4', executable('subdir4', prog2, lib1), should_fail : true) + +test('subdir4', executable('subdir5', prog2, lib2)) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir2/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir2/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/74 file object/subdir2/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/74 file object/subdir2/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include + +int func(void); + +int main(void) { + if(func() == 2) { + printf("Iz success.\n"); + } else { + printf("Iz fail.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/a.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +#include +char func_b(void); +char func_c(void); + +int main(void) { + if(func_b() != 'b') { + return 1; + } + if(func_c() != 'c') { + return 2; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/custom_subproject_dir/B/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/custom_subproject_dir/B/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/custom_subproject_dir/B/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/custom_subproject_dir/B/b.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +#include +char func_c(void); + +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +char DLL_PUBLIC func_b(void) { + if(func_c() != 'c') { + exit(3); + } + return 'b'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/custom_subproject_dir/B/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/custom_subproject_dir/B/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/custom_subproject_dir/B/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/custom_subproject_dir/B/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('B', 'c') +C = subproject('C') +c = C.get_variable('c') +b = shared_library('b', 'b.c', link_with : c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/custom_subproject_dir/C/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/custom_subproject_dir/C/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/custom_subproject_dir/C/c.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/custom_subproject_dir/C/c.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +char DLL_PUBLIC func_c(void) { + return 'c'; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/custom_subproject_dir/C/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/custom_subproject_dir/C/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/custom_subproject_dir/C/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/custom_subproject_dir/C/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +project('C', 'c') +c = shared_library('c', 'c.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 custom subproject dir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 custom subproject dir/meson.build" 2021-10-23 16:48:40.000000000 +0000 @@ -0,0 +1,10 @@ +project('A', 'c', subproject_dir:'custom_subproject_dir') + +B = subproject('B') +b = B.get_variable('b') + +C = subproject('C') +c = C.get_variable('c') + +a = executable('a', 'a.c', link_with : [b, c]) +test('a test', a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/a.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include -char func_b(void); -char func_c(void); - -int main(void) { - if(func_b() != 'b') { - return 1; - } - if(func_c() != 'c') { - return 2; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/meson.build" 2020-01-07 21:07:24.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('A', 'c') - -B = subproject('B') -b = B.get_variable('b') - -C = subproject('C') -c = C.get_variable('c') - -a = executable('a', 'a.c', link_with : [b, c]) -test('a test', a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/subprojects/B/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/subprojects/B/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/subprojects/B/b.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/subprojects/B/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#include -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - - -char func_c(void); - -char DLL_PUBLIC func_b(void) { - if(func_c() != 'c') { - exit(3); - } - return 'b'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/subprojects/B/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/subprojects/B/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/subprojects/B/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/subprojects/B/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('B', 'c') -C = subproject('C') -c = C.get_variable('c') -b = shared_library('b', 'b.c', link_with : c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/subprojects/C/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/subprojects/C/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/subprojects/C/c.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/subprojects/C/c.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -char DLL_PUBLIC func_c(void) { - return 'c'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/subprojects/C/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/subprojects/C/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/75 shared subproject/subprojects/C/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/75 shared subproject/subprojects/C/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('C', 'c') -c = shared_library('c', 'c.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 has type/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 has type/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 has type/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 has type/meson.build" 2021-10-23 16:48:40.000000000 +0000 @@ -0,0 +1,13 @@ +project('has type', 'c', 'cpp') + +compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] + +foreach cc : compilers + if not cc.has_type('time_t', prefix : '#include') + error('Did not detect type that exists.') + endif + + if cc.has_type('no_time_t', prefix : '#include') + error('Not existing type found.') + endif +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/a.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include -char func_b(void); -char func_c(void); - -int main(void) { - if(func_b() != 'b') { - return 1; - } - if(func_c() != 'c') { - return 2; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/meson.build" 2020-01-07 21:07:24.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('A', 'c') - -# Same as the previous test but use C and B in -# the opposite order. - -C = subproject('C') -c = C.get_variable('c') - -B = subproject('B') -b = B.get_variable('b') - -a = executable('a', 'a.c', link_with : [b, c]) -test('a test', a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/subprojects/B/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/subprojects/B/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/subprojects/B/b.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/subprojects/B/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#include -char func_c(void); - -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -char DLL_PUBLIC func_b(void) { - if(func_c() != 'c') { - exit(3); - } - return 'b'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/subprojects/B/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/subprojects/B/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/subprojects/B/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/subprojects/B/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('B', 'c') -C = subproject('C') -c = C.get_variable('c') -b = shared_library('b', 'b.c', link_with : c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/subprojects/C/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/subprojects/C/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/subprojects/C/c.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/subprojects/C/c.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -char DLL_PUBLIC func_c(void) { - return 'c'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/subprojects/C/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/subprojects/C/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/76 shared subproject 2/subprojects/C/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/76 shared subproject 2/subprojects/C/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('C', 'c') -c = shared_library('c', 'c.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/meson.build" 2021-10-23 16:48:40.000000000 +0000 @@ -0,0 +1,8 @@ +project('Extract objects from subdirs', 'c') + +if meson.is_unity() + message('Unity build: skipping incompatible test') +else + subdir('src') + subdir('tst') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/src/first/lib_first.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/src/first/lib_first.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/src/first/lib_first.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/src/first/lib_first.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int first(void) { + return 1001; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/src/first/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/src/first/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/src/first/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/src/first/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +first_lib = shared_library('first_lib', 'lib_first.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +subdir('first') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/tst/first/exe_first.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/tst/first/exe_first.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/tst/first/exe_first.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/tst/first/exe_first.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int first(void); + +int main(void) { + return first() - 1001; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/tst/first/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/tst/first/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/tst/first/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/tst/first/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +first_exe = executable('first_exe', 'exe_first.c', + objects : first_lib.extract_objects('lib_first.c')) + +test('first_test', first_exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/tst/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/tst/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 extract from nested subdir/tst/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 extract from nested subdir/tst/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +subdir('first') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/meson.build" 2020-01-07 21:07:24.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('file object', 'c') - -prog0 = files('prog.c') -lib0 = files('lib.c') -test('fobj', executable('fobj', prog0, lib0)) - -subdir('subdir1') -subdir('subdir2') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include - -int func(void); /* Files in different subdirs return different values. */ - -int main(void) { - if(func() == 0) { - printf("Iz success.\n"); - } else { - printf("Iz fail.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir1/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir1/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir1/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir1/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -prog1 = files('prog.c') -lib1 = files('lib.c') - -test('subdir0', executable('subdir0', prog0, lib1), should_fail : true) -test('subdir1', executable('subdir1', prog1, lib0), should_fail : true) - -test('subdir2', executable('subdir2', prog1, lib1)) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir1/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir1/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir1/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir1/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include - -int func(void); - -int main(void) { - if(func() == 1) { - printf("Iz success.\n"); - } else { - printf("Iz fail.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir2/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir2/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir2/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir2/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 2; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir2/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -prog2 = files('prog.c') -lib2 = files('lib.c') - -test('subdir3', executable('subdir3', prog1, lib2), should_fail : true) -test('subdir4', executable('subdir4', prog2, lib1), should_fail : true) - -test('subdir4', executable('subdir5', prog2, lib2)) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir2/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir2/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/77 file object/subdir2/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/77 file object/subdir2/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include - -int func(void); - -int main(void) { - if(func() == 2) { - printf("Iz success.\n"); - } else { - printf("Iz fail.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/a.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#include -char func_b(void); -char func_c(void); - -int main(void) { - if(func_b() != 'b') { - return 1; - } - if(func_c() != 'c') { - return 2; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/custom_subproject_dir/B/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/custom_subproject_dir/B/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/custom_subproject_dir/B/b.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/custom_subproject_dir/B/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#include -char func_c(void); - -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -char DLL_PUBLIC func_b(void) { - if(func_c() != 'c') { - exit(3); - } - return 'b'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/custom_subproject_dir/B/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/custom_subproject_dir/B/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/custom_subproject_dir/B/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/custom_subproject_dir/B/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('B', 'c') -C = subproject('C') -c = C.get_variable('c') -b = shared_library('b', 'b.c', link_with : c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/custom_subproject_dir/C/c.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/custom_subproject_dir/C/c.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/custom_subproject_dir/C/c.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/custom_subproject_dir/C/c.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -char DLL_PUBLIC func_c(void) { - return 'c'; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/custom_subproject_dir/C/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/custom_subproject_dir/C/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/custom_subproject_dir/C/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/custom_subproject_dir/C/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('C', 'c') -c = shared_library('c', 'c.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 custom subproject dir/meson.build" 2020-01-07 21:07:26.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 custom subproject dir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('A', 'c', subproject_dir:'custom_subproject_dir') - -B = subproject('B') -b = B.get_variable('b') - -C = subproject('C') -c = C.get_variable('c') - -a = executable('a', 'a.c', link_with : [b, c]) -test('a test', a) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/meson.build" 2021-10-23 16:48:41.000000000 +0000 @@ -0,0 +1,4 @@ +project('internal dependency', 'c') + +subdir('proj1') +subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/include/proj1.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/include/proj1.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/include/proj1.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/include/proj1.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#pragma once + +void proj1_func1(void); +void proj1_func2(void); +void proj1_func3(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +incdirs = include_directories('include') + +p1lib = static_library('proj1', 'proj1f1.c', + include_directories : incdirs +) + +indirect_source = files('proj1f2.c') + +proj1_dep = declare_dependency(include_directories : incdirs, + link_with : p1lib, + sources : ['proj1f3.c', indirect_source]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/proj1f1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/proj1f1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/proj1f1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/proj1f1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include +#include + +void proj1_func1(void) { + printf("In proj1_func1.\n"); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/proj1f2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/proj1f2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/proj1f2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/proj1f2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include +#include + +void proj1_func2(void) { + printf("In proj1_func2.\n"); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/proj1f3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/proj1f3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/proj1/proj1f3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/proj1/proj1f3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include +#include + +void proj1_func3(void) { + printf("In proj1_func3.\n"); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/src/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/src/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/src/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/src/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include + +int main(void) { + printf("Now calling into library.\n"); + proj1_func1(); + proj1_func2(); + proj1_func3(); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/78 internal dependency/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/78 internal dependency/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +exe = executable('projtest', 'main.c', dependencies : proj1_dep) +test('projtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 has type/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 has type/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 has type/meson.build" 2020-01-07 21:07:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 has type/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('has type', 'c', 'cpp') - -compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] - -foreach cc : compilers - if not cc.has_type('time_t', prefix : '#include') - error('Did not detect type that exists.') - endif - - if cc.has_type('no_time_t', prefix : '#include') - error('Not existing type found.') - endif -endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/exe1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/exe1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/exe1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/exe1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int func(void); + +int main(void) { + return func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/exe2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/exe2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/exe2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/exe2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int func(void); + +int main(void) { + return func() == 1 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/lib.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,22 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +#if defined SHAR +int DLL_PUBLIC func(void) { + return 1; +} +#elif defined STAT +int func(void) { + return 0; +} +#else +#error "Missing type definition." +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/meson.build" 2021-10-23 16:48:42.000000000 +0000 @@ -0,0 +1,14 @@ +project('same basename', 'c') + +subdir('sharedsub') +subdir('staticsub') + +# Use the same source file to check that each top level target +# has its own unique working directory. If they don't +# then the .o files will clobber each other. + +exe1 = executable('name', 'exe1.c', link_with : stlib) +exe2 = executable('name2', 'exe2.c', link_with : shlib) + +test('static', exe1) +test('shared', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/sharedsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/sharedsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/sharedsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/sharedsub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +shlib = shared_library('name', '../lib.c', c_args : '-DSHAR') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/staticsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/staticsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/79 same basename/staticsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/79 same basename/staticsub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +# On Windows a static lib is now libfoo.a, so it does not conflict with foo.lib +# from the shared library above +stlib = static_library('name', '../lib.c', c_args : '-DSTAT') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/entity/entity1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/entity/entity1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/entity/entity1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/entity/entity1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#include"entity.h" + +#ifdef USING_ENT +#error "Entity use flag leaked into entity compilation." +#endif + +int entity_func1(void) { + return 5; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/entity/entity2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/entity/entity2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/entity/entity2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/entity/entity2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int entity_func2(void) { + return 9; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/entity/entity.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/entity/entity.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/entity/entity.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/entity/entity.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +#pragma once + +int entity_func1(void); +int entity_func2(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/entity/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/entity/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/entity/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/entity/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +entity_lib = static_library('entity', 'entity1.c') + +entity_dep = declare_dependency(link_with : [[entity_lib]], + include_directories : [['.']], + sources : 'entity2.c', + compile_args : ['-DUSING_ENT=1'], + version : '1.2.3', + link_args : []) # No simple way of testing linker flags :(. + +assert(entity_dep.version().version_compare('==1.2.3'), 'Declare_dep has incorrect version string.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#include +#include + +#ifndef USING_ENT +#error "Entity use flag not used for compilation." +#endif + +int main(void) { + if(entity_func1() != 5) { + printf("Error in func1.\n"); + return 1; + } + if(entity_func2() != 9) { + printf("Error in func2.\n"); + return 2; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 declare dep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 declare dep/meson.build" 2021-10-23 16:48:43.000000000 +0000 @@ -0,0 +1,24 @@ +project('declare dependency', 'c') + +subdir('entity') + +exe = executable('dep_user', 'main.c', + dependencies : entity_dep) +test('dep', exe) + +# just to make sure [] works as a no-op dep here +executable('dummy', 'main.c', + dependencies : [entity_dep, []]) + +# simple case +declare_dependency(dependencies : entity_dep) + +# nested deps should be flattened +declare_dependency(dependencies : [entity_dep]) +declare_dependency(dependencies : [[entity_dep]]) + +# check that [] properly works as a no-op dep in declare_dependency() too +declare_dependency(dependencies : []) +declare_dependency(dependencies : [[]]) +declare_dependency(dependencies : [entity_dep, []]) +declare_dependency(dependencies : [[], entity_dep]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/meson.build" 2020-01-07 21:07:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('Extract objects from subdirs.', 'c') - -if meson.is_unity() - message('Unity build: skipping incompatible test') -else - subdir('src') - subdir('tst') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/src/first/lib_first.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/src/first/lib_first.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/src/first/lib_first.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/src/first/lib_first.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int first(void) { - return 1001; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/src/first/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/src/first/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/src/first/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/src/first/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -first_lib = shared_library('first_lib', 'lib_first.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/src/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -subdir('first') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/tst/first/exe_first.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/tst/first/exe_first.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/tst/first/exe_first.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/tst/first/exe_first.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int first(void); - -int main(void) { - return first() - 1001; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/tst/first/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/tst/first/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/tst/first/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/tst/first/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -first_exe = executable('first_exe', 'exe_first.c', - objects : first_lib.extract_objects('lib_first.c')) - -test('first_test', first_exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/tst/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/tst/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/80 extract from nested subdir/tst/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/80 extract from nested subdir/tst/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -subdir('first') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/extractor.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/extractor.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/extractor.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/extractor.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#pragma once + +int func1(void); +int func2(void); +int func3(void); +int func4(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/four.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/four.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/four.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/four.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func4(void) { + return 4; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/meson.build" 2021-10-23 16:48:43.000000000 +0000 @@ -0,0 +1,13 @@ +project('extract all', 'c') + +a = static_library('a', 'one.c', 'two.c') +b = static_library('b', 'three.c', 'four.c') +c = static_library('c', objects : [a.extract_all_objects(), b.extract_all_objects()]) +d = static_library('d', objects : [a.extract_all_objects(), b.extract_all_objects(), c.extract_all_objects()]) +d_recursive = static_library('d_recursive', objects : [c.extract_all_objects(recursive : true)]) + +e = executable('proggie', 'prog.c', link_with : d) +test('extall', e) + +e = executable('proggie_recursive', 'prog.c', link_with : d_recursive) +test('extall_recursive', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/one.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/one.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/one.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/one.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func1(void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include"extractor.h" +#include + +int main(void) { + if((1+2+3+4) != (func1() + func2() + func3() + func4())) { + printf("Arithmetic is fail.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/three.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/three.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/three.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/three.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func3(void) { + return 3; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/two.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/two.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 extract all/two.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 extract all/two.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func2(void) { + return 2; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/meson.build" 2020-01-07 21:07:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('internal dependency', 'c') - -subdir('proj1') -subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/include/proj1.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/include/proj1.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/include/proj1.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/include/proj1.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#pragma once - -void proj1_func1(void); -void proj1_func2(void); -void proj1_func3(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -incdirs = include_directories('include') - -p1lib = static_library('proj1', 'proj1f1.c', - include_directories : incdirs -) - -indirect_source = files('proj1f2.c') - -proj1_dep = declare_dependency(include_directories : incdirs, - link_with : p1lib, - sources : ['proj1f3.c', indirect_source]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/proj1f1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/proj1f1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/proj1f1.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/proj1f1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include -#include - -void proj1_func1(void) { - printf("In proj1_func1.\n"); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/proj1f2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/proj1f2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/proj1f2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/proj1f2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include -#include - -void proj1_func2(void) { - printf("In proj1_func2.\n"); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/proj1f3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/proj1f3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/proj1/proj1f3.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/proj1/proj1f3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include -#include - -void proj1_func3(void) { - printf("In proj1_func3.\n"); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/src/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/src/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/src/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/src/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include -#include - -int main(void) { - printf("Now calling into library.\n"); - proj1_func1(); - proj1_func2(); - proj1_func3(); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/81 internal dependency/src/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/81 internal dependency/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -exe = executable('projtest', 'main.c', dependencies : proj1_dep) -test('projtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 add language/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 add language/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 add language/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 add language/meson.build" 2021-10-23 16:48:46.000000000 +0000 @@ -0,0 +1,10 @@ +project('add language', 'c') + +test('C', executable('cprog', 'prog.c')) + +assert(add_languages('cpp', native: false), 'Add_languages returned false on success') +assert(not add_languages('klingon', required : false), 'Add_languages returned true on failure.') + +test('C++', executable('cppprog', 'prog.cc')) + +add_languages('c', native: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 add language/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 add language/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 add language/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 add language/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I am plain C.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 add language/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 add language/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 add language/prog.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 add language/prog.cc" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(int, char**) { + std::cout << "I am C++.\n"; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/exe1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/exe1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/exe1.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/exe1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int func(void); - -int main(void) { - return func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/exe2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/exe2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/exe2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/exe2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int func(void); - -int main(void) { - return func() == 1 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/lib.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -#if defined _WIN32 || defined __CYGWIN__ -#define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -#if defined SHAR -int DLL_PUBLIC func(void) { - return 1; -} -#elif defined STAT -int func(void) { - return 0; -} -#else -#error "Missing type definition." -#endif - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/meson.build" 2020-01-07 21:07:30.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('same basename', 'c') - -subdir('sharedsub') -subdir('staticsub') - -# Use the same source file to check that each top level target -# has its own unique working directory. If they don't -# then the .o files will clobber each other. - -exe1 = executable('name', 'exe1.c', link_with : stlib) -exe2 = executable('name2', 'exe2.c', link_with : shlib) - -test('static', exe1) -test('shared', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/sharedsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/sharedsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/sharedsub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/sharedsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -shlib = shared_library('name', '../lib.c', c_args : '-DSHAR') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/staticsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/staticsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/82 same basename/staticsub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/82 same basename/staticsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -# On Windows a static lib is now libfoo.a, so it does not conflict with foo.lib -# from the shared library above -stlib = static_library('name', '../lib.c', c_args : '-DSTAT') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/entity/entity1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/entity/entity1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/entity/entity1.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/entity/entity1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#include"entity.h" - -#ifdef USING_ENT -#error "Entity use flag leaked into entity compilation." -#endif - -int entity_func1(void) { - return 5; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/entity/entity2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/entity/entity2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/entity/entity2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/entity/entity2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -int entity_func2(void) { - return 9; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/entity/entity.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/entity/entity.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/entity/entity.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/entity/entity.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -#pragma once - -int entity_func1(void); -int entity_func2(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/entity/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/entity/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/entity/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/entity/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -entity_lib = static_library('entity', 'entity1.c') - -entity_dep = declare_dependency(link_with : [[entity_lib]], - include_directories : [['.']], - sources : 'entity2.c', - compile_args : ['-DUSING_ENT=1'], - version : '1.2.3', - link_args : []) # No simple way of testing linker flags :(. - -assert(entity_dep.version().version_compare('==1.2.3'), 'Declare_dep has incorrect version string.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/main.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#include -#include - -#ifndef USING_ENT -#error "Entity use flag not used for compilation." -#endif - -int main(void) { - if(entity_func1() != 5) { - printf("Error in func1.\n"); - return 1; - } - if(entity_func2() != 9) { - printf("Error in func2.\n"); - return 2; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 declare dep/meson.build" 2020-01-07 21:07:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 declare dep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -project('declare dependency', 'c') - -subdir('entity') - -exe = executable('dep_user', 'main.c', - dependencies : entity_dep) -test('dep', exe) - -# just to make sure [] works as a no-op dep here -executable('dummy', 'main.c', - dependencies : [entity_dep, []]) - -# simple case -declare_dependency(dependencies : entity_dep) - -# nested deps should be flattened -declare_dependency(dependencies : [entity_dep]) -declare_dependency(dependencies : [[entity_dep]]) - -# check that [] properly works as a no-op dep in declare_dependency() too -declare_dependency(dependencies : []) -declare_dependency(dependencies : [[]]) -declare_dependency(dependencies : [entity_dep, []]) -declare_dependency(dependencies : [[], entity_dep]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/bar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/bar.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I'm a main project bar.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/meson.build" 2021-10-23 16:48:45.000000000 +0000 @@ -0,0 +1,9 @@ +project('toplevel bar', 'c') + +subproject('foo') + +true_cmd = find_program('true.py') + +executable('bar', 'bar.c') +run_target('nop', command : [true_cmd]) +custom_target('cus', output: ['cus.c'], command : [true_cmd]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/subprojects/foo/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/subprojects/foo/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/subprojects/foo/bar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/subprojects/foo/bar.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I'm a subproject bar.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/subprojects/foo/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +project('subfoo', 'c') + +true_cmd = find_program('true.py') + +executable('bar', 'bar.c') +run_target('nop', command : [true_cmd]) +custom_target('cus', output: ['cus.c'], command : [true_cmd]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/subprojects/foo/true.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/subprojects/foo/true.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/subprojects/foo/true.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/subprojects/foo/true.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +if __name__ == '__main__': + pass diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/true.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/true.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/83 identical target name in subproject/true.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/83 identical target name in subproject/true.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +if __name__ == '__main__': + pass diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/extractor.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/extractor.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/extractor.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/extractor.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#pragma once - -int func1(void); -int func2(void); -int func3(void); -int func4(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/four.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/four.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/four.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/four.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"extractor.h" - -int func4(void) { - return 4; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/meson.build" 2020-01-07 21:07:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -project('extract all', 'c') - -a = static_library('a', 'one.c', 'two.c') -b = static_library('b', 'three.c', 'four.c') -c = static_library('c', objects : [a.extract_all_objects(), b.extract_all_objects()]) -d = static_library('d', objects : [a.extract_all_objects(), b.extract_all_objects(), c.extract_all_objects()]) -d_recursive = static_library('d_recursive', objects : [c.extract_all_objects(recursive : true)]) - -e = executable('proggie', 'prog.c', link_with : d) -test('extall', e) - -e = executable('proggie_recursive', 'prog.c', link_with : d_recursive) -test('extall_recursive', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/one.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/one.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/one.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/one.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"extractor.h" - -int func1(void) { - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include"extractor.h" -#include - -int main(void) { - if((1+2+3+4) != (func1() + func2() + func3() + func4())) { - printf("Arithmetic is fail.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/three.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/three.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/three.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/three.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"extractor.h" - -int func3(void) { - return 3; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/two.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/two.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 extract all/two.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 extract all/two.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"extractor.h" - -int func2(void) { - return 2; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 plusassign/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 plusassign/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/84 plusassign/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/84 plusassign/meson.build" 2021-10-23 16:48:45.000000000 +0000 @@ -0,0 +1,70 @@ +project('plusassign', 'c') + +x = [] + +x += 'a' + +if x.length() != 1 + error('Incorrect append') +endif + +if x[0] != 'a' + error('Incorrect append 2.') +endif + +y = x + +x += 'b' + +if y.length() != 1 + error('Immutability broken.') +endif + +if y[0] != 'a' + error('Immutability broken 2.') +endif + +if x.length() != 2 + error('Incorrect append 3') +endif + +if x[0] != 'a' + error('Incorrect append 4.') +endif + +if x[1] != 'b' + error('Incorrect append 5.') +endif + +# Now with evil added: append yourself. + +x += x + +if x.length() != 4 + error('Incorrect selfappend.') +endif + +# += on strings + +bra = 'bra' +foo = 'A' +foo += bra +foo += 'cada' +foo += bra +assert (foo == 'Abracadabra', 'string += failure [@0@]'.format(foo)) +assert (bra == 'bra', 'string += modified right argument!') +foo += ' ' + foo +assert (foo == 'Abracadabra Abracadabra', 'string += failure [@0@]'.format(foo)) + +# += on ints + +foo = 5 +foo += 6 +assert (foo == 11, 'int += failure [@0@]'.format(foo)) +bar = 99 +foo += bar +assert (foo == 110, 'int += failure [@0@]'.format(foo)) +assert (bar == 99, 'int += modified right argument"') +bar += foo + 1 +assert (bar == 210, 'int += failure [@0@]'.format(bar)) +assert (foo == 110, 'int += modified right argument"') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 add language/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 add language/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 add language/meson.build" 2020-01-07 21:07:33.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 add language/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('add language', 'c') - -test('C', executable('cprog', 'prog.c')) - -assert(add_languages('cpp'), 'Add_languages returned false on success') -assert(not add_languages('klingon', required : false), 'Add_languages returned true on failure.') - -test('C++', executable('cppprog', 'prog.cc')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 add language/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 add language/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 add language/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 add language/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I am plain C.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 add language/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 add language/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 add language/prog.cc" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 add language/prog.cc" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(int, char**) { - std::cout << "I am C++.\n"; - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 skip subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 skip subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 skip subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 skip subdir/meson.build" 2021-10-23 16:48:45.000000000 +0000 @@ -0,0 +1,3 @@ +project('foo', 'c') + +subdir('subdir1/subdir2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 skip subdir/subdir1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 skip subdir/subdir1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 skip subdir/subdir1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 skip subdir/subdir1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +error('This should not be called.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 skip subdir/subdir1/subdir2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 skip subdir/subdir1/subdir2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/85 skip subdir/subdir1/subdir2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/85 skip subdir/subdir1/subdir2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +message('I\'m in subdir subdir.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 identical target name in subproject/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 identical target name in subproject/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 identical target name in subproject/bar.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 identical target name in subproject/bar.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I'm a main project bar.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 identical target name in subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 identical target name in subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 identical target name in subproject/meson.build" 2020-01-07 21:07:33.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 identical target name in subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('toplevel bar', 'c') - -subproject('foo') - -executable('bar', 'bar.c') -run_target('nop', command : ['true']) -custom_target('cus', output: ['cus.c'], command : ['true']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 identical target name in subproject/subprojects/foo/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 identical target name in subproject/subprojects/foo/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 identical target name in subproject/subprojects/foo/bar.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 identical target name in subproject/subprojects/foo/bar.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I'm a subproject bar.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 identical target name in subproject/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 identical target name in subproject/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 identical target name in subproject/subprojects/foo/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 identical target name in subproject/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('subfoo', 'c') - -executable('bar', 'bar.c') -run_target('nop', command : ['true']) -custom_target('cus', output: ['cus.c'], command : ['true']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/meson.build" 2021-10-23 16:48:46.000000000 +0000 @@ -0,0 +1,4 @@ +project('access private', 'c') + +subdir('stlib') +subdir('user') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/stlib/compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/stlib/compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/stlib/compiler.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/stlib/compiler.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import sys, os + +assert len(sys.argv) == 3 + +h_templ = '''#pragma once +unsigned int %s(void); +''' + +c_templ = '''#include"%s.h" + +unsigned int %s(void) { + return 0; +} +''' + +ifile = sys.argv[1] +outdir = sys.argv[2] + +base = os.path.splitext(os.path.split(ifile)[-1])[0] + +cfile = os.path.join(outdir, base + '.c') +hfile = os.path.join(outdir, base + '.h') + +c_code = c_templ % (base, base) +h_code = h_templ % base + +with open(cfile, 'w') as f: + f.write(c_code) +with open(hfile, 'w') as f: + f.write(h_code) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/stlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/stlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/stlib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/stlib/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +genbin = find_program('compiler.py') + +gen = generator(genbin, + output : ['@BASENAME@.h', '@BASENAME@.c'], + arguments : ['@INPUT@', '@BUILD_DIR@'] + ) + +defs = ['foo1.def', 'foo2.def'] +generated = gen.process(defs) + +stlib = static_library('st', generated) +st_priv_inc = stlib.private_dir_include() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/user/libuser.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/user/libuser.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/user/libuser.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/user/libuser.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include"foo1.h" +#include"foo2.h" + +int main(void) { + return foo1() + foo2(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/user/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/user/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/86 private include/user/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/86 private include/user/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +exe = executable('libuser', 'libuser.c', + link_with : stlib, + include_directories : st_priv_inc) + +test('libuser', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/87 default options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/87 default options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/87 default options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/87 default options/meson.build" 2021-10-23 16:48:48.000000000 +0000 @@ -0,0 +1,33 @@ +project('default options', 'cpp', 'c', default_options : [ + 'prefix=/absoluteprefix', + 'buildtype=debugoptimized', + 'cpp_std=c++11', + 'cpp_eh=none', + 'warning_level=3', + 'sub1:test_option=false', + ]) + +assert(get_option('buildtype') == 'debugoptimized', 'Build type default value wrong.') + +cpp_eh = get_option('cpp_eh') +assert(cpp_eh == 'none', 'EH value is "' + cpp_eh + '" instead of "none"') +cpp_std = get_option('cpp_std') +assert(cpp_std == 'c++11', 'C++ std value is "' + cpp_std + '" instead of c++11.') + +w_level = get_option('warning_level') +assert(w_level == '3', 'warning level "' + w_level + '" instead of "3"') + +# FIXME. Since we no longer accept invalid options to c_std etc, +# there is no simple way to test this. Gcc does not seem to expose +# the C std used in a preprocessor token so we can't check for it. +# Think of a way to fix this. +# +# # Verify that project args are not used when told not to. +# # MSVC plain C does not have a simple arg to test so skip it. +# if cpp.get_id() != 'msvc' +# cc = meson.get_compiler('c') +# assert(not cc.compiles('int foobar;'), 'Default arg not used in test.') +# assert(cc.compiles('int foobar;', no_builtin_args : true), 'No_builtin did not disable builtins.') +# endif + +subproject('sub1') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/87 default options/subprojects/sub1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/87 default options/subprojects/sub1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/87 default options/subprojects/sub1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/87 default options/subprojects/sub1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('sub1') + +assert(get_option('test_option') == false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/87 default options/subprojects/sub1/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/87 default options/subprojects/sub1/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/87 default options/subprojects/sub1/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/87 default options/subprojects/sub1/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +option('test_option', type : 'boolean', value : true, description : 'Test option. Superproject overrides default to "false"') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/87 plusassign/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/87 plusassign/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/87 plusassign/meson.build" 2020-01-07 21:07:34.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/87 plusassign/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -project('plusassign', 'c') - -x = [] - -x += 'a' - -if x.length() != 1 - error('Incorrect append') -endif - -if x[0] != 'a' - error('Incorrect append 2.') -endif - -y = x - -x += 'b' - -if y.length() != 1 - error('Immutability broken.') -endif - -if y[0] != 'a' - error('Immutability broken 2.') -endif - -if x.length() != 2 - error('Incorrect append 3') -endif - -if x[0] != 'a' - error('Incorrect append 4.') -endif - -if x[1] != 'b' - error('Incorrect append 5.') -endif - -# Now with evil added: append yourself. - -x += x - -if x.length() != 4 - error('Incorrect selfappend.') -endif - -# += on strings - -bra = 'bra' -foo = 'A' -foo += bra -foo += 'cada' -foo += bra -assert (foo == 'Abracadabra', 'string += failure [@0@]'.format(foo)) -assert (bra == 'bra', 'string += modified right argument!') -foo += ' ' + foo -assert (foo == 'Abracadabra Abracadabra', 'string += failure [@0@]'.format(foo)) - -# += on ints - -foo = 5 -foo += 6 -assert (foo == 11, 'int += failure [@0@]'.format(foo)) -bar = 99 -foo += bar -assert (foo == 110, 'int += failure [@0@]'.format(foo)) -assert (bar == 99, 'int += modified right argument"') -bar += foo + 1 -assert (bar == 210, 'int += failure [@0@]'.format(bar)) -assert (foo == 110, 'int += modified right argument"') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/gensrc.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/gensrc.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/gensrc.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/gensrc.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/meson.build" 2021-10-23 16:48:51.000000000 +0000 @@ -0,0 +1,38 @@ +project('dep fallback', 'c') + +bob = dependency('boblib', fallback : ['boblib', 'bob_dep'], required: false, + default_options : 'warning_level=1') +if not bob.found() + error('Bob is actually needed') +endif + +# boblib subproject exists, but bobinc is not a dependency variable +sita = dependency('sitalib', fallback : ['boblib', 'bobinc'], required: false) +assert(not sita.found()) +# boblib subproject exists, but sita_dep doesn't exist +sita = dependency('sitalib', fallback : ['boblib', 'sita_dep'], required: false) +assert(not sita.found()) +# boblib has been configured so zlib cannot be searched on the system +zlib = dependency('zlib', fallback : ['boblib', 'notfound_dep'], required: false) +assert(not zlib.found()) +# boblib has been configured so zlib cannot be searched on the system. +# Not variable name provided and the subproject does not override zlib. +zlib = dependency('zlib', fallback : 'boblib', required: false) +assert(not zlib.found()) + +# jimmylib subproject doesn't exist +jimmy = dependency('jimmylib', fallback : ['jimmylib', 'jimmy_dep'], required: false) +# dummylib subproject fails to configure +dummy = dependency('dummylib', fallback : ['dummylib', 'dummy_dep'], required: false) + +gensrc_py = find_program('gensrc.py') +gensrc = custom_target('gensrc.c', + input : 'tester.c', + output : 'gensrc.c', + command : [gensrc_py, '@INPUT@', '@OUTPUT@']) + +exe = executable('bobtester', + [gensrc], + dependencies : bob) + +test('bobtester', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/boblib/bob.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/boblib/bob.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/boblib/bob.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/boblib/bob.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include"bob.h" + +#ifdef _MSC_VER +__declspec(dllexport) +#endif +const char* get_bob(void) { + return "bob"; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/boblib/bob.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/boblib/bob.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/boblib/bob.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/boblib/bob.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#pragma once + +#ifdef _MSC_VER +__declspec(dllimport) +#endif +const char* get_bob(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/boblib/genbob.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/boblib/genbob.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/boblib/genbob.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/boblib/genbob.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys + +with open(sys.argv[1], 'w') as f: + f.write('') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/boblib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/boblib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/boblib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/boblib/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,18 @@ +project('bob', 'c') + +gensrc_py = find_program('genbob.py') +genbob_h = custom_target('genbob.h', + output : 'genbob.h', + command : [gensrc_py, '@OUTPUT@']) +genbob_c = custom_target('genbob.c', + output : 'genbob.c', + command : [gensrc_py, '@OUTPUT@']) + +boblib = library('bob', ['bob.c', genbob_c]) +bobinc = include_directories('.') + +bob_dep = declare_dependency(link_with : boblib, + sources : [genbob_h], + include_directories : bobinc) + +notfound_dep = dependency('', required: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/dummylib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/dummylib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/subprojects/dummylib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/subprojects/dummylib/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('dummylib', 'c') + +dummy_dep = declare_dependency() +error('this subproject fails to configure') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/tester.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/tester.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 dep fallback/tester.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 dep fallback/tester.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#include"bob.h" +#include"genbob.h" +#include +#include + +int main(void) { + if(strcmp("bob", get_bob()) == 0) { + printf("Bob is indeed bob.\n"); + } else { + printf("ERROR: bob is not bob.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 skip subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 skip subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 skip subdir/meson.build" 2020-01-07 21:07:34.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 skip subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('foo', 'c') - -subdir('subdir1/subdir2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 skip subdir/subdir1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 skip subdir/subdir1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 skip subdir/subdir1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 skip subdir/subdir1/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -error('This should not be called.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 skip subdir/subdir1/subdir2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 skip subdir/subdir1/subdir2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/88 skip subdir/subdir1/subdir2/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/88 skip subdir/subdir1/subdir2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -message('I\'m in subdir subdir.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 default library/ef.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 default library/ef.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 default library/ef.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 default library/ef.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include"ef.h" + +DLL_PUBLIC Ef::Ef() : x(99) { +} + +int DLL_PUBLIC Ef::get_x() const { + return x; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 default library/ef.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 default library/ef.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 default library/ef.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 default library/ef.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,22 @@ +#pragma once + +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +class Ef { +private: + int x; + +public: + + DLL_PUBLIC Ef(); + int DLL_PUBLIC get_x() const; +}; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 default library/eftest.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 default library/eftest.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 default library/eftest.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 default library/eftest.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#include"ef.h" + +#include + +int main(int, char **) { + Ef var; + if(var.get_x() == 99) { + std::cout << "All is fine.\n"; + return 0; + } else { + std::cout << "Something went wrong.\n"; + return 1; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 default library/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 default library/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 default library/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 default library/meson.build" 2021-10-23 16:48:50.000000000 +0000 @@ -0,0 +1,10 @@ +project('default library', 'cpp') + +flib = library('ef', 'ef.cpp') +exe = executable('eftest', 'eftest.cpp', link_with : flib) +test('eftest', exe) + +# Same as above, but using build_target() +flib2 = build_target('ef2', 'ef.cpp', target_type: 'library') +exe2 = executable('eftest2', 'eftest.cpp', link_with : flib2) +test('eftest2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/meson.build" 2020-01-07 21:07:36.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('access private', 'c') - -subdir('stlib') -subdir('user') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/stlib/compiler.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/stlib/compiler.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/stlib/compiler.py" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/stlib/compiler.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os - -assert(len(sys.argv) == 3) - -h_templ = '''#pragma once -unsigned int %s(void); -''' - -c_templ = '''#include"%s.h" - -unsigned int %s(void) { - return 0; -} -''' - -ifile = sys.argv[1] -outdir = sys.argv[2] - -base = os.path.splitext(os.path.split(ifile)[-1])[0] - -cfile = os.path.join(outdir, base + '.c') -hfile = os.path.join(outdir, base + '.h') - -c_code = c_templ % (base, base) -h_code = h_templ % base - -with open(cfile, 'w') as f: - f.write(c_code) -with open(hfile, 'w') as f: - f.write(h_code) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/stlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/stlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/stlib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/stlib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -genbin = find_program('compiler.py') - -gen = generator(genbin, - output : ['@BASENAME@.h', '@BASENAME@.c'], - arguments : ['@INPUT@', '@BUILD_DIR@'] - ) - -defs = ['foo1.def', 'foo2.def'] -generated = gen.process(defs) - -stlib = static_library('st', generated) -st_priv_inc = stlib.private_dir_include() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/user/libuser.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/user/libuser.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/user/libuser.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/user/libuser.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include"foo1.h" -#include"foo2.h" - -int main(void) { - return foo1() + foo2(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/user/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/user/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/89 private include/user/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/89 private include/user/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -exe = executable('libuser', 'libuser.c', - link_with : stlib, - include_directories : st_priv_inc) - -test('libuser', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/8 install/gendir.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/8 install/gendir.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/8 install/gendir.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/8 install/gendir.py" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys, os + +dirname = sys.argv[1] +fname = os.path.join(dirname, 'file.txt') +os.makedirs(dirname, exist_ok=True) +open(fname, 'w').close() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/8 install/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/8 install/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/8 install/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/8 install/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb -usr/libtest/libstat.a diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/8 install/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/8 install/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/8 install/meson.build" 2020-01-07 21:06:15.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/8 install/meson.build" 2021-10-23 16:47:48.000000000 +0000 @@ -2,3 +2,9 @@ stlib = static_library('stat', 'stat.c', install : true) exe = executable('prog', 'prog.c', install : true) + +dirtarget = custom_target('dirtarget', + output: ['dir'], + install: true, + command: [find_program('gendir.py'), '@OUTPUT@'], + install_dir: get_option('datadir')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/8 install/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/8 install/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/8 install/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/8 install/test.json" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "installed": [ + { "type": "exe", "file": "usr/bin/prog" }, + { "type": "pdb", "file": "usr/bin/prog" }, + { "type": "file", "file": "usr/share/dir/file.txt" }, + { "type": "file", "file": "usr/libtest/libstat.a" } + ], + "do_not_set_opts": ["libdir"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 default options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 default options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 default options/meson.build" 2020-01-07 21:07:37.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 default options/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -project('default options', 'cpp', 'c', default_options : [ - 'prefix=/absoluteprefix', - 'buildtype=debugoptimized', - 'cpp_std=c++11', - 'cpp_eh=none', - 'warning_level=3', - ]) - -assert(get_option('buildtype') == 'debugoptimized', 'Build type default value wrong.') - -cpp_eh = get_option('cpp_eh') -assert(cpp_eh == 'none', 'EH value is "' + cpp_eh + '" instead of "none"') -cpp_std = get_option('cpp_std') -assert(cpp_std == 'c++11', 'C++ std value is "' + cpp_std + '" instead of c++11.') - -w_level = get_option('warning_level') -assert(w_level == '3', 'warning level "' + w_level + '" instead of "3"') - -# FIXME. Since we no longer accept invalid options to c_std etc, -# there is no simple way to test this. Gcc does not seem to expose -# the C std used in a preprocessor token so we can't check for it. -# Think of a way to fix this. -# -# # Verify that project args are not used when told not to. -# # MSVC plain C does not have a simple arg to test so skip it. -# if cpp.get_id() != 'msvc' -# cc = meson.get_compiler('c') -# assert(not cc.compiles('int foobar;'), 'Default arg not used in test.') -# assert(cc.compiles('int foobar;', no_builtin_args : true), 'No_builtin did not disable builtins.') -# endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/meson.build" 2021-10-23 16:48:51.000000000 +0000 @@ -0,0 +1,40 @@ +project('extra args in gen', 'c') + +prog = find_program('srcgen.py') + +gen = generator(prog, + output : '@BASENAME@.c', + arguments : ['--input=@INPUT@', '--output=@OUTPUT@', '@EXTRA_ARGS@']) + +g1 = gen.process('name.dat') +g2 = gen.process('name.dat', extra_args: '--upper') + +test('basic', executable('basic', 'plain.c', g1)) +test('upper', executable('upper', 'upper.c', g2)) + +prog2 = find_program('srcgen2.py') +basename_gen = generator(prog2, + output : ['@BASENAME@.tab.c', '@BASENAME@.tab.h'], + arguments : ['@BUILD_DIR@', '@BASENAME@', '@INPUT@']) + +basename_src = basename_gen.process('name.l') + +test('basename', executable('basename', basename_src)) + +plainname_gen = generator(prog2, + output : ['@PLAINNAME@.tab.c', '@PLAINNAME@.tab.h'], + arguments : ['@BUILD_DIR@', '@PLAINNAME@', '@INPUT@']) + +plainname_src = plainname_gen.process('name.l') + +test('plainname', executable('plainname', plainname_src)) + +prog3 = find_program('srcgen3.py') +capture_gen = generator(prog3, + output : ['@BASENAME@.yy.c'], + arguments : ['@INPUT@'], + capture : true) + +capture_src = capture_gen.process('name.l') + +test('capture', executable('capture', capture_src)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/name.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/name.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/name.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/name.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +bob_mcbob diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/name.l" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/name.l" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/name.l" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/name.l" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { +return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/plain.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/plain.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/plain.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/plain.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int bob_mcbob(void); + +int main(void) { + return bob_mcbob(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/srcgen2.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/srcgen2.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/srcgen2.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/srcgen2.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import os +import sys +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument('target_dir', + help='the target dir') +parser.add_argument('stem', + help='the stem') +parser.add_argument('input', + help='the input file') + +options = parser.parse_args(sys.argv[1:]) + +with open(options.input) as f: + content = f.read() + + +output_c = os.path.join(options.target_dir, options.stem + ".tab.c") +with open(output_c, 'w') as f: + f.write(content) + + +output_h = os.path.join(options.target_dir, options.stem + ".tab.h") +h_content = '''#pragma once + +int myfun(void); +''' +with open(output_h, 'w') as f: + f.write(h_content) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/srcgen3.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/srcgen3.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/srcgen3.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/srcgen3.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import sys +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument('input', + help='the input file') + +options = parser.parse_args(sys.argv[1:]) + +with open(options.input) as f: + content = f.read().strip() + +print(content) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/srcgen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/srcgen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/srcgen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/srcgen.py" 2021-10-23 16:43:19.000000000 +0000 @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +import sys +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument('--input', dest='input', + help='the input file') +parser.add_argument('--output', dest='output', + help='the output file') +parser.add_argument('--upper', dest='upper', action='store_true', default=False, + help='Convert to upper case.') + +c_templ = '''int %s(void) { + return 0; +} +''' + +options = parser.parse_args(sys.argv[1:]) + +with open(options.input) as f: + funcname = f.readline().strip() +if options.upper: + funcname = funcname.upper() + +with open(options.output, 'w') as f: + f.write(c_templ % funcname) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/upper.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/upper.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/90 gen extra/upper.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/90 gen extra/upper.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +int BOB_MCBOB(void); + +int main(void) { + return BOB_MCBOB(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 benchmark/delayer.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 benchmark/delayer.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 benchmark/delayer.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 benchmark/delayer.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,20 @@ +/* Simple prog that sleeps for a random time. */ + +#include +#include +#if defined(_WIN32) +#include +#endif + +int main(void) { + srand(time(NULL)); +#if !defined(_WIN32) + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 199999999.0*rand()/RAND_MAX; + nanosleep(&t, NULL); +#else + Sleep(50.0*rand()/RAND_MAX); +#endif + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 benchmark/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 benchmark/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 benchmark/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 benchmark/meson.build" 2021-10-23 16:48:50.000000000 +0000 @@ -0,0 +1,4 @@ +project('benchmark', 'c') + +delayer = executable('delayer', 'delayer.c', c_args : '-D_GNU_SOURCE') +benchmark('delayer', delayer) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/gensrc.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/gensrc.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/gensrc.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/gensrc.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import shutil - -shutil.copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/meson.build" 2020-01-07 21:07:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -project('dep fallback', 'c') - -bob = dependency('boblib', fallback : ['boblib', 'bob_dep'], required: false, - default_options : 'warning_level=1') -if not bob.found() - error('Bob is actually needed') -endif -# boblib subproject exists, but sita_dep doesn't exist -sita = dependency('sitalib', fallback : ['boblib', 'sita_dep'], required: false) -# jimmylib subproject doesn't exist -jimmy = dependency('jimmylib', fallback : ['jimmylib', 'jimmy_dep'], required: false) -# dummylib subproject fails to configure -dummy = dependency('dummylib', fallback : ['dummylib', 'dummy_dep'], required: false) - -gensrc_py = find_program('gensrc.py') -gensrc = custom_target('gensrc.c', - input : 'tester.c', - output : 'gensrc.c', - command : [gensrc_py, '@INPUT@', '@OUTPUT@']) - -exe = executable('bobtester', - [gensrc], - dependencies : bob) - -test('bobtester', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/boblib/bob.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/boblib/bob.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/boblib/bob.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/boblib/bob.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include"bob.h" - -#ifdef _MSC_VER -__declspec(dllexport) -#endif -const char* get_bob(void) { - return "bob"; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/boblib/bob.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/boblib/bob.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/boblib/bob.h" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/boblib/bob.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#pragma once - -#ifdef _MSC_VER -__declspec(dllimport) -#endif -const char* get_bob(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/boblib/genbob.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/boblib/genbob.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/boblib/genbob.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/boblib/genbob.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -with open(sys.argv[1], 'w') as f: - f.write('') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/boblib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/boblib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/boblib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/boblib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -project('bob', 'c') - -gensrc_py = find_program('genbob.py') -genbob_h = custom_target('genbob.h', - output : 'genbob.h', - command : [gensrc_py, '@OUTPUT@']) -genbob_c = custom_target('genbob.c', - output : 'genbob.c', - command : [gensrc_py, '@OUTPUT@']) - -boblib = library('bob', ['bob.c', genbob_c]) -bobinc = include_directories('.') - -bob_dep = declare_dependency(link_with : boblib, - sources : [genbob_h], - include_directories : bobinc) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/dummylib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/dummylib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/subprojects/dummylib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/subprojects/dummylib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('dummylib', 'c') - -dummy_dep = declare_dependency() -error('this subproject fails to configure') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/tester.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/tester.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/91 dep fallback/tester.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/91 dep fallback/tester.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#include"bob.h" -#include"genbob.h" -#include -#include - -int main(void) { - if(strcmp("bob", get_bob()) == 0) { - printf("Bob is indeed bob.\n"); - } else { - printf("ERROR: bob is not bob.\n"); - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 default library/ef.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 default library/ef.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 default library/ef.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 default library/ef.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include"ef.h" - -DLL_PUBLIC Ef::Ef() : x(99) { -} - -int DLL_PUBLIC Ef::get_x() const { - return x; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 default library/ef.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 default library/ef.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 default library/ef.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 default library/ef.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -#pragma once - -#if defined _WIN32 || defined __CYGWIN__ - #define DLL_PUBLIC __declspec(dllexport) -#else - #if defined __GNUC__ - #define DLL_PUBLIC __attribute__ ((visibility("default"))) - #else - #pragma message ("Compiler does not support symbol visibility.") - #define DLL_PUBLIC - #endif -#endif - -class Ef { -private: - int x; - -public: - - DLL_PUBLIC Ef(); - int DLL_PUBLIC get_x() const; -}; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 default library/eftest.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 default library/eftest.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 default library/eftest.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 default library/eftest.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#include"ef.h" - -#include - -int main(int, char **) { - Ef var; - if(var.get_x() == 99) { - std::cout << "All is fine.\n"; - return 0; - } else { - std::cout << "Something went wrong.\n"; - return 1; - } -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 default library/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 default library/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 default library/meson.build" 2020-01-07 21:07:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 default library/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('default library', 'cpp') - -flib = library('ef', 'ef.cpp') -exe = executable('eftest', 'eftest.cpp', link_with : flib) -test('eftest', exe) - -# Same as above, but using build_target() -flib2 = build_target('ef2', 'ef.cpp', target_type: 'library') -exe2 = executable('eftest2', 'eftest.cpp', link_with : flib2) -test('eftest2', exe2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 test workdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 test workdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 test workdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 test workdir/meson.build" 2021-10-23 16:48:51.000000000 +0000 @@ -0,0 +1,8 @@ +project('test workdir', 'c') + +exe = executable('opener', 'opener.c') + +test('basic', exe, workdir : meson.source_root()) +test('shouldfail', exe, should_fail : true) + +subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 test workdir/opener.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 test workdir/opener.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 test workdir/opener.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 test workdir/opener.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,12 @@ +// This test only succeeds if run in the source root dir. + +#include + +int main(void) { + FILE *f = fopen("opener.c", "r"); + if(f) { + fclose(f); + return 0; + } + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 test workdir/subdir/checker.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 test workdir/subdir/checker.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 test workdir/subdir/checker.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 test workdir/subdir/checker.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +import sys + +data = open(sys.argv[1], 'rb').read() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 test workdir/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 test workdir/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/92 test workdir/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/92 test workdir/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +exe2 = executable('dummy', '../opener.c') +test('subdir', find_program('checker.py'), + workdir : meson.source_root(), + args: [exe2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 selfbuilt custom/data.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 selfbuilt custom/data.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 selfbuilt custom/data.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 selfbuilt custom/data.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -generated_function diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 selfbuilt custom/mainprog.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 selfbuilt custom/mainprog.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 selfbuilt custom/mainprog.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 selfbuilt custom/mainprog.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include"data.h" - -int main(void) { - return generated_function() != 52; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 selfbuilt custom/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 selfbuilt custom/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 selfbuilt custom/meson.build" 2020-01-07 21:07:41.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 selfbuilt custom/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -project('selfbuilt custom', 'cpp') - -# Build an exe and use it in a custom target -# whose output is used to build a different exe. - -tool = executable('tool', 'tool.cpp', native : true) - -hfile = custom_target('datah', - output : 'data.h', - input : 'data.dat', - command : [tool, '@INPUT@', '@OUTPUT@'], -) - -main = executable('mainprog', 'mainprog.cpp', hfile) - -test('maintest', main) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 selfbuilt custom/tool.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 selfbuilt custom/tool.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 selfbuilt custom/tool.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 selfbuilt custom/tool.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -#include -#include -#include - -using namespace std; - -const char prefix[] = "int "; -const char suffix[] = " () {\n return 52;}\n"; - -int main(int argc, char **argv) { - if(argc != 3) { - cout << "You is fail.\n"; - return 1; - } - ifstream is(argv[1], ifstream::binary); - if(!is) { - cout << "Opening input file failed.\n"; - return 1; - } - string funcname; - is >> funcname; - ofstream os(argv[2], ofstream::binary); - if(!os) { - cout << "Opening output file failed.\n"; - return 1; - } - os << prefix << funcname << suffix; - os.close(); - if(!os.good()) { - cout << "Writing data out failed.\n"; - return 1; - } - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/exe1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/exe1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/exe1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/exe1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I am test exe1.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/exe2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/exe2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/exe2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/exe2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I am test exe2.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/meson.build" 2021-10-23 16:48:51.000000000 +0000 @@ -0,0 +1,9 @@ +project('multiple test suites', 'c') + +subproject('sub') + +exe1 = executable('exe1', 'exe1.c') +exe2 = executable('exe2', 'exe2.c') + +test('exe1', exe1) +test('exe2', exe2, suite : ['suite2', ['super-special']]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +project('subproject test suites', 'c') + +sub1 = executable('sub1', 'sub1.c') +sub2 = executable('sub2', 'sub2.c') + +test('sub1', sub1) +test('sub2', sub2, suite : 'suite2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/subprojects/sub/sub1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/subprojects/sub/sub1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/subprojects/sub/sub1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/subprojects/sub/sub1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I am test sub1.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/subprojects/sub/sub2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/subprojects/sub/sub2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/93 suites/subprojects/sub/sub2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/93 suites/subprojects/sub/sub2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("I am test sub2.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/meson.build" 2020-01-07 21:07:42.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -project('extra args in gen', 'c') - -prog = find_program('srcgen.py') - -gen = generator(prog, - output : '@BASENAME@.c', - arguments : ['--input=@INPUT@', '--output=@OUTPUT@', '@EXTRA_ARGS@']) - -g1 = gen.process('name.dat') -g2 = gen.process('name.dat', extra_args: '--upper') - -test('basic', executable('basic', 'plain.c', g1)) -test('upper', executable('upper', 'upper.c', g2)) - -prog2 = find_program('srcgen2.py') -basename_gen = generator(prog2, - output : ['@BASENAME@.tab.c', '@BASENAME@.tab.h'], - arguments : ['@BUILD_DIR@', '@BASENAME@', '@INPUT@']) - -basename_src = basename_gen.process('name.l') - -test('basename', executable('basename', basename_src)) - -plainname_gen = generator(prog2, - output : ['@PLAINNAME@.tab.c', '@PLAINNAME@.tab.h'], - arguments : ['@BUILD_DIR@', '@PLAINNAME@', '@INPUT@']) - -plainname_src = plainname_gen.process('name.l') - -test('plainname', executable('plainname', plainname_src)) - -prog3 = find_program('srcgen3.py') -capture_gen = generator(prog3, - output : ['@BASENAME@.yy.c'], - arguments : ['@INPUT@'], - capture : true) - -capture_src = capture_gen.process('name.l') - -test('capture', executable('capture', capture_src)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/name.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/name.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/name.dat" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/name.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -bob_mcbob diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/name.l" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/name.l" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/name.l" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/name.l" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { -return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/plain.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/plain.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/plain.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/plain.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int bob_mcbob(void); - -int main(void) { - return bob_mcbob(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/srcgen2.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/srcgen2.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/srcgen2.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/srcgen2.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument('target_dir', - help='the target dir') -parser.add_argument('stem', - help='the stem') -parser.add_argument('input', - help='the input file') - -options = parser.parse_args(sys.argv[1:]) - -with open(options.input) as f: - content = f.read() - - -output_c = os.path.join(options.target_dir, options.stem + ".tab.c") -with open(output_c, 'w') as f: - f.write(content) - - -output_h = os.path.join(options.target_dir, options.stem + ".tab.h") -h_content = '''#pragma once - -int myfun(void); -''' -with open(output_h, 'w') as f: - f.write(h_content) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/srcgen3.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/srcgen3.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/srcgen3.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/srcgen3.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument('input', - help='the input file') - -options = parser.parse_args(sys.argv[1:]) - -with open(options.input) as f: - content = f.read().strip() - -print(content) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/srcgen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/srcgen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/srcgen.py" 2020-01-07 21:01:29.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/srcgen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument('--input', dest='input', - help='the input file') -parser.add_argument('--output', dest='output', - help='the output file') -parser.add_argument('--upper', dest='upper', action='store_true', default=False, - help='Convert to upper case.') - -c_templ = '''int %s(void) { - return 0; -} -''' - -options = parser.parse_args(sys.argv[1:]) - -with open(options.input) as f: - funcname = f.readline().strip() -if options.upper: - funcname = funcname.upper() - -with open(options.output, 'w') as f: - f.write(c_templ % funcname) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/upper.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/upper.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 gen extra/upper.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 gen extra/upper.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int BOB_MCBOB(void); - -int main(void) { - return BOB_MCBOB(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 threads/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 threads/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 threads/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 threads/meson.build" 2021-10-23 16:48:53.000000000 +0000 @@ -0,0 +1,16 @@ +project('threads', 'cpp', 'c', + default_options : ['cpp_std=c++11']) + +threaddep = dependency('threads') + +test('cppthreadtest', + executable('cppthreadprog', 'threadprog.cpp', + dependencies : threaddep + ) +) + +test('cthreadtest', + executable('cthreadprog', 'threadprog.c', + dependencies : threaddep + ) +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 threads/threadprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 threads/threadprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 threads/threadprog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 threads/threadprog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,40 @@ +#if defined _WIN32 + +#include +#include + +DWORD WINAPI thread_func(void) { + printf("Printing from a thread.\n"); + return 0; +} + +int main(void) { + DWORD id; + HANDLE th; + printf("Starting thread.\n"); + th = CreateThread(NULL, 0, thread_func, NULL, 0, &id); + WaitForSingleObject(th, INFINITE); + printf("Stopped thread.\n"); + return 0; +} +#else + +#include +#include + +void* main_func(void) { + printf("Printing from a thread.\n"); + return NULL; +} + +int main(void) { + pthread_t thread; + int rc; + printf("Starting thread.\n"); + rc = pthread_create(&thread, NULL, main_func, NULL); + rc = pthread_join(thread, NULL); + printf("Stopped thread.\n"); + return rc; +} + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 threads/threadprog.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 threads/threadprog.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/94 threads/threadprog.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/94 threads/threadprog.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,43 @@ +/* On Windows not all versions of VS support C++11 and + * some (most?) versions of mingw don't support std::thread, + * even though they do support c++11. Since we only care about + * threads working, do the test with raw win threads. + */ + +#if defined _WIN32 + +#include +#include + +DWORD WINAPI thread_func(LPVOID) { + printf("Printing from a thread.\n"); + return 0; +} + +int main(void) { + printf("Starting thread.\n"); + HANDLE th; + DWORD id; + th = CreateThread(NULL, 0, thread_func, NULL, 0, &id); + WaitForSingleObject(th, INFINITE); + printf("Stopped thread.\n"); + return 0; +} +#else + +#include +#include + +void main_func(void) { + printf("Printing from a thread.\n"); +} + +int main(void) { + printf("Starting thread.\n"); + std::thread th(main_func); + th.join(); + printf("Stopped thread.\n"); + return 0; +} + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 benchmark/delayer.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 benchmark/delayer.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 benchmark/delayer.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 benchmark/delayer.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -/* Simple prog that sleeps for a random time. */ - -#include -#include -#if defined(_WIN32) -#include -#endif - -int main(void) { - srand(time(NULL)); -#if !defined(_WIN32) - struct timespec t; - t.tv_sec = 0; - t.tv_nsec = 199999999.0*rand()/RAND_MAX; - nanosleep(&t, NULL); -#else - Sleep(50.0*rand()/RAND_MAX); -#endif - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 benchmark/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 benchmark/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 benchmark/meson.build" 2020-01-07 21:07:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 benchmark/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('benchmark', 'c') - -delayer = executable('delayer', 'delayer.c', c_args : '-D_GNU_SOURCE') -benchmark('delayer', delayer) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/depuser.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/depuser.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/depuser.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/depuser.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include"gen_func.h" + +int main(void) { + unsigned int i = (unsigned int) gen_func_in_lib(); + unsigned int j = (unsigned int) gen_func_in_obj(); + unsigned int k = (unsigned int) gen_func_in_src(); + return (int)(i + j + k); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/meson.build" 2021-10-23 16:48:53.000000000 +0000 @@ -0,0 +1,14 @@ +project('manygen', 'c') + +if meson.is_cross_build() + # FIXME error out with skip message once cross test runner + # recognizes it. + message('Not running this test during cross build.') +else + subdir('subdir') + + exe = executable('depuser', 'depuser.c', + generated) + + test('depuser test', exe) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/subdir/funcinfo.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/subdir/funcinfo.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/subdir/funcinfo.def" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/subdir/funcinfo.def" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +gen_func diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/subdir/manygen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/subdir/manygen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/subdir/manygen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/subdir/manygen.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 + + +# Generates a static library, object file, source +# file and a header file. + +import sys, os +import subprocess + +with open(sys.argv[1]) as f: + funcname = f.readline().strip() +outdir = sys.argv[2] +buildtype_args = sys.argv[3] +compiler_type = sys.argv[4] +compiler = sys.argv[5:] + +if not os.path.isdir(outdir): + print('Outdir does not exist.') + sys.exit(1) + +if compiler_type == 'msvc': + libsuffix = '.lib' + is_vs = True + if any(['clang-cl' in c for c in compiler]): + linker = 'llvm-lib' + else: + linker = 'lib' +else: + libsuffix = '.a' + is_vs = False + linker = 'ar' + +objsuffix = '.o' + +outo = os.path.join(outdir, funcname + objsuffix) +outa = os.path.join(outdir, funcname + libsuffix) +outh = os.path.join(outdir, funcname + '.h') +outc = os.path.join(outdir, funcname + '.c') + +tmpc = 'diibadaaba.c' +tmpo = 'diibadaaba' + objsuffix + +with open(outc, 'w') as f: + f.write('''#include"{}.h" +int {}_in_src(void) {{ + return 0; +}} +'''.format(funcname, funcname)) + +with open(outh, 'w') as f: + f.write('''#pragma once +int {}_in_lib(void); +int {}_in_obj(void); +int {}_in_src(void); +'''.format(funcname, funcname, funcname)) + +with open(tmpc, 'w') as f: + f.write('''int %s_in_obj(void) { + return 0; +} +''' % funcname) + +if is_vs: + subprocess.check_call(compiler + ['/nologo', '/c', buildtype_args, '/Fo' + outo, tmpc]) +else: + subprocess.check_call(compiler + ['-c', '-o', outo, tmpc]) + +with open(tmpc, 'w') as f: + f.write('''int %s_in_lib() { + return 0; +} +''' % funcname) + +if is_vs: + subprocess.check_call(compiler + ['/nologo', '/c', '/Fo' + tmpo, tmpc]) + subprocess.check_call([linker, '/NOLOGO', '/OUT:' + outa, tmpo]) +else: + subprocess.check_call(compiler + ['-c', '-o', tmpo, tmpc]) + subprocess.check_call([linker, 'csr', outa, tmpo]) + +os.unlink(tmpo) +os.unlink(tmpc) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/95 manygen/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/95 manygen/subdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,26 @@ +gen = files('manygen.py') +py3_bin = import('python3').find_python() + +buildtype = get_option('buildtype') +buildtype_args = '-Dfooxxx' # a useless compiler argument +cc = meson.get_compiler('c') +if cc.get_argument_syntax() == 'msvc' + # We need our manually generated code to use the same CRT as the executable. + # Taken from compilers.py since build files do not have access to this. + if buildtype == 'debug' + buildtype_args = '/MDd' + elif buildtype == 'debugoptimized' + buildtype_args = '/MDd' + elif buildtype == 'release' + buildtype_args = '/MD' + endif + outfiles = ['gen_func.lib', 'gen_func.c', 'gen_func.h', 'gen_func.o'] +else + outfiles = ['gen_func.a', 'gen_func.c', 'gen_func.h', 'gen_func.o'] +endif + +generated = custom_target('manygen', + output : outfiles, + input : ['funcinfo.def'], + command : [py3_bin, gen[0], '@INPUT@', '@OUTDIR@', buildtype_args, cc.get_argument_syntax(), cc.cmd_array()], +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 stringdef/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 stringdef/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 stringdef/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 stringdef/meson.build" 2021-10-23 16:48:55.000000000 +0000 @@ -0,0 +1,3 @@ +project('stringdef', 'c') + +test('stringdef', executable('stringdef', 'stringdef.c', c_args : '-DFOO="bar"')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 stringdef/stringdef.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 stringdef/stringdef.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 stringdef/stringdef.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 stringdef/stringdef.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include + +int main(void) { + if(strcmp(FOO, "bar")) { + printf("FOO is misquoted: %s\n", FOO); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 test workdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 test workdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 test workdir/meson.build" 2020-01-07 21:07:44.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 test workdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('test workdir', 'c') - -exe = executable('opener', 'opener.c') - -test('basic', exe, workdir : meson.source_root()) -test('shouldfail', exe, should_fail : true) - -subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 test workdir/opener.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 test workdir/opener.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 test workdir/opener.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 test workdir/opener.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -// This test only succeeds if run in the source root dir. - -#include - -int main(void) { - FILE *f = fopen("opener.c", "r"); - if(f) { - fclose(f); - return 0; - } - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 test workdir/subdir/checker.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 test workdir/subdir/checker.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 test workdir/subdir/checker.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 test workdir/subdir/checker.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -data = open(sys.argv[1], 'rb').read() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 test workdir/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 test workdir/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/96 test workdir/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/96 test workdir/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -exe2 = executable('dummy', '../opener.c') -test('subdir', find_program('checker.py'), - workdir : meson.source_root(), - args: [exe2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 find program path/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 find program path/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 find program path/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 find program path/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,22 @@ +project('find program', 'c') + +python = import('python3').find_python() + +# Source file via string +prog = find_program('program.py') +# Source file via files() +progf = files('program.py') +# Built file +py = configure_file(input : 'program.py', + output : 'builtprogram.py', + configuration : configuration_data()) + +foreach f : [prog, progf, py, find_program(py), find_program(progf)] + ret = run_command(python, f, check: false) + assert(ret.returncode() == 0, 'can\'t manually run @0@'.format(prog.path())) + assert(ret.stdout().strip() == 'Found', 'wrong output from manually-run @0@'.format(prog.path())) + + ret = run_command(f, check: false) + assert(ret.returncode() == 0, 'can\'t run @0@'.format(prog.path())) + assert(ret.stdout().strip() == 'Found', 'wrong output from @0@'.format(prog.path())) +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 find program path/program.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 find program path/program.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 find program path/program.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 find program path/program.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print("Found") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/exe1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/exe1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/exe1.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/exe1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I am test exe1.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/exe2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/exe2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/exe2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/exe2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I am test exe2.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/meson.build" 2020-01-07 21:07:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('multiple test suites', 'c') - -subproject('sub') - -exe1 = executable('exe1', 'exe1.c') -exe2 = executable('exe2', 'exe2.c') - -test('exe1', exe1) -test('exe2', exe2, suite : ['suite2', 'super-special']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/subprojects/sub/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('subproject test suites', 'c') - -sub1 = executable('sub1', 'sub1.c') -sub2 = executable('sub2', 'sub2.c') - -test('sub1', sub1) -test('sub2', sub2, suite : 'suite2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/subprojects/sub/sub1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/subprojects/sub/sub1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/subprojects/sub/sub1.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/subprojects/sub/sub1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I am test sub1.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/subprojects/sub/sub2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/subprojects/sub/sub2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/97 suites/subprojects/sub/sub2.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/97 suites/subprojects/sub/sub2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(void) { - printf("I am test sub2.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,94 @@ +project('proj', 'c') +subproject('sub') +libSub = dependency('sub', fallback: ['sub', 'libSub']) + +exe = executable('prog', 'prog.c', dependencies: libSub) +test('subproject subdir', exe) + +# Verify the subproject has placed dependency override. +dependency('sub-1.0') + +# Verify we can now take 'sub' dependency without fallback, but only version 1.0. +dependency('sub') +d = dependency('sub', version : '>=2.0', required : false) +assert(not d.found(), 'version should not match') + +# Verify that not-found does not get cached, we can still fallback afterward. +dependency('sub2', required : false) +d = dependency('sub2', fallback: ['sub', 'libSub']) +assert(d.found(), 'Should fallback even if a previous call returned not-found') + +# Verify we can get a fallback dependency without specifying the variable name, +# because the subproject overridden 'sub-novar'. +dependency('sub-novar', fallback : 'sub_novar') + +# Verify a subproject can force a dependency to be not-found +d = dependency('sub-notfound', fallback : 'sub_novar', required : false) +assert(not d.found(), 'Dependency should be not-found') + +# Verify that implicit fallback works because subprojects/sub_implicit directory exists +d = dependency('sub_implicit', default_options: 'opt=overriden') +assert(d.found(), 'Should implicitly fallback') + +# Verify that implicit fallback works because sub_implicit.wrap has +# `dependency_names=sub_implicit_provide1` and the subproject overrides sub_implicit_provide1. +d = dependency('sub_implicit_provide1') +assert(d.found(), 'Should implicitly fallback') + +# Verify that implicit fallback works because sub_implicit.wrap has +# `sub_implicit_provide2=sub_implicit_provide2_dep` and does not override +# sub_implicit_provide2. +d = dependency('sub_implicit_provide2') +assert(d.found(), 'Should implicitly fallback') + +# sub_implicit.wrap provides glib-2.0 and we already configured that subproject, +# so we must not return the system dependency here. Using glib-2.0 here because +# some CI runners have it installed. +d = dependency('glib-2.0', required : false) +assert(d.found()) +assert(d.type_name() == 'internal') + +# sub_implicit.wrap provides gobject-2.0 and we already configured that subproject, +# so we must not return the system dependency here. But since the subproject did +# not override that dependency and its not required, not-found should be returned. +# Using gobject-2.0 here because some CI runners have it installed. +d = dependency('gobject-2.0', required : false) +assert(not d.found()) + +# Verify that implicit fallback works because subprojects/sub_implicit/subprojects/subsub +# directory exists. +d = dependency('subsub') +assert(d.found(), 'Should be able to fallback to sub-subproject') + +# Verify that implicit fallback works because +# subprojects/sub_implicit/subprojects/subsub/subprojects/subsubsub.wrap +# file exists. +d = dependency('subsubsub') +assert(d.found(), 'Should be able to fallback to sub-sub-subproject') + +# Verify that `static: true` implies 'default_library=static'. +d = dependency('sub_static', static: true) +assert(d.found()) +# Verify that when not specifying static kwarg we can still get fallback dep. +d = dependency('sub_static') +assert(d.found()) +# But when asking for shared library explicitly, it is not found. +d = dependency('sub_static', static: false, required: false) +assert(not d.found()) +# The subproject also overrides sub_static2 with `static: true` +d = dependency('sub_static2') +assert(d.found()) +d = dependency('sub_static2', static: true) +assert(d.found()) +d = dependency('sub_static2', static: false, required: false) +assert(not d.found()) +# sub_static3 is overridden twice with `static: true` and `static: false` +d = dependency('sub_static3') +assert(d.found()) +assert(d.get_variable('static') == 'true') +d = dependency('sub_static3', static: true) +assert(d.found()) +assert(d.get_variable('static') == 'true') +d = dependency('sub_static3', static: false) +assert(d.found()) +assert(d.get_variable('static') == 'false') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int main(void) { + return sub(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub/lib/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +lib = static_library('sub', 'sub.c') +libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) +meson.override_dependency('sub-1.0', libSub) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub/lib/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub/lib/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub/lib/sub.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub/lib/sub.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include "sub.h" + +int sub(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub/lib/sub.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub/lib/sub.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub/lib/sub.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub/lib/sub.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#ifndef SUB_H +#define SUB_H + +int sub(void); + +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +project('sub', 'c', version : '1.0') +subdir('lib') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,13 @@ +project('sub_implicit', 'c', version : '1.0') + +dep = declare_dependency() +meson.override_dependency('sub_implicit', dep) +meson.override_dependency('sub_implicit_provide1', dep) + +# This one is not overridden but the wrap file tells the variable name to use. +sub_implicit_provide2_dep = dep + +# This one is not overridden but the wrap file tells the variable name to use. +glib_dep = dep + +assert(get_option('opt') == 'overriden') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1 @@ +option('opt', type: 'string', value: 'default') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/foo.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/foo.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#define DUMMY 42 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +project('subsub') + +meson.override_dependency('subsub', declare_dependency()) + +# Regression test: Installing a header from nested sub-subproject used to raise: +# ERROR: Sandbox violation: Tried to grab file foo.h from a nested subproject. +install_headers('foo.h') Binary files /tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/packagefiles/subsubsub-1.0.zip and /tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/packagefiles/subsubsub-1.0.zip differ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/subsubsub.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/subsubsub.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/subsubsub.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/subsubsub.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +[wrap-file] +directory = subsubsub-1.0 +source_filename = subsubsub-1.0.zip +source_hash = c073a96b7251937e53216578f6f03d91b84816618a0f1ce3ecfb867beddf1498 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_implicit.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_implicit.wrap" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +[wrap-file] + +[provide] +glib-2.0 = glib_dep +dependency_names = sub_implicit_provide1, gobject-2.0 +sub_implicit_provide2 = sub_implicit_provide2_dep diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_novar/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_novar/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_novar/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_novar/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('sub-novar', 'c', version : '1.0') + +meson.override_dependency('sub-novar', declare_dependency()) +meson.override_dependency('sub-notfound', dependency('', required : false)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_static/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_static/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/subprojects/sub_static/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/subprojects/sub_static/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,8 @@ +project('sub_static') + +assert(get_option('default_library') == 'static') +meson.override_dependency('sub_static', declare_dependency()) +meson.override_dependency('sub_static2', declare_dependency(), static: true) +meson.override_dependency('sub_static3', declare_dependency(variables: {'static': 'true'}), static: true) +meson.override_dependency('sub_static3', declare_dependency(variables: {'static': 'false'}), static: false) + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 subproject subdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 subproject subdir/test.json" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + { "type": "file", "file": "usr/include/foo.h" } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 threads/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 threads/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 threads/meson.build" 2020-01-07 21:07:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 threads/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -project('threads', 'cpp', 'c', - default_options : ['cpp_std=c++11']) - -threaddep = dependency('threads') - -test('cppthreadtest', - executable('cppthreadprog', 'threadprog.cpp', - dependencies : threaddep - ) -) - -test('cthreadtest', - executable('cthreadprog', 'threadprog.c', - dependencies : threaddep - ) -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 threads/threadprog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 threads/threadprog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 threads/threadprog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 threads/threadprog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#if defined _WIN32 - -#include -#include - -DWORD WINAPI thread_func(void) { - printf("Printing from a thread.\n"); - return 0; -} - -int main(void) { - DWORD id; - HANDLE th; - printf("Starting thread.\n"); - th = CreateThread(NULL, 0, thread_func, NULL, 0, &id); - WaitForSingleObject(th, INFINITE); - printf("Stopped thread.\n"); - return 0; -} -#else - -#include -#include - -void* main_func(void) { - printf("Printing from a thread.\n"); - return NULL; -} - -int main(void) { - pthread_t thread; - int rc; - printf("Starting thread.\n"); - rc = pthread_create(&thread, NULL, main_func, NULL); - rc = pthread_join(thread, NULL); - printf("Stopped thread.\n"); - return rc; -} - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 threads/threadprog.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 threads/threadprog.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/98 threads/threadprog.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/98 threads/threadprog.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -/* On Windows not all versions of VS support C++11 and - * some (most?) versions of mingw don't support std::thread, - * even though they do support c++11. Since we only care about - * threads working, do the test with raw win threads. - */ - -#if defined _WIN32 - -#include -#include - -DWORD WINAPI thread_func(LPVOID) { - printf("Printing from a thread.\n"); - return 0; -} - -int main(void) { - printf("Starting thread.\n"); - HANDLE th; - DWORD id; - th = CreateThread(NULL, 0, thread_func, NULL, 0, &id); - WaitForSingleObject(th, INFINITE); - printf("Stopped thread.\n"); - return 0; -} -#else - -#include -#include - -void main_func(void) { - printf("Printing from a thread.\n"); -} - -int main(void) { - printf("Starting thread.\n"); - std::thread th(main_func); - th.join(); - printf("Stopped thread.\n"); - return 0; -} - -#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/depuser.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/depuser.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/depuser.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/depuser.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#include"gen_func.h" - -int main(void) { - unsigned int i = (unsigned int) gen_func_in_lib(); - unsigned int j = (unsigned int) gen_func_in_obj(); - unsigned int k = (unsigned int) gen_func_in_src(); - return (int)(i + j + k); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/meson.build" 2020-01-07 21:07:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('manygen', 'c') - -if meson.is_cross_build() - # FIXME error out with skip message once cross test runner - # recognizes it. - message('Not running this test during cross build.') -else - subdir('subdir') - - exe = executable('depuser', 'depuser.c', - generated) - - test('depuser test', exe) -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/subdir/funcinfo.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/subdir/funcinfo.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/subdir/funcinfo.def" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/subdir/funcinfo.def" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -gen_func diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/subdir/manygen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/subdir/manygen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/subdir/manygen.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/subdir/manygen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import print_function - -# Generates a static library, object file, source -# file and a header file. - -import sys, os -import subprocess - -with open(sys.argv[1]) as f: - funcname = f.readline().strip() -outdir = sys.argv[2] -buildtype_args = sys.argv[3] -compiler_type = sys.argv[4] -compiler = sys.argv[5:] - -if not os.path.isdir(outdir): - print('Outdir does not exist.') - sys.exit(1) - -if compiler_type == 'msvc': - libsuffix = '.lib' - is_vs = True - if any(['clang-cl' in c for c in compiler]): - linker = 'llvm-lib' - else: - linker = 'lib' -else: - libsuffix = '.a' - is_vs = False - linker = 'ar' - -objsuffix = '.o' - -outo = os.path.join(outdir, funcname + objsuffix) -outa = os.path.join(outdir, funcname + libsuffix) -outh = os.path.join(outdir, funcname + '.h') -outc = os.path.join(outdir, funcname + '.c') - -tmpc = 'diibadaaba.c' -tmpo = 'diibadaaba' + objsuffix - -with open(outc, 'w') as f: - f.write('''#include"%s.h" -int %s_in_src(void) { - return 0; -} -''' % (funcname, funcname)) - -with open(outh, 'w') as f: - f.write('''#pragma once -int %s_in_lib(void); -int %s_in_obj(void); -int %s_in_src(void); -''' % (funcname, funcname, funcname)) - -with open(tmpc, 'w') as f: - f.write('''int %s_in_obj(void) { - return 0; -} -''' % funcname) - -if is_vs: - subprocess.check_call(compiler + ['/nologo', '/c', buildtype_args, '/Fo' + outo, tmpc]) -else: - subprocess.check_call(compiler + ['-c', '-o', outo, tmpc]) - -with open(tmpc, 'w') as f: - f.write('''int %s_in_lib() { - return 0; -} -''' % funcname) - -if is_vs: - subprocess.check_call(compiler + ['/nologo', '/c', '/Fo' + tmpo, tmpc]) - subprocess.check_call([linker, '/NOLOGO', '/OUT:' + outa, tmpo]) -else: - subprocess.check_call(compiler + ['-c', '-o', tmpo, tmpc]) - subprocess.check_call([linker, 'csr', outa, tmpo]) - -os.unlink(tmpo) -os.unlink(tmpc) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 manygen/subdir/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 manygen/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -gen = files('manygen.py') -py3_bin = import('python3').find_python() - -buildtype = get_option('buildtype') -buildtype_args = '-Dfooxxx' # a useless compiler argument -cc = meson.get_compiler('c') -if cc.get_argument_syntax() == 'msvc' - # We need our manually generated code to use the same CRT as the executable. - # Taken from compilers.py since build files do not have access to this. - if buildtype == 'debug' - buildtype_args = '/MDd' - elif buildtype == 'debugoptimized' - buildtype_args = '/MDd' - elif buildtype == 'release' - buildtype_args = '/MD' - endif - outfiles = ['gen_func.lib', 'gen_func.c', 'gen_func.h', 'gen_func.o'] -else - outfiles = ['gen_func.a', 'gen_func.c', 'gen_func.h', 'gen_func.o'] -endif - -generated = custom_target('manygen', - output : outfiles, - input : ['funcinfo.def'], - command : [py3_bin, gen[0], '@INPUT@', '@OUTDIR@', buildtype_args, cc.get_argument_syntax(), cc.cmd_array()], -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 postconf/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 postconf/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 postconf/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 postconf/meson.build" 2021-10-23 16:48:56.000000000 +0000 @@ -0,0 +1,5 @@ +project('postconf script', 'c') + +meson.add_postconf_script('postconf.py') + +test('post', executable('prog', 'prog.c')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 postconf/postconf.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 postconf/postconf.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 postconf/postconf.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 postconf/postconf.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 + +import os + +template = '''#pragma once + +#define THE_NUMBER {} +''' + +input_file = os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat') +output_file = os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h') + +with open(input_file) as f: + data = f.readline().strip() +with open(output_file, 'w') as f: + f.write(template.format(data)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 postconf/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 postconf/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 postconf/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 postconf/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include"generated.h" + +int main(void) { + return THE_NUMBER != 9; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 postconf/raw.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 postconf/raw.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/99 postconf/raw.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/99 postconf/raw.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +9 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/9 header install/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/9 header install/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/9 header install/installed_files.txt" 2016-11-27 18:42:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/9 header install/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -usr/include/rootdir.h -usr/include/subdir/subdir.h -usr/include/vanished.h -usr/include/fileheader.h diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/9 header install/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/9 header install/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/9 header install/meson.build" 2020-01-07 21:06:17.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/9 header install/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -9,4 +9,3 @@ h2 = install_headers(as_array, subdir : 'subdir') h3 = install_headers(subheader) h4 = install_headers(disabler()) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/9 header install/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/9 header install/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/9 header install/sub/meson.build" 2016-11-27 18:42:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/9 header install/sub/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,2 +1 @@ subheader = files('fileheader.h') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/9 header install/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/9 header install/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/common/9 header install/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/common/9 header install/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "installed": [ + { "type": "file", "file": "usr/include/rootdir.h" }, + { "type": "file", "file": "usr/include/subdir/subdir.h" }, + { "type": "file", "file": "usr/include/vanished.h" }, + { "type": "file", "file": "usr/include/fileheader.h" } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/1 basic/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/1 basic/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/1 basic/installed_files.txt" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/1 basic/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/prog.exe -?msvc:usr/bin/prog.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/1 basic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/1 basic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/1 basic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/1 basic/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/prog.exe"}, + {"type": "pdb", "file": "usr/bin/prog"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/2 library/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/2 library/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/2 library/installed_files.txt" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/2 library/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -usr/bin/prog.exe -?msvc:usr/bin/prog.pdb -?msvc:usr/bin/helper.dll -?msvc:usr/bin/helper.pdb -?gcc:usr/lib/helper.dll diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/2 library/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/2 library/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/2 library/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/2 library/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/prog.exe"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/helper.dll"}, + {"type": "pdb", "file": "usr/bin/helper"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/helper.dll"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/4 external dep/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/4 external dep/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/4 external dep/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/4 external dep/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/bin/prog.exe diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/4 external dep/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/4 external dep/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/csharp/4 external dep/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/csharp/4 external dep/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/prog.exe"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/13 cuda compiler setting/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/13 cuda compiler setting/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/13 cuda compiler setting/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/13 cuda compiler setting/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,4 @@ +project('simple', 'cuda', version : '1.0.0') + +exe = executable('prog', 'prog.cu') +test('cudatest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/13 cuda compiler setting/nativefile.ini" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/13 cuda compiler setting/nativefile.ini" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/13 cuda compiler setting/nativefile.ini" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/13 cuda compiler setting/nativefile.ini" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +[binaries] + +cuda = 'nvcc' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/13 cuda compiler setting/prog.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/13 cuda compiler setting/prog.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/13 cuda compiler setting/prog.cu" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/13 cuda compiler setting/prog.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,29 @@ +#include + +int main(void) { + int cuda_devices = 0; + std::cout << "CUDA version: " << CUDART_VERSION << "\n"; + cudaGetDeviceCount(&cuda_devices); + if(cuda_devices == 0) { + std::cout << "No Cuda hardware found. Exiting.\n"; + return 0; + } + std::cout << "This computer has " << cuda_devices << " Cuda device(s).\n"; + cudaDeviceProp props; + cudaGetDeviceProperties(&props, 0); + std::cout << "Properties of device 0.\n\n"; + + std::cout << " Name: " << props.name << "\n"; + std::cout << " Global memory: " << props.totalGlobalMem << "\n"; + std::cout << " Shared memory: " << props.sharedMemPerBlock << "\n"; + std::cout << " Constant memory: " << props.totalConstMem << "\n"; + std::cout << " Block registers: " << props.regsPerBlock << "\n"; + + std::cout << " Warp size: " << props.warpSize << "\n"; + std::cout << " Threads per block: " << props.maxThreadsPerBlock << "\n"; + std::cout << " Max block dimensions: [ " << props.maxThreadsDim[0] << ", " << props.maxThreadsDim[1] << ", " << props.maxThreadsDim[2] << " ]" << "\n"; + std::cout << " Max grid dimensions: [ " << props.maxGridSize[0] << ", " << props.maxGridSize[1] << ", " << props.maxGridSize[2] << " ]" << "\n"; + std::cout << "\n"; + + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/14 cuda has header symbol/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/14 cuda has header symbol/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/14 cuda has header symbol/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/14 cuda has header symbol/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,26 @@ +project('cuda has header symbol', 'cuda') + +cuda = meson.get_compiler('cuda') + +# C checks +assert (cuda.has_header_symbol('stdio.h', 'int'), 'base types should always be available') +assert (cuda.has_header_symbol('stdio.h', 'printf'), 'printf function not found') +assert (cuda.has_header_symbol('stdio.h', 'FILE'), 'FILE structure not found') +assert (cuda.has_header_symbol('limits.h', 'INT_MAX'), 'INT_MAX define not found') +assert (not cuda.has_header_symbol('limits.h', 'guint64'), 'guint64 is not defined in limits.h') +assert (not cuda.has_header_symbol('stdlib.h', 'FILE'), 'FILE structure is defined in stdio.h, not stdlib.h') +assert (not cuda.has_header_symbol('stdlol.h', 'printf'), 'stdlol.h shouldn\'t exist') +assert (not cuda.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header') + +# C++ checks +assert (cuda.has_header_symbol('iostream', 'std::iostream'), 'iostream not found in iostream.h') +assert (cuda.has_header_symbol('vector', 'std::vector'), 'vector not found in vector.h') +assert (not cuda.has_header_symbol('limits.h', 'std::iostream'), 'iostream should not be defined in limits.h') + +# CUDA checks +assert (cuda.has_header_symbol('cuda.h', 'CUDA_VERSION'), 'CUDA_VERSION not found in cuda.h') +assert (not cuda.has_header_symbol('cuda.h', 'cublasSaxpy'), 'cublasSaxpy is defined in cublas.h, not cuda.h') +if cuda.version().version_compare('>=4.0') + assert (cuda.has_header_symbol('thrust/device_vector.h', 'thrust::device_vector'), 'thrust::device_vector not found') + assert (not cuda.has_header_symbol('thrust/fill.h', 'thrust::sort'), 'thrust::sort should not be defined in thrust/fill.h') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/15 sanitizer/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/15 sanitizer/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/15 sanitizer/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/15 sanitizer/meson.build" 2021-04-10 09:22:14.000000000 +0000 @@ -0,0 +1,4 @@ +project('simple', 'cuda', version : '1.0.0', + default_options: ['b_sanitize=address,undefined']) + +libtests = shared_library('tests', 'prog.cu') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/15 sanitizer/prog.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/15 sanitizer/prog.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/15 sanitizer/prog.cu" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/15 sanitizer/prog.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,29 @@ +#include + +int run_tests(void) { + int cuda_devices = 0; + std::cout << "CUDA version: " << CUDART_VERSION << "\n"; + cudaGetDeviceCount(&cuda_devices); + if(cuda_devices == 0) { + std::cout << "No Cuda hardware found. Exiting.\n"; + return 0; + } + std::cout << "This computer has " << cuda_devices << " Cuda device(s).\n"; + cudaDeviceProp props; + cudaGetDeviceProperties(&props, 0); + std::cout << "Properties of device 0.\n\n"; + + std::cout << " Name: " << props.name << "\n"; + std::cout << " Global memory: " << props.totalGlobalMem << "\n"; + std::cout << " Shared memory: " << props.sharedMemPerBlock << "\n"; + std::cout << " Constant memory: " << props.totalConstMem << "\n"; + std::cout << " Block registers: " << props.regsPerBlock << "\n"; + + std::cout << " Warp size: " << props.warpSize << "\n"; + std::cout << " Threads per block: " << props.maxThreadsPerBlock << "\n"; + std::cout << " Max block dimensions: [ " << props.maxThreadsDim[0] << ", " << props.maxThreadsDim[1] << ", " << props.maxThreadsDim[2] << " ]" << "\n"; + std::cout << " Max grid dimensions: [ " << props.maxGridSize[0] << ", " << props.maxGridSize[1] << ", " << props.maxGridSize[2] << " ]" << "\n"; + std::cout << "\n"; + + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/16 multistd/lib.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/16 multistd/lib.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/16 multistd/lib.cu" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/16 multistd/lib.cu" 2021-11-02 19:58:13.000000000 +0000 @@ -0,0 +1,3 @@ +int do_cuda_stuff() { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/16 multistd/main.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/16 multistd/main.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/16 multistd/main.cu" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/16 multistd/main.cu" 2021-11-02 19:58:13.000000000 +0000 @@ -0,0 +1,21 @@ +#include +#include + +auto cuda_devices(void) { + int result = 0; + cudaGetDeviceCount(&result); + return result; +} + +int do_cuda_stuff(); + +int main(void) { + int n = cuda_devices(); + if (n == 0) { + std::cout << "No Cuda hardware found. Exiting.\n"; + return 0; + } + + std::cout << "Found " << n << "Cuda devices.\n"; + return do_cuda_stuff(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/16 multistd/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/16 multistd/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/16 multistd/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/16 multistd/meson.build" 2021-11-02 19:58:13.000000000 +0000 @@ -0,0 +1,13 @@ +project('C++-CUDA multi-std', 'cpp', 'cuda', + version : '1.0.0', + default_options : ['cpp_std=c++17', 'cuda_std=c++14']) + +# Regression test: Passing override_options used to cause a crash. +# See https://github.com/mesonbuild/meson/issues/9448. +libcpp11 = static_library('testcpp11', 'lib.cu', + override_options: ['cpp_std=c++11'] +) + +exe = executable('prog', 'main.cu', link_with: libcpp11) +# The runtimes leak memory, so ignore it. +test('cudatest', exe, env: ['ASAN_OPTIONS=detect_leaks=0']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/1 simple/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/1 simple/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/1 simple/meson.build" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/1 simple/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -2,4 +2,3 @@ exe = executable('prog', 'prog.cu') test('cudatest', exe) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/1 simple/prog.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/1 simple/prog.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/1 simple/prog.cu" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/1 simple/prog.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -27,4 +27,3 @@ return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/2 split/lib.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/2 split/lib.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/2 split/lib.cu" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/2 split/lib.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -10,4 +10,3 @@ printf("Hello, World!\n"); return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/2 split/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/2 split/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/2 split/meson.build" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/2 split/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -4,4 +4,3 @@ test('cudatest', exe) subdir('static') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/2 split/static/lib.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/2 split/static/lib.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/2 split/static/lib.cu" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/2 split/static/lib.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -10,4 +10,3 @@ printf("Hello, World!\n"); return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/2 split/static/libsta.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/2 split/static/libsta.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/2 split/static/libsta.cu" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/2 split/static/libsta.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -10,4 +10,3 @@ printf("Hello, World!\n"); return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/3 cudamodule/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/3 cudamodule/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/3 cudamodule/meson.build" 2019-02-07 09:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/3 cudamodule/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -3,9 +3,9 @@ nvcc = meson.get_compiler('cuda') cuda = import('unstable-cuda') -arch_flags = cuda.nvcc_arch_flags(nvcc, 'Auto', detected: ['3.0']) -arch_readable = cuda.nvcc_arch_readable(nvcc, 'Auto', detected: ['3.0']) -driver_version = cuda.min_driver_version(nvcc) +arch_flags = cuda.nvcc_arch_flags(nvcc.version(), 'Auto', detected: ['6.0']) +arch_readable = cuda.nvcc_arch_readable(nvcc.version(), 'Auto', detected: ['6.0']) +driver_version = cuda.min_driver_version(nvcc.version()) message('NVCC version: ' + nvcc.version()) message('NVCC flags: ' + ' '.join(arch_flags)) @@ -14,3 +14,56 @@ exe = executable('prog', 'prog.cu', cuda_args: arch_flags) test('cudatest', exe) + + +# +# Assert Series +# + +# Sanity test. +assert(' '.join(cuda.nvcc_arch_flags('11.1', '8.6')) == + '-gencode arch=compute_86,code=sm_86') + +# CUDA Toolkit too old, flag filtered out. +assert(' '.join(cuda.nvcc_arch_flags('11.0', '8.6')) == + '') + +# Named architectures. +assert(' '.join(cuda.nvcc_arch_flags('11.0', 'Ampere')) == + '-gencode arch=compute_80,code=sm_80') + +# Splitting & deduplication. +assert(' '.join(cuda.nvcc_arch_flags('11.0', 'Ampere;8.0,8.0')) == + '-gencode arch=compute_80,code=sm_80') + +# Same, but list supplied as list. +assert(' '.join(cuda.nvcc_arch_flags('11.0', ['Ampere', '8.0', '8.0'])) == + '-gencode arch=compute_80,code=sm_80') + +# Same, but mode set to Auto with detected set to a string with a variety of separators. +assert(' '.join(cuda.nvcc_arch_flags('11.0', 'Auto', detected: 'Ampere;8.0,8.0')) == + '-gencode arch=compute_80,code=sm_80') + +# Same, but detected set to a list. +assert(' '.join(cuda.nvcc_arch_flags('11.0', 'Auto', detected: ['Ampere', '8.0', '8.0'])) == + '-gencode arch=compute_80,code=sm_80') + +# Ask for 8.6 binary with 8.0-level PTX. +assert(' '.join(cuda.nvcc_arch_flags('11.1', '8.6(8.0)')) == + '-gencode arch=compute_80,code=sm_86') + +# Same, but keep the 8.0 PTX. +assert(' '.join(cuda.nvcc_arch_flags('11.1', '8.6(8.0)+PTX')) == + '-gencode arch=compute_80,code=sm_86 -gencode arch=compute_80,code=compute_80') + +# Detected Ampere RTX 3090 on CUDA 10.2, saturate to 7.5+PTX +assert(' '.join(cuda.nvcc_arch_flags('10.2', 'Auto', detected: ['8.0'])) == + '-gencode arch=compute_75,code=sm_75 -gencode arch=compute_75,code=compute_75') + +# Failed to auto-detect with CUDA 10.2, default to common GPUs (3.0;3.5;5.0;5.2;6.0;6.1;7.0;7.5+PTX) +assert(' '.join(cuda.nvcc_arch_flags('10.2', 'Auto', detected: [])) == + '-gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=sm_35 '+ + '-gencode arch=compute_50,code=sm_50 -gencode arch=compute_52,code=sm_52 '+ + '-gencode arch=compute_60,code=sm_60 -gencode arch=compute_61,code=sm_61 '+ + '-gencode arch=compute_70,code=sm_70 -gencode arch=compute_75,code=sm_75 '+ + '-gencode arch=compute_75,code=compute_75') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/3 cudamodule/prog.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/3 cudamodule/prog.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/3 cudamodule/prog.cu" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/3 cudamodule/prog.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -27,4 +27,3 @@ return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/4 shared/shared/kernels.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/4 shared/shared/kernels.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/4 shared/shared/kernels.cu" 2019-02-28 20:43:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/4 shared/shared/kernels.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -11,4 +11,3 @@ return (int)cudaDeviceSynchronize(); } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/4 shared/shared/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/4 shared/shared/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/4 shared/shared/meson.build" 2019-02-28 20:43:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/4 shared/shared/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,5 +1,7 @@ libkernels = shared_library('kernels', 'kernels.cu', cuda_args: ['-DTAG_IS_SHARED=1', '-DTAG_IS_BUILDING=1'], - gnu_symbol_visibility: 'hidden') + gnu_symbol_visibility: 'hidden', + soversion : 1, + version : '1.2.3') libkernels = declare_dependency(compile_args: ['-DTAG_IS_SHARED=1'], link_with: libkernels) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/5 threads/shared/kernels.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/5 threads/shared/kernels.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/5 threads/shared/kernels.cu" 2019-02-28 20:43:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/5 threads/shared/kernels.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -11,4 +11,3 @@ return (int)cudaDeviceSynchronize(); } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/8 release/main.cu" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/8 release/main.cu" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/8 release/main.cu" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/8 release/main.cu" 2021-11-02 19:58:07.000000000 +0000 @@ -1,6 +1,10 @@ #include #include +#ifndef NDEBUG +#error "NDEBUG not defined, this is a Meson bug" +#endif + int cuda_devices(void) { int result = 0; cudaGetDeviceCount(&result); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/8 release/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/8 release/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cuda/8 release/meson.build" 2019-09-28 23:52:33.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cuda/8 release/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,10 @@ -project('release', 'cuda', version : '1.0.0', default_options : ['buildtype=release']) +project('release', 'cpp', 'cuda', version : '1.0.0', default_options : ['buildtype=release', 'b_ndebug=if-release']) -exe = executable('prog', 'main.cu') +# We don't actually need boost, but it serves as a common dependency +# that has the potential to add "-isystem/usr/include" to the compile +# line. By making it optional, we test that system search paths get +# removed without unnecessarily failing the test if boost is absent. +boost_dep = dependency('boost', include_type : 'system', required : false) + +exe = executable('prog', 'main.cu', dependencies : boost_dep) test('cudatest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/cytest.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/cytest.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/cytest.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/cytest.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +from storer import Storer + +s = Storer() + +if s.get_value() != 0: + raise SystemExit('Initial value incorrect.') + +s.set_value(42) + +if s.get_value() != 42: + raise SystemExit('Setting value failed.') + +try: + s.set_value('not a number') + raise SystemExit('Using wrong argument type did not fail.') +except TypeError: + pass diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/cstorer.pxd" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/cstorer.pxd" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/cstorer.pxd" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/cstorer.pxd" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ + +cdef extern from "storer.h": + ctypedef struct Storer: + pass + + Storer* storer_new(); + void storer_destroy(Storer *s); + int storer_get_value(Storer *s); + void storer_set_value(Storer *s, int v); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +slib = py3.extension_module( + 'storer', + 'storer.pyx', + 'storer.c', + dependencies : py3_dep +) + +pydir = meson.current_build_dir() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/storer.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/storer.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/storer.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/storer.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,24 @@ +#include"storer.h" +#include + +struct _Storer { + int value; +}; + +Storer* storer_new() { + Storer *s = malloc(sizeof(struct _Storer)); + s->value = 0; + return s; +} + +void storer_destroy(Storer *s) { + free(s); +} + +int storer_get_value(Storer *s) { + return s->value; +} + +void storer_set_value(Storer *s, int v) { + s->value = v; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/storer.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/storer.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/storer.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/storer.h" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,16 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _Storer Storer; + +Storer* storer_new(); +void storer_destroy(Storer *s); +int storer_get_value(Storer *s); +void storer_set_value(Storer *s, int v); + +#ifdef __cplusplus +} +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/storer.pyx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/storer.pyx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/libdir/storer.pyx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/libdir/storer.pyx" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,16 @@ +cimport cstorer + +cdef class Storer: + cdef cstorer.Storer* _c_storer + + def __cinit__(self): + self._c_storer = cstorer.storer_new() + + def __dealloc__(self): + cstorer.storer_destroy(self._c_storer) + + cpdef int get_value(self): + return cstorer.storer_get_value(self._c_storer) + + cpdef set_value(self, int value): + cstorer.storer_set_value(self._c_storer, value) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,20 @@ +project( + 'basic cython project', + ['cython', 'c'], + default_options : ['warning_level=3'] +) + +py_mod = import('python') +py3 = py_mod.find_installation() +py3_dep = py3.dependency(required : false) +if not py3_dep.found() + error('MESON_SKIP_TEST: Python library not found.') +endif + +subdir('libdir') + +test('cython tester', + py3, + args : files('cytest.py'), + env : ['PYTHONPATH=' + pydir] +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/1 basic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/1 basic/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "matrix": { + "options": { + "cython_language": [ + { "val": "c" }, + { "val": "cpp" } + ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/configure.pyx.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/configure.pyx.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/configure.pyx.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/configure.pyx.in" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +cpdef func(): + return "Hello, World!" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/generator.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/generator.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/generator.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/generator.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 + +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument('input') +parser.add_argument('output') +args = parser.parse_args() + +with open(args.input) as i, open(args.output, 'w') as o: + o.write(i.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/gen.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import textwrap + +parser = argparse.ArgumentParser() +parser.add_argument('output') +args = parser.parse_args() + +with open(args.output, 'w') as f: + f.write(textwrap.dedent('''\ + cpdef func(): + return "Hello, World!" + ''')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/g.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/g.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/g.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/g.in" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +cpdef func(): + return "Hello, World!" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/libdir/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/libdir/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/libdir/gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/libdir/gen.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import textwrap + +parser = argparse.ArgumentParser() +parser.add_argument('output') +args = parser.parse_args() + +with open(args.output, 'w') as f: + f.write(textwrap.dedent('''\ + cpdef func(): + return "Hello, World!" + ''')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/libdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/libdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/libdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/libdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,10 @@ +ct2 = custom_target( + 'ct2', + input : 'gen.py', + output : 'ct2.pyx', + command : [py3, '@INPUT@', '@OUTPUT@'], +) + +ct2_ext = py3.extension_module('ct2', ct2, dependencies : py3_dep) + +pydir = meson.current_build_dir() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/meson.build" 2021-08-18 11:22:25.000000000 +0000 @@ -0,0 +1,80 @@ +project( + 'generated cython sources', + ['cython'], +) + +py_mod = import('python') +py3 = py_mod.find_installation('python3') +py3_dep = py3.dependency(required : false) +if not py3_dep.found() + error('MESON_SKIP_TEST: Python library not found.') +endif + +ct = custom_target( + 'ct', + input : 'gen.py', + output : 'ct.pyx', + command : [py3, '@INPUT@', '@OUTPUT@'], +) + +ct_ext = py3.extension_module('ct', ct, dependencies : py3_dep) + +test( + 'custom target', + py3, + args : [files('test.py'), 'ct'], + env : ['PYTHONPATH=' + meson.current_build_dir()] +) + +# Test a CustomTargetIndex +cti = custom_target( + 'cti', + input : 'gen.py', + output : 'cti.pyx', + command : [py3, '@INPUT@', '@OUTPUT@'], +) + +cti_ext = py3.extension_module('cti', cti[0], dependencies : py3_dep) + +cf = configure_file( + input : 'configure.pyx.in', + output : 'cf.pyx', + copy : true, +) + +cf_ext = py3.extension_module('cf', cf, dependencies : py3_dep) + +test( + 'configure file', + py3, + args : [files('test.py'), 'cf'], + env : ['PYTHONPATH=' + meson.current_build_dir()] +) + +gen = generator( + find_program('generator.py'), + arguments : ['@INPUT@', '@OUTPUT@'], + output : '@BASENAME@.pyx', +) + +g_ext = py3.extension_module( + 'g', + gen.process('g.in'), + dependencies : py3_dep, +) + +test( + 'generator', + py3, + args : [files('test.py'), 'g'], + env : ['PYTHONPATH=' + meson.current_build_dir()] +) + +subdir('libdir') + +test( + 'custom target in subdir', + py3, + args : [files('test.py'), 'ct2'], + env : ['PYTHONPATH=' + pydir] +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/test.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/test.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/cython/2 generated sources/test.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/cython/2 generated sources/test.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import importlib + +parser = argparse.ArgumentParser() +parser.add_argument('mod') +args = parser.parse_args() + +mod = importlib.import_module(args.mod) + +assert mod.func() == 'Hello, World!' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/10 d cpp/cppmain.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/10 d cpp/cppmain.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/10 d cpp/cppmain.cpp" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/10 d cpp/cppmain.cpp" 2021-11-02 19:58:07.000000000 +0000 @@ -6,13 +6,13 @@ // initialize D runtime if (!rt_init()) return 1; - + print_hello(1); - + // terminate D runtime, each initialize call // must be paired with a terminate call. if (!rt_term()) return 1; - + return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/12 root include directory/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/12 root include directory/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/12 root include directory/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/12 root include directory/meson.build" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,7 @@ +project('some', 'd') + +project_dep = declare_dependency( + include_directories: ['.'], +) +subdir('some') + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/12 root include directory/some/dlang/code.d" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/12 root include directory/some/dlang/code.d" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/12 root include directory/some/dlang/code.d" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/12 root include directory/some/dlang/code.d" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,7 @@ +void foo() {} + +version (Windows) +{ + import core.sys.windows.dll; + mixin SimpleDllMain; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/12 root include directory/some/dlang/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/12 root include directory/some/dlang/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/12 root include directory/some/dlang/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/12 root include directory/some/dlang/meson.build" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,8 @@ +code_lib = library('code', + ['code.d'], + dependencies: [project_dep]) + +code_dep = declare_dependency( + link_with: code_lib, + dependencies: project_dep +) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/12 root include directory/some/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/12 root include directory/some/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/12 root include directory/some/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/12 root include directory/some/meson.build" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1 @@ +subdir('dlang') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/1 simple/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/1 simple/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/1 simple/installed_files.txt" 2016-08-21 11:17:04.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/1 simple/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/bin/dsimpleapp?exe diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/1 simple/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/1 simple/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/1 simple/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/1 simple/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/dsimpleapp"}, + {"type": "pdb", "file": "usr/bin/dsimpleapp", "language": "d"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/2 static library/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/2 static library/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/2 static library/installed_files.txt" 2016-08-21 11:17:04.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/2 static library/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/app_s?exe -usr/lib/libstuff.a diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/2 static library/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/2 static library/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/2 static library/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/2 static library/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/app_s"}, + {"type": "pdb", "file": "usr/bin/app_s", "language": "d"}, + {"type": "file", "file": "usr/lib/libstuff.a"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -usr/bin/app_d?exe -?msvc:usr/bin/stuff.dll -?msvc:usr/lib/stuff.lib -?gcc:usr/lib/libstuff.so -usr/lib/pkgconfig/test.pc diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/lld-test.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/lld-test.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/lld-test.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/lld-test.py" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +import argparse +import subprocess + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('ldd') + parser.add_argument('bin') + args = parser.parse_args() + + p, o, _ = subprocess.run([args.ldd, args.bin], stdout=subprocess.PIPE) + assert p == 0 + o = o.decode() + assert 'libstuff.so =>' in o, 'libstuff so not in linker path.' + assert 'libstuff.so => not found' not in o, 'libstuff.so not found correctly' + + +if __name__ == '__main__': + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/meson.build" 2020-01-07 21:12:26.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/meson.build" 2021-10-23 16:53:19.000000000 +0000 @@ -7,7 +7,7 @@ endif endif -ldyn = shared_library('stuff', 'libstuff.d', install : true) +subdir('sub') ed = executable('app_d', 'app.d', link_with : ldyn, install : true) test('linktest_dyn', ed) @@ -19,3 +19,8 @@ description: 'A test of D attributes to pkgconfig.generate.', d_module_versions: ['Use_Static'] ) + +ldd = find_program('ldd', required : false) +if ldd.found() + test('ldd-test.py', ed) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/sub/libstuff.d" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/sub/libstuff.d" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/sub/libstuff.d" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/sub/libstuff.d" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,14 @@ +import std.stdio; +import std.string : format; + +export int printLibraryString (string str) +{ + writeln ("Library says: %s".format (str)); + return 4; +} + +version (Windows) +{ + import core.sys.windows.dll; + mixin SimpleDllMain; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/sub/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +ldyn = shared_library('stuff', 'libstuff.d', install : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/3 shared library/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/3 shared library/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,11 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/app_d"}, + {"type": "pdb", "file": "usr/bin/app_d", "language": "d"}, + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/stuff"}, + {"type": "pdb", "file": "usr/bin/stuff", "language": "d"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/stuff"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff.lib"}, + {"type": "file", "file": "usr/lib/pkgconfig/test.pc"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/4 library versions/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/4 library versions/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/4 library versions/installed_files.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/4 library versions/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -?gcc:usr/lib/libsome.so -?gcc:usr/lib/libsome.so.0 -?gcc:usr/lib/libsome.so.1.2.3 -?gcc:usr/lib/libnoversion.so -?gcc:usr/lib/libonlyversion.so -?gcc:usr/lib/libonlyversion.so.1 -?gcc:usr/lib/libonlyversion.so.1.4.5 -?gcc:usr/lib/libonlysoversion.so -?gcc:usr/lib/libonlysoversion.so.5 -?msvc:usr/bin/noversion.dll -?msvc:usr/bin/onlysoversion-5.dll -?msvc:usr/bin/onlyversion-1.dll -?msvc:usr/bin/some-0.dll -?msvc:usr/lib/noversion.lib -?msvc:usr/lib/onlysoversion.lib -?msvc:usr/lib/onlyversion.lib -?msvc:usr/lib/some.lib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/4 library versions/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/4 library versions/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/4 library versions/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/4 library versions/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,25 @@ +{ + "installed": [ + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/some"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/some", "version": "0"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/some", "version": "1.2.3"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/noversion"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlyversion"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlyversion", "version": "1"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlyversion", "version": "1.4.5"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlysoversion"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlysoversion", "version": "5"}, + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/noversion"}, + {"type": "pdb", "file": "usr/bin/noversion", "language": "d"}, + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/onlysoversion", "version": "5"}, + {"type": "pdb", "file": "usr/bin/onlysoversion", "version": "5", "language": "d"}, + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/onlyversion", "version": "1"}, + {"type": "pdb", "file": "usr/bin/onlyversion", "version": "1", "language": "d"}, + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/some", "version": "0"}, + {"type": "pdb", "file": "usr/bin/some", "version": "0", "language": "d"}, + {"type": "implib", "file": "usr/lib/noversion"}, + {"type": "implib", "file": "usr/lib/onlysoversion"}, + {"type": "implib", "file": "usr/lib/onlyversion"}, + {"type": "implib", "file": "usr/lib/some"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/5 mixed/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/5 mixed/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/5 mixed/installed_files.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/5 mixed/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -usr/bin/appdc_d?exe -usr/bin/appdc_s?exe -usr/lib/libstuff.a -?gcc:usr/lib/libstuff.so -?msvc:usr/bin/stuff.dll -?msvc:usr/bin/stuff.pdb -?msvc:usr/lib/stuff.lib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/5 mixed/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/5 mixed/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/5 mixed/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/5 mixed/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,13 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/appdc_d"}, + {"type": "pdb", "file": "usr/bin/appdc_d", "language": "d"}, + {"type": "exe", "file": "usr/bin/appdc_s"}, + {"type": "pdb", "file": "usr/bin/appdc_s", "language": "d"}, + {"type": "file", "file": "usr/lib/libstuff.a"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/stuff"}, + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/stuff"}, + {"type": "pdb", "file": "usr/bin/stuff", "language": "c"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff.lib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/6 unittest/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/6 unittest/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/6 unittest/installed_files.txt" 2016-08-21 11:17:04.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/6 unittest/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/bin/dapp?exe diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/6 unittest/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/6 unittest/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/6 unittest/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/6 unittest/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/dapp"}, + {"type": "pdb", "file": "usr/bin/dapp", "language": "d"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/7 multilib/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/7 multilib/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/7 multilib/installed_files.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/7 multilib/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -usr/bin/app_d?exe -?gcc:usr/lib/libsay1.so -?gcc:usr/lib/libsay1.so.0 -?gcc:usr/lib/libsay1.so.1.2.3 -?gcc:usr/lib/libsay2.so -?gcc:usr/lib/libsay2.so.1 -?gcc:usr/lib/libsay2.so.1.2.4 -?msvc:usr/bin/say1-0.dll -?msvc:usr/bin/say2-1.dll -?msvc:usr/lib/say1.lib -?msvc:usr/lib/say2.lib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/7 multilib/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/7 multilib/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/7 multilib/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/7 multilib/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,18 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/app_d"}, + {"type": "pdb", "file": "usr/bin/app_d", "language": "d"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say1"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say1", "version": "0"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say1", "version": "1.2.3"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say2"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say2", "version": "1"}, + {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say2", "version": "1.2.4"}, + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/say1", "version": "0"}, + {"type": "pdb", "file": "usr/bin/say1", "version": "0", "language": "d"}, + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/say2", "version": "1"}, + {"type": "pdb", "file": "usr/bin/say2", "version": "1", "language": "d"}, + {"type": "implib", "file": "usr/lib/say1"}, + {"type": "implib", "file": "usr/lib/say2"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/9 features/app.d" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/9 features/app.d" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/d/9 features/app.d" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/d/9 features/app.d" 2021-11-02 19:58:07.000000000 +0000 @@ -41,19 +41,19 @@ exit (1); } } - + version (With_VersionInteger) version(3) exit(0); version (With_Debug) debug exit(0); - + version (With_DebugInteger) debug(3) exit(0); - + version (With_DebugIdentifier) debug(DebugIdentifier) exit(0); - + version (With_DebugAll) { int dbg = 0; debug dbg++; @@ -61,7 +61,7 @@ debug(3) dbg++; debug(4) dbg++; debug(DebugIdentifier) dbg++; - + if (dbg == 5) exit(0); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/100 no lang/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/100 no lang/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/100 no lang/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/100 no lang/main.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/100 no lang/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/100 no lang/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/100 no lang/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/100 no lang/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('target without lang') +executable('main', 'main.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/100 no lang/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/100 no lang/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/100 no lang/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/100 no lang/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/100 no lang/meson.build:2:0: ERROR: No host machine compiler for \"main.c\"" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/101 no glib-compile-resources/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/101 no glib-compile-resources/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/101 no glib-compile-resources/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/101 no glib-compile-resources/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +project('no glib-compile-resources') + +if find_program('glib-compile-resources', required: false).found() + error('MESON_SKIP_TEST test only applicable when glib-compile-resources is missing.') +endif + +gnome = import('gnome') +res = gnome.compile_resources('resources', 'trivial.gresource.xml') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/101 no glib-compile-resources/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/101 no glib-compile-resources/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/101 no glib-compile-resources/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/101 no glib-compile-resources/test.json" 2021-12-22 17:54:40.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/101 no glib-compile-resources/meson.build:8:0: ERROR: Program 'glib-compile-resources' not found or not executable" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/101 no glib-compile-resources/trivial.gresource.xml" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/101 no glib-compile-resources/trivial.gresource.xml" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/101 no glib-compile-resources/trivial.gresource.xml" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/101 no glib-compile-resources/trivial.gresource.xml" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ + + + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/102 number in combo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/102 number in combo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/102 number in combo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/102 number in combo/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +project('number in combo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/102 number in combo/nativefile.ini" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/102 number in combo/nativefile.ini" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/102 number in combo/nativefile.ini" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/102 number in combo/nativefile.ini" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +[built-in options] +optimization = 1 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/102 number in combo/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/102 number in combo/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/102 number in combo/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/102 number in combo/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "stdout": [ + { "line": "test cases/failing/102 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/103 bool in combo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/103 bool in combo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/103 bool in combo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/103 bool in combo/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +project('bool in combo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/103 bool in combo/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/103 bool in combo/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/103 bool in combo/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/103 bool in combo/meson_options.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +option( + 'opt', + type : 'combo', + choices : ['true', 'false'] +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/103 bool in combo/nativefile.ini" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/103 bool in combo/nativefile.ini" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/103 bool in combo/nativefile.ini" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/103 bool in combo/nativefile.ini" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +[project options] +opt = true diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/103 bool in combo/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/103 bool in combo/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/103 bool in combo/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/103 bool in combo/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "stdout": [ + { "line": "test cases/failing/103 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/104 compiler no lang/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/104 compiler no lang/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/104 compiler no lang/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/104 compiler no lang/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('compiler without lang') +meson.get_compiler('c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/104 compiler no lang/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/104 compiler no lang/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/104 compiler no lang/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/104 compiler no lang/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/104 compiler no lang/meson.build:2:6: ERROR: Tried to access compiler for language \"c\", not specified for host machine." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/105 no fallback/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/105 no fallback/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/105 no fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/105 no fallback/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('no fallback', 'c') +foob_dep = dependency('foob', allow_fallback: false, required: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/105 no fallback/subprojects/foob/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/105 no fallback/subprojects/foob/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/105 no fallback/subprojects/foob/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/105 no fallback/subprojects/foob/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('foob', 'c') +meson.override_dependency('foob', declare_dependency()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/105 no fallback/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/105 no fallback/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/105 no fallback/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/105 no fallback/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": ".*/meson\\.build:2:0: ERROR: (Pkg-config binary for machine MachineChoice\\.HOST not found\\. Giving up\\.|Dependency \"foob\" not found, tried .*)" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/106 feature require/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/106 feature require/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/106 feature require/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/106 feature require/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('no fallback', 'c') +foo = get_option('reqfeature').require(false, error_message: 'frobnicator not available') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/106 feature require/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/106 feature require/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/106 feature require/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/106 feature require/meson_options.txt" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +option('reqfeature', type : 'feature', value : 'enabled', description : 'A required feature') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/106 feature require/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/106 feature require/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/106 feature require/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/106 feature require/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": ".*/meson\\.build:2:0: ERROR: Feature reqfeature cannot be enabled: frobnicator not available" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/107 feature require.bis/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/107 feature require.bis/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/107 feature require.bis/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/107 feature require.bis/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,2 @@ +project('no fallback', 'c') +foo = get_option('reqfeature').require(false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/107 feature require.bis/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/107 feature require.bis/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/107 feature require.bis/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/107 feature require.bis/meson_options.txt" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1 @@ +option('reqfeature', type : 'feature', value : 'enabled', description : 'A required feature') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/107 feature require.bis/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/107 feature require.bis/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/107 feature require.bis/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/107 feature require.bis/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": ".*/meson\\.build:2:0: ERROR: Feature reqfeature cannot be enabled" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/108 no build get_external_property/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/108 no build get_external_property/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/108 no build get_external_property/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/108 no build get_external_property/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +project('missing property') + +message(meson.get_external_property('nonexisting', native : true)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/108 no build get_external_property/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/108 no build get_external_property/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/108 no build get_external_property/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/108 no build get_external_property/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/108 no build get_external_property/meson.build:3:0: ERROR: Unknown property for build machine: nonexisting" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/109 enter subdir twice/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/109 enter subdir twice/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/109 enter subdir twice/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/109 enter subdir twice/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +project('subdir2', 'c') +subdir('sub') +subdir('sub') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/109 enter subdir twice/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/109 enter subdir twice/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/109 enter subdir twice/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/109 enter subdir twice/sub/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1 @@ +message('Now in subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/109 enter subdir twice/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/109 enter subdir twice/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/109 enter subdir twice/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/109 enter subdir twice/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/109 enter subdir twice/meson.build:3:0: ERROR: Tried to enter directory \"sub\", which has already been visited." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/10 out of bounds/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/10 out of bounds/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/10 out of bounds/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/10 out of bounds/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/10 out of bounds/meson.build:4:0: ERROR: Index 0 out of bounds of array of size 0." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/111 invalid fstring/109 invalid fstring/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/111 invalid fstring/109 invalid fstring/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/111 invalid fstring/109 invalid fstring/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/111 invalid fstring/109 invalid fstring/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,4 @@ +project('invalid-fstring', 'c') + +dict = {'key': true} +s = f'invalid fstring: @dict@' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/111 invalid fstring/109 invalid fstring/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/111 invalid fstring/109 invalid fstring/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/111 invalid fstring/109 invalid fstring/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/111 invalid fstring/109 invalid fstring/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/109 invalid fstring/meson.build:4:0: ERROR: Identifier \"dict\" does not name a formattable variable (has to be an integer, a string, a floating point number or a boolean)." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/111 invalid fstring/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/111 invalid fstring/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/111 invalid fstring/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/111 invalid fstring/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +project('invalid-fstring', 'c') + +z = f'invalid fstring: @foo@' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/111 invalid fstring/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/111 invalid fstring/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/111 invalid fstring/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/111 invalid fstring/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/111 invalid fstring/meson.build:3:0: ERROR: Identifier \"foo\" does not name a variable." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/112 compiler argument checking/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/112 compiler argument checking/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/112 compiler argument checking/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/112 compiler argument checking/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,4 @@ +project('compiler argument checking test', 'c') + +cc = meson.get_compiler('c') +add_project_arguments(cc.get_supported_arguments('-meson-goober-arg-for-testing', checked : 'require'), language : 'c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/112 compiler argument checking/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/112 compiler argument checking/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/112 compiler argument checking/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/112 compiler argument checking/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/113 empty fallback/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/113 empty fallback/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/113 empty fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/113 empty fallback/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,6 @@ +project('empty fallback') + +# There is a subproject named 'foo' that overrides that dependency, +# but `fallback: []` should not allow to use it. Same behaviour than with +# `allow_fallback: false` +dependency('foo', fallback: []) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/113 empty fallback/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/113 empty fallback/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/113 empty fallback/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/113 empty fallback/subprojects/foo/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +project('foo') + +meson.override_dependency('foo', declare_dependency()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/113 empty fallback/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/113 empty fallback/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/113 empty fallback/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/113 empty fallback/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/113 empty fallback/meson.build:6:0: ERROR: Dependency \"foo\" not found, tried pkgconfig and cmake" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/114 cmake executable dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/114 cmake executable dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/114 cmake executable dependency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/114 cmake executable dependency/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,9 @@ +project('cmake-executable-dependency', ['c', 'cpp']) + +if not find_program('cmake', required: false).found() + error('MESON_SKIP_TEST CMake is not installed') +endif + +cmake = import('cmake') +cmlib = cmake.subproject('cmlib') +maind = cmlib.dependency('main') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/114 cmake executable dependency/subprojects/cmlib/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/114 cmake executable dependency/subprojects/cmlib/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/114 cmake executable dependency/subprojects/cmlib/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/114 cmake executable dependency/subprojects/cmlib/CMakeLists.txt" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmlib) + +add_executable(main main.c) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/114 cmake executable dependency/subprojects/cmlib/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/114 cmake executable dependency/subprojects/cmlib/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/114 cmake executable dependency/subprojects/cmlib/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/114 cmake executable dependency/subprojects/cmlib/main.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/114 cmake executable dependency/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/114 cmake executable dependency/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/114 cmake executable dependency/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/114 cmake executable dependency/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/115 allow_fallback with fallback/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/115 allow_fallback with fallback/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/115 allow_fallback with fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/115 allow_fallback with fallback/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +project('fallback and allow_fallback') + +dependency('foo', fallback: 'foo', allow_fallback: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/115 allow_fallback with fallback/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/115 allow_fallback with fallback/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/115 allow_fallback with fallback/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/115 allow_fallback with fallback/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "line": "test cases/failing/115 allow_fallback with fallback/meson.build:3:0: ERROR: \"fallback\" and \"allow_fallback\" arguments are mutually exclusive" + } + ] +} + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/116 nonsensical bindgen/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/116 nonsensical bindgen/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/116 nonsensical bindgen/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/116 nonsensical bindgen/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,20 @@ +# SPDX-license-identifer: Apache-2.0 +# Copyright © 2021 Intel Corporation + +project('rustmod bindgen', 'c') + +if not add_languages('rust', required: false) + error('MESON_SKIP_TEST test requires rust compiler') +endif + +prog_bindgen = find_program('bindgen', required : false) +if not prog_bindgen.found() + error('MESON_SKIP_TEST bindgen not found') +endif + +c_lib = static_library('clib', 'src/source.c') + +import('unstable-rust').bindgen( + input : c_lib, + output : 'header.rs', +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/116 nonsensical bindgen/src/header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/116 nonsensical bindgen/src/header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/116 nonsensical bindgen/src/header.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/116 nonsensical bindgen/src/header.h" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2021 Intel Corporation + +#pragma once + +#include + +int32_t add(const int32_t, const int32_t); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/116 nonsensical bindgen/src/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/116 nonsensical bindgen/src/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/116 nonsensical bindgen/src/source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/116 nonsensical bindgen/src/source.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2021 Intel Corporation + +#include "header.h" + +int32_t add(const int32_t first, const int32_t second) { + return first + second; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/116 nonsensical bindgen/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/116 nonsensical bindgen/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/116 nonsensical bindgen/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/116 nonsensical bindgen/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/117 run_target in test/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/117 run_target in test/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/117 run_target in test/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/117 run_target in test/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,4 @@ +project('trivial test', 'c') +exe = executable('trivialprog', 'trivial.c') +runt = run_target('invalid', command: ['echo', 'run_target']) +test('runtest', exe, args: runt) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/117 run_target in test/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/117 run_target in test/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/117 run_target in test/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/117 run_target in test/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/117 run_target in test/trivial.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/117 run_target in test/trivial.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/117 run_target in test/trivial.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/117 run_target in test/trivial.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("Trivial test is working.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/118 run_target in add_install_script/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/118 run_target in add_install_script/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/118 run_target in add_install_script/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/118 run_target in add_install_script/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,4 @@ +project('trivial test', 'c') +exe = executable('trivialprog', 'trivial.c') +runt = run_target('invalid', command: ['echo', 'run_target']) +meson.add_install_script(exe, runt) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/118 run_target in add_install_script/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/118 run_target in add_install_script/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/118 run_target in add_install_script/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/118 run_target in add_install_script/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/118 run_target in add_install_script/trivial.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/118 run_target in add_install_script/trivial.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/118 run_target in add_install_script/trivial.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/118 run_target in add_install_script/trivial.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,11 @@ +#include + +int main(int argc, char **argv) { + FILE *fp = fopen(argv[1], "r"); + if (fp == NULL) { + perror("fopen"); + return 1; + } else { + return 0; + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/119 pathsep in install_symlink/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/119 pathsep in install_symlink/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/119 pathsep in install_symlink/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/119 pathsep in install_symlink/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +project('symlink_pathsep') + +install_symlink('foo/bar', pointing_to: '/usr/baz/bar', install_dir: '/usr') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/119 pathsep in install_symlink/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/119 pathsep in install_symlink/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/119 pathsep in install_symlink/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/119 pathsep in install_symlink/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/11 object arithmetic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/11 object arithmetic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/11 object arithmetic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/11 object arithmetic/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": "test cases/failing/11 object arithmetic/meson\\.build:3:0: ERROR: The `\\+` operator of str does not accept objects of type MesonMain .*" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/12 string arithmetic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/12 string arithmetic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/12 string arithmetic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/12 string arithmetic/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/12 string arithmetic/meson.build:3:0: ERROR: The `+` operator of str does not accept objects of type int (3)" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/13 array arithmetic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/13 array arithmetic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/13 array arithmetic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/13 array arithmetic/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/13 array arithmetic/meson.build:3:0: ERROR: Object <[ArrayHolder] holds [list]: ['a', 'b']> of type array does not support the `*` operator." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/14 invalid option name/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/14 invalid option name/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/14 invalid option name/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/14 invalid option name/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/14 invalid option name/meson_options.txt:1:0: ERROR: Option names can only contain letters, numbers or dashes." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/15 kwarg before arg/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/15 kwarg before arg/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/15 kwarg before arg/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/15 kwarg before arg/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/15 kwarg before arg/meson.build:3:0: ERROR: All keyword arguments must be after positional arguments." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/16 extract from subproject/subprojects/sub_project/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/16 extract from subproject/subprojects/sub_project/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/16 extract from subproject/subprojects/sub_project/meson.build" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/16 extract from subproject/subprojects/sub_project/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -1,3 +1,3 @@ project('extract subproject object -- subproject', 'c') -lib = shared_library('sub_lib', 'sub_lib.c') +lib = library('sub_lib', 'sub_lib.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/16 extract from subproject/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/16 extract from subproject/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/16 extract from subproject/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/16 extract from subproject/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/16 extract from subproject/meson.build:6:0: ERROR: Tried to extract objects from a different subproject." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/17 same target/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/17 same target/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/17 same target/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/17 same target/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/17 same target/meson.build:4:0: ERROR: Tried to create target \"foo\", but a target of that name already exists." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/18 wrong plusassign/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/18 wrong plusassign/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/18 wrong plusassign/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/18 wrong plusassign/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/18 wrong plusassign/meson.build:3:0: ERROR: Plusassignment target must be an id." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/19 target clash/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/19 target clash/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/19 target clash/meson.build" 2017-04-15 14:27:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/19 target clash/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -8,8 +8,8 @@ # output location is redirected. if host_machine.system() == 'windows' or host_machine.system() == 'cygwin' - error('This is expected.') + error('MESON_SKIP_TEST test only works on platforms where executables have no suffix.') endif executable('clash', 'clash.c') -run_target('clash', 'echo', 'clash 1') +run_target('clash', command: ['echo', 'clash 1']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/19 target clash/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/19 target clash/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/19 target clash/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/19 target clash/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "ERROR: Multiple producers for Ninja target \"clash\". Please rename your targets." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/1 project not first/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/1 project not first/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/1 project not first/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/1 project not first/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "ERROR: Invalid source tree: first statement must be a call to project()" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/20 version/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/20 version/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/20 version/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/20 version/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": "test cases/failing/20 version/meson\\.build:1:0: ERROR: Meson version is .* but project requires >100\\.0\\.0" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/21 subver/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/21 subver/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/21 subver/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/21 subver/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/21 subver/meson.build:3:0: ERROR: Subproject foo version is 1.0.0 but >1.0.0 required." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/22 assert/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/22 assert/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/22 assert/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/22 assert/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/22 assert/meson.build:3:0: ERROR: Assert failed: I am fail." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/23 rel testdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/23 rel testdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/23 rel testdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/23 rel testdir/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/23 rel testdir/meson.build:4:0: ERROR: test keyword argument \"workdir\" must be an absolute path" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/24 int conversion/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/24 int conversion/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/24 int conversion/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/24 int conversion/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/24 int conversion/meson.build:3:13: ERROR: String 'notanumber' cannot be converted to int" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/25 badlang/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/25 badlang/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/25 badlang/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/25 badlang/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/25 badlang/meson.build:3:0: ERROR: Tried to use unknown language \"nonexisting\"." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/26 output subdir/subdir/dummy.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/26 output subdir/subdir/dummy.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/26 output subdir/subdir/dummy.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/26 output subdir/subdir/dummy.txt" 2021-11-02 19:58:07.000000000 +0000 @@ -1,2 +1 @@ I'm only here because Git is stupid about empty dirs. - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/26 output subdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/26 output subdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/26 output subdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/26 output subdir/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/26 output subdir/meson.build:3:0: ERROR: Output file name must not contain a subdirectory." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/27 noprog use/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/27 noprog use/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/27 noprog use/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/27 noprog use/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/27 noprog use/meson.build:5:0: ERROR: Tried to use not-found external program in \"command\"" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/28 no crossprop/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/28 no crossprop/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/28 no crossprop/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/28 no crossprop/test.json" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/28 no crossprop/meson.build:3:0: ERROR: Unknown property for host machine: nonexisting" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/29 nested ternary/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/29 nested ternary/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/29 nested ternary/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/29 nested ternary/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/29 nested ternary/meson.build:3:12: ERROR: Nested ternary operators are not allowed." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/2 missing file/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/2 missing file/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/2 missing file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/2 missing file/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/2 missing file/meson.build:3:0: ERROR: File missing.c does not exist." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/30 invalid man extension/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/30 invalid man extension/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/30 invalid man extension/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/30 invalid man extension/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/30 invalid man extension/meson.build:2:0: ERROR: Man file must have a file extension of a number between 1 and 9" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/31 no man extension/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/31 no man extension/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/31 no man extension/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/31 no man extension/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/31 no man extension/meson.build:2:0: ERROR: Man file must have a file extension of a number between 1 and 9" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/32 exe static shared/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/32 exe static shared/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/32 exe static shared/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/32 exe static shared/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -2,7 +2,7 @@ host_system = host_machine.system() if host_system == 'windows' or host_system == 'darwin' - error('Test only fails on Linux and BSD') + error('MESON_SKIP_TEST test only fails on Linux and BSD') endif statlib = static_library('stat', 'stat.c', pic : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/32 exe static shared/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/32 exe static shared/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/32 exe static shared/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/32 exe static shared/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/32 exe static shared/meson.build:9:0: ERROR: Can't link non-PIC static library 'stat' into shared library 'shr2'. Use the 'pic' option to static_library to build with PIC." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/33 non-root subproject/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/33 non-root subproject/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/33 non-root subproject/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/33 non-root subproject/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/33 non-root subproject/some/meson.build:1:0: ERROR: Neither a subproject directory nor a someproj.wrap file was found." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/34 dependency not-required then required/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/34 dependency not-required then required/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/34 dependency not-required then required/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/34 dependency not-required then required/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": ".*/meson\\.build:4:0: ERROR: (Pkg-config binary for machine MachineChoice\\.HOST not found\\. Giving up\\.|Dependency \"foo\\-bar\\-xyz\\-12\\.3\" not found, tried .*)" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/35 project argument after target/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/35 project argument after target/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/35 project argument after target/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/35 project argument after target/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/35 project argument after target/meson.build:7:0: ERROR: Tried to use 'add_project_arguments' after a build target has been declared." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/36 pkgconfig dependency impossible conditions/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/36 pkgconfig dependency impossible conditions/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/36 pkgconfig dependency impossible conditions/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/36 pkgconfig dependency impossible conditions/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -1,3 +1,7 @@ project('impossible-dep-test', 'c', version : '1.0') +if not dependency('zlib', required: false).found() + error('MESON_SKIP_TEST test requires zlib') +endif + dependency('zlib', version : ['>=1.0', '<1.0']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/36 pkgconfig dependency impossible conditions/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/36 pkgconfig dependency impossible conditions/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/36 pkgconfig dependency impossible conditions/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/36 pkgconfig dependency impossible conditions/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/36 pkgconfig dependency impossible conditions/meson.build:7:0: ERROR: Dependency 'zlib' is required but not found." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/37 has function external dependency/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/37 has function external dependency/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/37 has function external dependency/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/37 has function external dependency/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/37 has function external dependency/meson.build:8:3: ERROR: Dependencies must be external dependencies" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/38 libdir must be inside prefix/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/38 libdir must be inside prefix/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/38 libdir must be inside prefix/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/38 libdir must be inside prefix/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -1,2 +1,6 @@ project('libdir prefix', 'c', default_options : ['libdir=/opt/lib']) + +if host_machine.system() == 'windows' + error('MESON_SKIP_TEST: this test does not work on Windows since /foo is not absolute') +endif \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/38 libdir must be inside prefix/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/38 libdir must be inside prefix/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/38 libdir must be inside prefix/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/38 libdir must be inside prefix/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "do_not_set_opts": [ + "libdir" + ], + "stdout": [ + { + "line": "test cases/failing/38 libdir must be inside prefix/meson.build:1:0: ERROR: The value of the 'libdir' option is '/opt/lib' which must be a subdir of the prefix '/usr'." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/39 prefix absolute/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/39 prefix absolute/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/39 prefix absolute/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/39 prefix absolute/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,11 @@ +{ + "do_not_set_opts": [ + "prefix" + ], + "stdout": [ + { + "comment": "literal 'some/path/notabs' appears in output, irrespective of os.path.sep, as that's the prefix", + "line": "test cases/failing/39 prefix absolute/meson.build:1:0: ERROR: prefix value 'some/path/notabs' must be an absolute path" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/3 missing subdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/3 missing subdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/3 missing subdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/3 missing subdir/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "stdout": [ + { + "comment": "'missing/meson.build' gets transformed with os.path.sep separators", + "match": "re", + "line": "test cases/failing/3 missing subdir/meson\\.build:3:0: ERROR: Non\\-existent build file 'missing[\\\\/]meson\\.build'" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/40 kwarg assign/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/40 kwarg assign/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/40 kwarg assign/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/40 kwarg assign/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,3 @@ project('assign in kwarg', 'c') executable('prog', 'dummy.c', args = 'prog.c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/40 kwarg assign/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/40 kwarg assign/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/40 kwarg assign/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/40 kwarg assign/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/40 kwarg assign/meson.build:3:0: ERROR: Tried to assign values inside an argument list." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/41 custom target plainname many inputs/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/41 custom target plainname many inputs/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/41 custom target plainname many inputs/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/41 custom target plainname many inputs/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/41 custom target plainname many inputs/meson.build:5:0: ERROR: Output cannot contain @PLAINNAME@ or @BASENAME@ when there is more than one input (we can't know which to use)" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/42 custom target outputs not matching install_dirs/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/42 custom target outputs not matching install_dirs/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/42 custom target outputs not matching install_dirs/installed_files.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/42 custom target outputs not matching install_dirs/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -usr/include/diff.h -usr/include/first.h -usr/bin/diff.sh -usr/bin/second.sh -opt/same.h -opt/same.sh diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/42 custom target outputs not matching install_dirs/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/42 custom target outputs not matching install_dirs/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/42 custom target outputs not matching install_dirs/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/42 custom target outputs not matching install_dirs/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -3,7 +3,7 @@ gen = find_program('generator.py') if meson.backend() != 'ninja' - error('Failing manually, test is only for the ninja backend') + error('MESON_SKIP_TEST test is only for the ninja backend') endif custom_target('too-few-install-dirs', diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/42 custom target outputs not matching install_dirs/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/42 custom target outputs not matching install_dirs/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/42 custom target outputs not matching install_dirs/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/42 custom target outputs not matching install_dirs/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,33 @@ +{ + "installed": [ + { + "type": "file", + "file": "usr/include/diff.h" + }, + { + "type": "file", + "file": "usr/include/first.h" + }, + { + "type": "file", + "file": "usr/bin/diff.sh" + }, + { + "type": "file", + "file": "usr/bin/second.sh" + }, + { + "type": "file", + "file": "opt/same.h" + }, + { + "type": "file", + "file": "opt/same.sh" + } + ], + "stdout": [ + { + "line": "ERROR: Target 'too-few-install-dirs' has 3 outputs: ['toofew.h', 'toofew.c', 'toofew.sh'], but only 2 \"install_dir\"s were found." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/43 project name colon/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/43 project name colon/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/43 project name colon/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/43 project name colon/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/43 project name colon/meson.build:1:0: ERROR: Project name 'name with :' must not contain ':'" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/44 abs subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/44 abs subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/44 abs subdir/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/44 abs subdir/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -3,4 +3,3 @@ # For some reason people insist on doing this, probably # because Make has taught them to never rely on anything. subdir(join_paths(meson.source_root(), 'bob')) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/44 abs subdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/44 abs subdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/44 abs subdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/44 abs subdir/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/44 abs subdir/meson.build:5:0: ERROR: Subdir argument must be a relative path." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/45 abspath to srcdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/45 abspath to srcdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/45 abspath to srcdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/45 abspath to srcdir/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/45 abspath to srcdir/meson.build:3:0: ERROR: Tried to form an absolute path to a source dir." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/46 pkgconfig variables reserved/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/46 pkgconfig variables reserved/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/46 pkgconfig variables reserved/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/46 pkgconfig variables reserved/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/46 pkgconfig variables reserved/meson.build:8:5: ERROR: Variable \"prefix\" is reserved" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/47 pkgconfig variables zero length/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/47 pkgconfig variables zero length/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/47 pkgconfig variables zero length/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/47 pkgconfig variables zero length/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/47 pkgconfig variables zero length/meson.build:8:5: ERROR: Empty variable name or value" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/48 pkgconfig variables zero length value/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/48 pkgconfig variables zero length value/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/48 pkgconfig variables zero length value/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/48 pkgconfig variables zero length value/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/48 pkgconfig variables zero length value/meson.build:8:5: ERROR: Empty variable name or value" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/49 pkgconfig variables not key value/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/49 pkgconfig variables not key value/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/49 pkgconfig variables not key value/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/49 pkgconfig variables not key value/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/49 pkgconfig variables not key value/meson.build:8:5: ERROR: Variable 'this_should_be_key_value' must have a value separated by equals sign." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/4 missing meson.build/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/4 missing meson.build/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/4 missing meson.build/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/4 missing meson.build/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "stdout": [ + { + "match": "re", + "comment": "'subdir/meson.build' gets transformed with os.path.sep separators", + "line": "test cases/failing/4 missing meson\\.build/meson\\.build:3:0: ERROR: Non\\-existent build file 'subdir[\\\\/]meson\\.build'" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/50 executable comparison/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/50 executable comparison/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/50 executable comparison/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/50 executable comparison/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": "test cases/failing/50 executable comparison/meson.build:6:0: ERROR: Object of type Executable does not support the `<` operator." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/51 inconsistent comparison/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/51 inconsistent comparison/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/51 inconsistent comparison/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/51 inconsistent comparison/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/51 inconsistent comparison/meson.build:5:0: ERROR: Object <[ArrayHolder] holds [list]: []> of type array does not support the `<` operator." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/52 slashname/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/52 slashname/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/52 slashname/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/52 slashname/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -9,4 +9,3 @@ executable('sub/prog', pf) error('Re-enable me once slash in name is finally prohibited.') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/52 slashname/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/52 slashname/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/52 slashname/sub/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/52 slashname/sub/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,2 +1 @@ pf = files('prog.c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/52 slashname/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/52 slashname/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/52 slashname/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/52 slashname/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/52 slashname/meson.build:9:0: ERROR: Target \"sub/prog\" has a path segment pointing to directory \"sub\". This is an error." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/53 reserved meson prefix/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/53 reserved meson prefix/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/53 reserved meson prefix/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/53 reserved meson prefix/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/53 reserved meson prefix/meson.build:3:0: ERROR: The \"meson-\" prefix is reserved and cannot be used for top-level subdir()." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/54 wrong shared crate type/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/54 wrong shared crate type/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/54 wrong shared crate type/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/54 wrong shared crate type/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -1,3 +1,7 @@ -project('test', 'rust') +project('test') + +if not add_languages('rust', required: false) + error('MESON_SKIP_TEST test requires rust compiler') +endif shared_library('test', 'foo.rs', rust_crate_type : 'staticlib') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/54 wrong shared crate type/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/54 wrong shared crate type/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/54 wrong shared crate type/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/54 wrong shared crate type/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/54 wrong shared crate type/meson.build:7:0: ERROR: Crate type \"staticlib\" invalid for dynamic libraries; must be \"dylib\" or \"cdylib\"" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/55 wrong static crate type/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/55 wrong static crate type/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/55 wrong static crate type/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/55 wrong static crate type/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -1,3 +1,7 @@ -project('test', 'rust') +project('test') + +if not add_languages('rust', required: false) + error('MESON_SKIP_TEST test requires rust compiler') +endif static_library('test', 'foo.rs', rust_crate_type : 'cdylib') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/55 wrong static crate type/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/55 wrong static crate type/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/55 wrong static crate type/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/55 wrong static crate type/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/55 wrong static crate type/meson.build:7:0: ERROR: Crate type \"cdylib\" invalid for static libraries; must be \"rlib\" or \"staticlib\"" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/56 or on new line/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/56 or on new line/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/56 or on new line/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/56 or on new line/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/56 or on new line/meson.build:4:8: ERROR: Invalid or clause." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 kwarg in module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 kwarg in module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 kwarg in module/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 kwarg in module/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('module test', 'c') - -modtest = import('modtest', i_cause: 'a_build_failure') -modtest.print_hello() - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 link with executable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 link with executable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 link with executable/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 link with executable/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('link with exe', 'c') + +e = executable('prog', 'prog.c') +m = shared_module('module', 'module.c', link_with: e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 link with executable/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 link with executable/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 link with executable/module.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 link with executable/module.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ + +int func(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 link with executable/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 link with executable/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 link with executable/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 link with executable/prog.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +int +main (int argc, char **argv) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 link with executable/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 link with executable/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/57 link with executable/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/57 link with executable/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/57 link with executable/meson.build:4:0: ERROR: Link target 'prog' is not linkable." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 assign custom target index/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 assign custom target index/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 assign custom target index/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 assign custom target index/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,24 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +prog_python = import('python3').find_python() + +target = custom_target( + 'target', + output : ['1', '2'], + command : [prog_python, '-c', + 'with open("1", "w") as f: f.write("foo"); with open("2", "w") as f: f.write("foo")'], +) + +target[0] = 'foo' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 assign custom target index/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 assign custom target index/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 assign custom target index/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 assign custom target index/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/58 assign custom target index/meson.build:24:0: ERROR: Assignment target must be an id." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 link with executable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 link with executable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 link with executable/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 link with executable/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('link with exe', 'c') - -e = executable('prog', 'prog.c') -m = shared_module('module', 'module.c', link_with: e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 link with executable/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 link with executable/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 link with executable/module.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 link with executable/module.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -int func(void) { - return 42; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 link with executable/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 link with executable/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/58 link with executable/prog.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/58 link with executable/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -int -main (int argc, char **argv) -{ - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 assign custom target index/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 assign custom target index/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 assign custom target index/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 assign custom target index/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -# Copyright © 2017 Intel Corporation -# -# 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. - -prog_python = import('python3').find_python() - -target = custom_target( - 'target', - output : ['1', '2'], - command : [prog_python, '-c', - 'with open("1", "w") as f: f.write("foo"); with open("2", "w") as f: f.write("foo")'], -) - -target[0] = 'foo' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 getoption prefix/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 getoption prefix/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 getoption prefix/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 getoption prefix/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +project('getopt prefix') + +subproject('abc') + +get_option('abc:foo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 getoption prefix/subprojects/abc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 getoption prefix/subprojects/abc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 getoption prefix/subprojects/abc/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 getoption prefix/subprojects/abc/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +project('abc', 'c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 getoption prefix/subprojects/abc/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 getoption prefix/subprojects/abc/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 getoption prefix/subprojects/abc/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 getoption prefix/subprojects/abc/meson_options.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +option('foo', type : 'boolean') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 getoption prefix/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 getoption prefix/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/59 getoption prefix/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/59 getoption prefix/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/59 getoption prefix/meson.build:5:0: ERROR: Having a colon in option name is forbidden, projects are not allowed to directly access options of other subprojects." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/5 misplaced option/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/5 misplaced option/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/5 misplaced option/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/5 misplaced option/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/5 misplaced option/meson.build:3:0: ERROR: Tried to call option() in build description file. All options must be in the option file." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 bad option argument/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 bad option argument/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 bad option argument/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 bad option argument/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('bad option') + +get_option('name') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 bad option argument/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 bad option argument/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 bad option argument/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 bad option argument/meson_options.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +option('name', type : 'string', vaule : 'foo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 bad option argument/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 bad option argument/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 bad option argument/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 bad option argument/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/60 bad option argument/meson_options.txt:1:0: ERROR: option got unknown keyword arguments \"vaule\"" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 getoption prefix/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 getoption prefix/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 getoption prefix/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 getoption prefix/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('getopt prefix') - -subproject('abc') - -get_option('abc:foo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 getoption prefix/subprojects/abc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 getoption prefix/subprojects/abc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 getoption prefix/subprojects/abc/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 getoption prefix/subprojects/abc/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -project('abc', 'c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 getoption prefix/subprojects/abc/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 getoption prefix/subprojects/abc/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/60 getoption prefix/subprojects/abc/meson_options.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/60 getoption prefix/subprojects/abc/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -option('foo', type : 'boolean') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 bad option argument/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 bad option argument/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 bad option argument/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 bad option argument/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('bad option') - -get_option('name') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 bad option argument/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 bad option argument/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 bad option argument/meson_options.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 bad option argument/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -option('name', type : 'string', vaule : 'foo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 subproj filegrab/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 subproj filegrab/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 subproj filegrab/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 subproj filegrab/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +project('mainproj', 'c') + +# Try to grab a file from a parent project. + +subproject('a') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 subproj filegrab/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 subproj filegrab/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 subproj filegrab/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 subproj filegrab/prog.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +int main(int argc, char **argv) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 subproj filegrab/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 subproj filegrab/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 subproj filegrab/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 subproj filegrab/subprojects/a/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('a', 'c') + +executable('prog', '../../prog.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 subproj filegrab/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 subproj filegrab/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/61 subproj filegrab/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/61 subproj filegrab/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/61 subproj filegrab/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file prog.c outside current (sub)project." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 grab subproj/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 grab subproj/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 grab subproj/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 grab subproj/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +project('grabber', 'c') + +# Try to grab a file from a child subproject. + +subproject('foo') + +executable('foo', 'subprojects/foo/sub.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 grab subproj/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 grab subproj/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 grab subproj/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 grab subproj/subprojects/foo/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('foo', 'c') + +message('I do nothing.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 grab subproj/subprojects/foo/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 grab subproj/subprojects/foo/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 grab subproj/subprojects/foo/sub.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 grab subproj/subprojects/foo/sub.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + printf("I am a subproject executable file.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 grab subproj/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 grab subproj/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 grab subproj/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 grab subproj/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/62 grab subproj/meson.build:7:0: ERROR: Sandbox violation: Tried to grab file sub.c from a nested subproject." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 subproj filegrab/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 subproj filegrab/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 subproj filegrab/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 subproj filegrab/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('mainproj', 'c') - -# Try to grab a file from a parent project. - -subproject('a') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 subproj filegrab/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 subproj filegrab/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 subproj filegrab/prog.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 subproj filegrab/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(int argc, char **argv) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 subproj filegrab/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 subproj filegrab/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/62 subproj filegrab/subprojects/a/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/62 subproj filegrab/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('a', 'c') - -executable('prog', '../../prog.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('master', 'c') + +subproject('a') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/subprojects/a/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('a', 'c') + +executable('sneaky', '../b/sneaky.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/subprojects/b/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/subprojects/b/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/subprojects/b/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/subprojects/b/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +projecT('b', 'c') + +message('I do nothing.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/subprojects/b/sneaky.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/subprojects/b/sneaky.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/subprojects/b/sneaky.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/subprojects/b/sneaky.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + printf("I can only come into existence via trickery.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab sibling/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab sibling/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/63 grab sibling/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file sneaky.c outside current (sub)project." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab subproj/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab subproj/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab subproj/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab subproj/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('grabber', 'c') - -# Try to grab a file from a child subproject. - -subproject('foo') - -executable('foo', 'subprojects/foo/sub.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab subproj/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab subproj/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab subproj/subprojects/foo/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab subproj/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('foo', 'c') - -message('I do nothing.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab subproj/subprojects/foo/sub.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab subproj/subprojects/foo/sub.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/63 grab subproj/subprojects/foo/sub.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/63 grab subproj/subprojects/foo/sub.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(int argc, char **argv) { - printf("I am a subproject executable file.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 grab sibling/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 grab sibling/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 grab sibling/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 grab sibling/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('master', 'c') - -subproject('a') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 grab sibling/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 grab sibling/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 grab sibling/subprojects/a/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 grab sibling/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('a', 'c') - -executable('sneaky', '../b/sneaky.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 grab sibling/subprojects/b/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 grab sibling/subprojects/b/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 grab sibling/subprojects/b/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 grab sibling/subprojects/b/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -projecT('b', 'c') - -message('I do nothing.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 grab sibling/subprojects/b/sneaky.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 grab sibling/subprojects/b/sneaky.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 grab sibling/subprojects/b/sneaky.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 grab sibling/subprojects/b/sneaky.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(int argc, char **argv) { - printf("I can only come into existence via trickery.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 string as link target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 string as link target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 string as link target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 string as link target/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('string as link argument', 'c') +executable('myprog', 'prog.c', link_with: [ '' ]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 string as link target/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 string as link target/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 string as link target/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 string as link target/prog.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +int main(int argc, char **argv) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 string as link target/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 string as link target/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/64 string as link target/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/64 string as link target/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/64 string as link target/meson.build:2:0: ERROR: '' is not a target." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/65 dependency not-found and required/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/65 dependency not-found and required/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/65 dependency not-found and required/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/65 dependency not-found and required/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('dep-test') +dep = dependency('', required:true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/65 dependency not-found and required/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/65 dependency not-found and required/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/65 dependency not-found and required/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/65 dependency not-found and required/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/65 dependency not-found and required/meson.build:2:0: ERROR: Dependency is required but has no candidates." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/65 string as link target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/65 string as link target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/65 string as link target/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/65 string as link target/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('string as link argument', 'c') -executable('myprog', 'prog.c', link_with: [ '' ]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/65 string as link target/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/65 string as link target/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/65 string as link target/prog.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/65 string as link target/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(int argc, char **argv) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 dependency not-found and required/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 dependency not-found and required/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 dependency not-found and required/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 dependency not-found and required/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('dep-test') -dep = dependency('', required:true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/main.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ +#include +#include "a.h" +#include "b.h" + +int main(int argc, char **argv) { + int life = a_fun() + b_fun(); + printf("%d\n", life); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ +project('super', 'c') + +# A will use version 1 of C +a_dep = dependency('a', fallback: ['a', 'a_dep']) + +# B will fail because it requests version 2 of C +b_dep = dependency('b', fallback: ['b', 'b_dep']) + +main = executable('main', files('main.c'), dependencies: [a_dep, b_dep]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/a/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/a/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/a/a.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/a/a.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +#include "c.h" + +int a_fun() { + return c_fun(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/a/a.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/a/a.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/a/a.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/a/a.h" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +int a_fun(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/a/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,11 @@ +project('a', 'c') + +c_dep = dependency('c', version:'1', fallback: ['c', 'c_dep']) + +alib = library('a', 'a.c', + dependencies: c_dep) + +a_dep = declare_dependency( + link_with: alib, + include_directories: include_directories('.'), +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/b/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/b/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/b/b.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/b/b.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +#include "c.h" + +int b_fun(){ +return c_fun(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/b/b.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/b/b.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/b/b.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/b/b.h" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +int b_fun(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/b/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/b/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/b/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/b/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,11 @@ +project('b', 'c') + +c_dep = dependency('c', version:'2', fallback: ['c', 'c_dep']) + +blib = library('b', 'b.c', + dependencies: c_dep) + +b_dep = declare_dependency( + link_with: blib, + include_directories: include_directories('.'), +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/c/c.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/c/c.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/c/c.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/c/c.h" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +static int c_fun(){ + return 3; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/c/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/c/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/subprojects/c/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/subprojects/c/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +project('c', 'c', version:'1') + +c_dep = declare_dependency( + include_directories: include_directories('.') +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/66 subproj different versions/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/66 subproj different versions/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/66 subproj different versions/subprojects/b/meson.build:3:0: ERROR: Dependency 'c' is required but not found." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/main.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#include -#include "a.h" -#include "b.h" - -int main(int argc, char **argv) { - int life = a_fun() + b_fun(); - printf("%d\n", life); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('super', 'c') - -# A will use version 1 of C -a_dep = dependency('a', fallback: ['a', 'a_dep']) - -# B will fail because it requests version 2 of C -b_dep = dependency('b', fallback: ['b', 'b_dep']) - -main = executable('main', files('main.c'), dependencies: [a_dep, b_dep]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/a/a.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/a/a.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/a/a.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/a/a.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "c.h" - -int a_fun() { - return c_fun(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/a/a.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/a/a.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/a/a.h" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/a/a.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int a_fun(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/a/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/a/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/a/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/a/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('a', 'c') - -c_dep = dependency('c', version:'1', fallback: ['c', 'c_dep']) - -alib = library('a', 'a.c', - dependencies: c_dep) - -a_dep = declare_dependency( - link_with: alib, - include_directories: include_directories('.'), -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/b/b.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/b/b.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/b/b.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/b/b.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include "c.h" - -int b_fun(){ -return c_fun(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/b/b.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/b/b.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/b/b.h" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/b/b.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int b_fun(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/b/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/b/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/b/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/b/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('b', 'c') - -c_dep = dependency('c', version:'2', fallback: ['c', 'c_dep']) - -blib = library('b', 'b.c', - dependencies: c_dep) - -b_dep = declare_dependency( - link_with: blib, - include_directories: include_directories('.'), -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/c/c.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/c/c.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/c/c.h" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/c/c.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -static int c_fun(){ - return 3; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/c/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/c/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 subproj different versions/subprojects/c/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 subproj different versions/subprojects/c/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('c', 'c', version:'1') - -c_dep = declare_dependency( - include_directories: include_directories('.') -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 wrong boost module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 wrong boost module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 wrong boost module/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 wrong boost module/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ +project('boosttest', 'cpp', + default_options : ['cpp_std=c++11']) + +if not dependency('boost', required: false).found() + error('MESON_SKIP_TEST test requires boost') +endif + +# abc doesn't exist +linkdep = dependency('boost', modules : ['thread', 'system', 'test', 'abc']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 wrong boost module/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 wrong boost module/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/67 wrong boost module/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/67 wrong boost module/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/67 wrong boost module/meson.build:9:0: ERROR: Dependency \"boost\" not found, tried system" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/68 install_data rename bad size/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/68 install_data rename bad size/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/68 install_data rename bad size/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/68 install_data rename bad size/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('data install test', 'c') + +install_data(['file1.txt', 'file2.txt'], rename : 'just one name') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/68 install_data rename bad size/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/68 install_data rename bad size/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/68 install_data rename bad size/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/68 install_data rename bad size/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/68 install_data rename bad size/meson.build:3:0: ERROR: \"rename\" and \"sources\" argument lists must be the same length if \"rename\" is given. Rename has 1 elements and sources has 2." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/68 wrong boost module/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/68 wrong boost module/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/68 wrong boost module/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/68 wrong boost module/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('boosttest', 'cpp', - default_options : ['cpp_std=c++11']) - -# abc doesn't exist -linkdep = dependency('boost', modules : ['thread', 'system', 'test', 'abc']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/69 install_data rename bad size/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/69 install_data rename bad size/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/69 install_data rename bad size/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/69 install_data rename bad size/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('data install test', 'c') - -install_data(['file1.txt', 'file2.txt'], rename : 'just one name') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/69 skip only subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/69 skip only subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/69 skip only subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/69 skip only subdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +# Check that skip_rest only exits subdir, not the whole script. +# Should create an error because main.cpp does not exists. +project('example exit', 'cpp') + +subdir('subdir') + +message('Good') +executable('main', 'main.cpp') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/69 skip only subdir/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/69 skip only subdir/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/69 skip only subdir/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/69 skip only subdir/subdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +subdir_done() + +error('Unreachable') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/69 skip only subdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/69 skip only subdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/69 skip only subdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/69 skip only subdir/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/69 skip only subdir/meson.build:8:0: ERROR: File main.cpp does not exist." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/6 missing incdir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/6 missing incdir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/6 missing incdir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/6 missing incdir/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/6 missing incdir/meson.build:3:0: ERROR: Include dir nosuchdir does not exist." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 dual override/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 dual override/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 dual override/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 dual override/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +project('yo dawg', 'c') + +p = find_program('overrides.py') +meson.override_find_program('override', p) +meson.override_find_program('override', p) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 dual override/overrides.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 dual override/overrides.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 dual override/overrides.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 dual override/overrides.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +print('Yo dawg, we put overrides in your overrides,') +print('so now you can override when you override.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 dual override/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 dual override/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 dual override/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 dual override/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/70 dual override/meson.build:5:6: ERROR: Tried to override executable \"override\" which has already been overridden." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 skip only subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 skip only subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 skip only subdir/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 skip only subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -# Check that skip_rest only exits subdir, not the whole script. -# Should create an error because main.cpp does not exists. -project('example exit', 'cpp') - -subdir('subdir') - -message('Good') -executable('main', 'main.cpp') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 skip only subdir/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 skip only subdir/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/70 skip only subdir/subdir/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/70 skip only subdir/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -subdir_done() - -error('Unreachable') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 invalid escape char/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 invalid escape char/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 invalid escape char/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 invalid escape char/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -# Make sure meson exits on invalid string -# The string below contains an invalid unicode code point - -'my name is what \uxyzo who are you' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 override used/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 override used/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 override used/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 override used/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +project('overridde an already found exe', 'c') + +old = find_program('something.py') +replacement = find_program('other.py') +meson.override_find_program('something.py', replacement) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 override used/other.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 override used/other.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 override used/other.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 override used/other.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('Doing something else.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 override used/something.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 override used/something.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 override used/something.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 override used/something.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('Doing something.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 override used/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 override used/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/71 override used/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/71 override used/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/71 override used/meson.build:5:6: ERROR: Tried to override finding of executable \"something.py\" which has already been found." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 dual override/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 dual override/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 dual override/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 dual override/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('yo dawg', 'c') - -p = find_program('overrides.py') -meson.override_find_program('override', p) -meson.override_find_program('override', p) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 dual override/overrides.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 dual override/overrides.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 dual override/overrides.py" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 dual override/overrides.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -#!/usr/bin/env python3 - -print('Yo dawg, we put overrides in your overrides,') -print('so now you can override when you override.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 run_command unclean exit/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 run_command unclean exit/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 run_command unclean exit/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 run_command unclean exit/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('run_command unclean exit', 'c') + +rcprog = find_program('./returncode.py') +run_command(rcprog, '1', check : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 run_command unclean exit/returncode.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 run_command unclean exit/returncode.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 run_command unclean exit/returncode.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 run_command unclean exit/returncode.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +import sys +exit(int(sys.argv[1])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 run_command unclean exit/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 run_command unclean exit/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/72 run_command unclean exit/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/72 run_command unclean exit/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": "test cases/failing/72 run_command unclean exit/meson\\.build:4:0: ERROR: Command \".*[\\\\/]test cases[\\\\/]failing[\\\\/]72 run_command unclean exit[\\\\/]\\.[\\\\/]returncode\\.py 1\" failed with status 1\\." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 int literal leading zero/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 int literal leading zero/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 int literal leading zero/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 int literal leading zero/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,5 @@ + +# This should fail. +# Decimal syntax is 123. +# Octal syntax is 0o123. +fail_0123 = 0123 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 int literal leading zero/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 int literal leading zero/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 int literal leading zero/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 int literal leading zero/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "comment": "this error message is not very informative", + "line": "test cases/failing/73 int literal leading zero/meson.build:5:13: ERROR: Expecting eof got number." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 override used/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 override used/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 override used/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 override used/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('overridde an already found exe', 'c') - -old = find_program('something.py') -replacement = find_program('other.py') -meson.override_find_program('something.py', replacement) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 override used/other.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 override used/other.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 override used/other.py" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 override used/other.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/usr/bin/env python3 - -print('Doing something else.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 override used/something.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 override used/something.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/73 override used/something.py" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/73 override used/something.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/usr/bin/env python3 - -print('Doing something.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/74 configuration immutable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/74 configuration immutable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/74 configuration immutable/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/74 configuration immutable/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,12 @@ +project('configuration_data is immutable') + +a = configuration_data() + +configure_file( + configuration : a, + input : 'input', + output : 'output', +) + +still_immutable = a +still_immutable.set('hello', 'world') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/74 configuration immutable/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/74 configuration immutable/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/74 configuration immutable/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/74 configuration immutable/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/74 configuration immutable/meson.build:12:16: ERROR: Can not set values on configuration object that has been used." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/74 run_command unclean exit/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/74 run_command unclean exit/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/74 run_command unclean exit/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/74 run_command unclean exit/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('run_command unclean exit', 'c') - -rcprog = find_program('./returncode.py') -run_command(rcprog, '1', check : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/74 run_command unclean exit/returncode.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/74 run_command unclean exit/returncode.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/74 run_command unclean exit/returncode.py" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/74 run_command unclean exit/returncode.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -#!/usr/bin/env python3 - -import sys -exit(int(sys.argv[1])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 int literal leading zero/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 int literal leading zero/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 int literal leading zero/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 int literal leading zero/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ - -# This should fail. -# Decimal syntax is 123. -# Octal syntax is 0o123. -fail_0123 = 0123 - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 link with shared module on osx/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 link with shared module on osx/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 link with shared module on osx/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 link with shared module on osx/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +project('link with shared module', 'c') + +if host_machine.system() != 'darwin' + error('MESON_SKIP_TEST test only fails on OSX') +endif + +m = shared_module('mymodule', 'module.c') +e = executable('prog', 'prog.c', link_with : m) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 link with shared module on osx/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 link with shared module on osx/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 link with shared module on osx/module.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 link with shared module on osx/module.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 1496; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 link with shared module on osx/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 link with shared module on osx/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 link with shared module on osx/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 link with shared module on osx/prog.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ + +int main(int argc, char **argv) { + return func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 link with shared module on osx/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 link with shared module on osx/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/75 link with shared module on osx/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/75 link with shared module on osx/test.json" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/75 link with shared module on osx/meson.build:8:0: ERROR: target prog links against shared module mymodule. This is not permitted on OSX" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/76 configuration immutable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/76 configuration immutable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/76 configuration immutable/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/76 configuration immutable/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -project('configuration_data is immutable') - -a = configuration_data() - -configure_file( - configuration : a, - input : 'input', - output : 'output', -) - -still_immutable = a -still_immutable.set('hello', 'world') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/76 non ascii in ascii encoded configure file/config9.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/76 non ascii in ascii encoded configure file/config9.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/76 non ascii in ascii encoded configure file/config9.h.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/76 non ascii in ascii encoded configure file/config9.h.in" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +#define MESSAGE "@var@" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/76 non ascii in ascii encoded configure file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/76 non ascii in ascii encoded configure file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/76 non ascii in ascii encoded configure file/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/76 non ascii in ascii encoded configure file/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,10 @@ +project('non acsii to ascii encoding', 'c') +# Writing a non ASCII character with a ASCII encoding should fail +conf9 = configuration_data() +conf9.set('var', 'д') +configure_file( + input : 'config9.h.in', + output : '@BASENAME@', + encoding : 'ascii', + configuration : conf9 +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/76 non ascii in ascii encoded configure file/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/76 non ascii in ascii encoded configure file/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/76 non ascii in ascii encoded configure file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/76 non ascii in ascii encoded configure file/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": "test cases/failing/76 non ascii in ascii encoded configure file/meson\\.build:5:0: ERROR: Could not write output file .*[\\\\/]config9\\.h: 'ascii' codec can't encode character '\\\\u0434' in position 17: ordinal not in range\\(128\\)" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 link with shared module on osx/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 link with shared module on osx/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 link with shared module on osx/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 link with shared module on osx/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('link with shared module', 'c') - -if host_machine.system() != 'darwin' - error('Test only fails on OSX') -endif - -m = shared_module('mymodule', 'module.c') -e = executable('prog', 'prog.c', link_with : m) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 link with shared module on osx/module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 link with shared module on osx/module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 link with shared module on osx/module.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 link with shared module on osx/module.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int func(void) { - return 1496; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 link with shared module on osx/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 link with shared module on osx/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 link with shared module on osx/prog.c" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 link with shared module on osx/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -int main(int argc, char **argv) { - return func(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 subproj dependency not-found and required/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 subproj dependency not-found and required/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 subproj dependency not-found and required/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 subproj dependency not-found and required/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('dep-test') +missing = dependency('', fallback: ['missing', 'missing_dep'], required: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 subproj dependency not-found and required/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 subproj dependency not-found and required/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/77 subproj dependency not-found and required/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/77 subproj dependency not-found and required/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/77 subproj dependency not-found and required/meson.build:2:0: ERROR: Neither a subproject directory nor a missing.wrap file was found." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/78 non ascii in ascii encoded configure file/config9.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/78 non ascii in ascii encoded configure file/config9.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/78 non ascii in ascii encoded configure file/config9.h.in" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/78 non ascii in ascii encoded configure file/config9.h.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#define MESSAGE "@var@" diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/78 non ascii in ascii encoded configure file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/78 non ascii in ascii encoded configure file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/78 non ascii in ascii encoded configure file/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/78 non ascii in ascii encoded configure file/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('non acsii to ascii encoding', 'c') -# Writing a non ASCII character with a ASCII encoding should fail -conf9 = configuration_data() -conf9.set('var', 'д') -configure_file( - input : 'config9.h.in', - output : '@BASENAME@', - encoding : 'ascii', - configuration : conf9 -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/78 unfound run/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/78 unfound run/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/78 unfound run/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/78 unfound run/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('unfound runtarget') + +exe = find_program('nonexisting_prog', required : false) +run_target('invoke_fail', command : [exe]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/78 unfound run/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/78 unfound run/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/78 unfound run/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/78 unfound run/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/78 unfound run/meson.build:4:0: ERROR: Tried to use non-existing executable 'nonexisting_prog'" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/79 framework dependency with version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/79 framework dependency with version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/79 framework dependency with version/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/79 framework dependency with version/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +project('framework dependency with version', 'c') + +if host_machine.system() != 'darwin' + error('MESON_SKIP_TEST test only applicable on darwin') +endif + +# do individual frameworks have a meaningful version to test? And multiple frameworks might be listed... +dep = dependency('appleframeworks', modules: 'foundation', version: '>0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/79 framework dependency with version/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/79 framework dependency with version/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/79 framework dependency with version/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/79 framework dependency with version/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/79 framework dependency with version/meson.build:8:0: ERROR: Unknown version of dependency 'appleframeworks', but need ['>0']." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/79 subproj dependency not-found and required/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/79 subproj dependency not-found and required/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/79 subproj dependency not-found and required/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/79 subproj dependency not-found and required/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('dep-test') -missing = dependency('', fallback: ['missing', 'missing_dep'], required: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/7 go to subproject/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/7 go to subproject/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/7 go to subproject/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/7 go to subproject/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/7 go to subproject/meson.build:3:0: ERROR: Must not go into subprojects dir with subdir(), use subproject() instead." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/80 override exe config/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/80 override exe config/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/80 override exe config/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/80 override exe config/foo.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/80 override exe config/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/80 override exe config/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/80 override exe config/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/80 override exe config/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,6 @@ +project('myexe', 'c') + +foo = executable('foo', 'foo.c') +meson.override_find_program('bar', foo) +bar = find_program('bar') +run_command(bar, check: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/80 override exe config/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/80 override exe config/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/80 override exe config/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/80 override exe config/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/80 override exe config/meson.build:6:0: ERROR: Program 'bar' was overridden with the compiled executable 'foo' and therefore cannot be used during configuration" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/80 unfound run/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/80 unfound run/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/80 unfound run/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/80 unfound run/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('unfound runtarget') - -exe = find_program('nonexisting_prog', required : false) -run_target('invoke_fail', command : [exe]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/81 framework dependency with version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/81 framework dependency with version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/81 framework dependency with version/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/81 framework dependency with version/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('framework dependency with version') -# do individual frameworks have a meaningful version to test? And multiple frameworks might be listed... -# otherwise we're not on OSX and this will definitely fail -dep = dependency('appleframeworks', modules: 'foundation', version: '>0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/81 gl dependency with version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/81 gl dependency with version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/81 gl dependency with version/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/81 gl dependency with version/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ +project('gl dependency with version', 'c') + +host_system = host_machine.system() +if host_system != 'windows' and host_system != 'darwin' + error('MESON_SKIP_TEST: test only fails on Windows and OSX') +endif + +# gl dependency found via system method doesn't have a meaningful version to check +dep = dependency('gl', method: 'system', version: '>0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/81 gl dependency with version/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/81 gl dependency with version/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/81 gl dependency with version/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/81 gl dependency with version/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/81 gl dependency with version/meson.build:9:0: ERROR: Unknown version of dependency 'gl', but need ['>0']." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/82 override exe config/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/82 override exe config/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/82 override exe config/foo.c" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/82 override exe config/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/82 override exe config/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/82 override exe config/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/82 override exe config/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/82 override exe config/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -project('myexe', 'c') - -foo = executable('foo', 'foo.c') -meson.override_find_program('bar', foo) -bar = find_program('bar') -run_command(bar) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/82 threads dependency with version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/82 threads dependency with version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/82 threads dependency with version/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/82 threads dependency with version/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('threads dependency with version', 'c') +# threads dependency doesn't have a meaningful version to check +dep = dependency('threads', version: '>0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/82 threads dependency with version/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/82 threads dependency with version/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/82 threads dependency with version/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/82 threads dependency with version/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/82 threads dependency with version/meson.build:3:0: ERROR: Unknown version of dependency 'threads', but need ['>0']." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/83 gl dependency with version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/83 gl dependency with version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/83 gl dependency with version/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/83 gl dependency with version/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('gl dependency with version', 'c') - -host_system = host_machine.system() -if host_system != 'windows' and host_system != 'darwin' - error('Test only fails on Windows and OSX') -endif - -# gl dependency found via system method doesn't have a meaningful version to check -dep = dependency('gl', method: 'system', version: '>0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/83 gtest dependency with version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/83 gtest dependency with version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/83 gtest dependency with version/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/83 gtest dependency with version/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +project('gtest dependency with version', ['c', 'cpp']) + +if not dependency('gtest', method: 'system', required: false).found() + error('MESON_SKIP_TEST test requires gtest') +endif + +# discovering gtest version is not yet implemented +dep = dependency('gtest', method: 'system', version: '>0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/83 gtest dependency with version/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/83 gtest dependency with version/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/83 gtest dependency with version/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/83 gtest dependency with version/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/83 gtest dependency with version/meson.build:8:0: ERROR: Dependency 'gtest' is required but not found." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/84 dub libray/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/84 dub libray/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/84 dub libray/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/84 dub libray/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,11 @@ +project('dub') + +if not add_languages('d', required: false) + error('MESON_SKIP_TEST test requires D compiler') +endif + +if not find_program('dub', required: false).found() + error('MESON_SKIP_TEST test requires dub') +endif + +dependency('dubtestproject', method: 'dub') # Not library (none) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/84 dub libray/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/84 dub libray/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/84 dub libray/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/84 dub libray/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/84 dub libray/meson.build:11:0: ERROR: Dependency \"dubtestproject\" not found" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/84 threads dependency with version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/84 threads dependency with version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/84 threads dependency with version/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/84 threads dependency with version/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('threads dependency with version', 'c') -# threads dependency doesn't have a meaningful version to check -dep = dependency('threads', version: '>0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/85 dub executable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/85 dub executable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/85 dub executable/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/85 dub executable/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,11 @@ +project('dub') + +if not add_languages('d', required: false) + error('MESON_SKIP_TEST test requires D compiler') +endif + +if not find_program('dub', required: false).found() + error('MESON_SKIP_TEST test requires dub') +endif + +dependency('dubtestproject:test1', method: 'dub') # Not library (executable) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/85 dub executable/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/85 dub executable/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/85 dub executable/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/85 dub executable/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/85 dub executable/meson.build:11:0: ERROR: Dependency \"dubtestproject:test1\" not found" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/85 gtest dependency with version/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/85 gtest dependency with version/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/85 gtest dependency with version/meson.build" 2019-04-17 08:08:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/85 gtest dependency with version/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('gtest dependency with version', ['c', 'cpp']) -# discovering gtest version is not yet implemented -dep = dependency('gtest', method: 'system', version: '>0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/86 dub compiler/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/86 dub compiler/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/86 dub compiler/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/86 dub compiler/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,17 @@ +project('dub') + +if not add_languages('d', required: false) + error('MESON_SKIP_TEST test requires D compiler') +endif + +if meson.get_compiler('d').get_id() == 'dmd' + if host_machine.system() == 'windows' or host_machine.system() == 'cygwin' + error('MESON_SKIP_TEST Windows test environment lacks multiple D compilers.') + endif +endif + +if not find_program('dub', required: false).found() + error('MESON_SKIP_TEST test requires dub') +endif + +dependency('dubtestproject:test2', method: 'dub') # Compiler mismatch diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/86 dub compiler/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/86 dub compiler/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/86 dub compiler/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/86 dub compiler/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,19 @@ +{ + "matrix": { + "options": { + "warning_level": [ + { + "val": "1", + "skip_on_env": [ + "SINGLE_DUB_COMPILER" + ] + } + ] + } + }, + "stdout": [ + { + "line": "test cases/failing/86 dub compiler/meson.build:17:0: ERROR: Dependency \"dubtestproject:test2\" not found" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/86 dub libray/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/86 dub libray/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/86 dub libray/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/86 dub libray/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('dub', 'd', meson_version: '0.48.0') - -dependency('dubtestproject', method: 'dub') # Not library (none) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/87 dub executable/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/87 dub executable/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/87 dub executable/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/87 dub executable/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('dub', 'd', meson_version: '0.48.0') - -dependency('dubtestproject:test1', method: 'dub') # Not library (executable) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/87 subproj not-found dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/87 subproj not-found dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/87 subproj not-found dep/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/87 subproj not-found dep/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('dep-test') +missing = dependency('', fallback: ['somesubproj', 'notfound_dep'], required: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/87 subproj not-found dep/subprojects/somesubproj/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/87 subproj not-found dep/subprojects/somesubproj/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/87 subproj not-found dep/subprojects/somesubproj/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/87 subproj not-found dep/subprojects/somesubproj/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('dep', 'c') + +notfound_dep = dependency('', required : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/87 subproj not-found dep/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/87 subproj not-found dep/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/87 subproj not-found dep/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/87 subproj not-found dep/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/87 subproj not-found dep/meson.build:2:0: ERROR: Dependency '(anonymous)' is required but not found." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/88 dub compiler/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/88 dub compiler/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/88 dub compiler/meson.build" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/88 dub compiler/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('dub', 'd', meson_version: '0.48.0') - -if meson.get_compiler('d').get_id() == 'dmd' - if host_machine.system() == 'windows' or host_machine.system() == 'cygwin' - error('MESON_SKIP_TEST Windows test environment lacks multiple D compilers.') - endif -endif - -dependency('dubtestproject:test2', method: 'dub') # Compiler mismatch diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/88 invalid configure file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/88 invalid configure file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/88 invalid configure file/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/88 invalid configure file/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ +project('invalid configura file') + +configure_file( + configuration : configuration_data(), + input : 'input', + output : 'output', + install_dir : '', + install : true, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/88 invalid configure file/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/88 invalid configure file/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/88 invalid configure file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/88 invalid configure file/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/88 invalid configure file/meson.build:3:0: ERROR: \"install_dir\" must be specified when \"install\" in a configure_file is true" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 kwarg dupe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 kwarg dupe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 kwarg dupe/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 kwarg dupe/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +project('dupe kwarg', 'c') + +dupedict = {'install': true} + +executable('prog', 'prog.c', install: true, + kwargs: dupedict) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 kwarg dupe/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 kwarg dupe/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 kwarg dupe/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 kwarg dupe/prog.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + printf("I don't get built. It makes me saaaaaad. :(\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 kwarg dupe/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 kwarg dupe/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 kwarg dupe/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 kwarg dupe/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/89 kwarg dupe/meson.build:5:0: ERROR: Entry \"install\" defined both as a keyword argument and in a \"kwarg\" entry." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 subproj not-found dep/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 subproj not-found dep/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 subproj not-found dep/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 subproj not-found dep/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('dep-test') -missing = dependency('', fallback: ['somesubproj', 'notfound_dep'], required: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 subproj not-found dep/subprojects/somesubproj/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 subproj not-found dep/subprojects/somesubproj/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/89 subproj not-found dep/subprojects/somesubproj/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/89 subproj not-found dep/subprojects/somesubproj/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('dep', 'c') - -notfound_dep = dependency('', required : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/8 recursive/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/8 recursive/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/8 recursive/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/8 recursive/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/8 recursive/subprojects/b/meson.build:3:0: ERROR: Recursive include of subprojects: a => b => a." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/90 invalid configure file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/90 invalid configure file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/90 invalid configure file/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/90 invalid configure file/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('invalid configura file') - -configure_file( - configuration : configuration_data(), - input : 'input', - output : 'output', - install_dir : '', - install : true, -) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/90 missing pch file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/90 missing pch file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/90 missing pch file/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/90 missing pch file/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('pch test', 'c') +exe = executable('prog', 'prog.c', +c_pch : ['pch/prog_pch.c', 'pch/prog.h']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/90 missing pch file/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/90 missing pch file/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/90 missing pch file/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/90 missing pch file/prog.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +int main(int argc, char **argv) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/90 missing pch file/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/90 missing pch file/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/90 missing pch file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/90 missing pch file/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "comment": "literal 'pch/prog.h' from meson.build appears in output, irrespective of os.path.sep", + "line": "test cases/failing/90 missing pch file/meson.build:2:0: ERROR: File pch/prog.h does not exist." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 kwarg dupe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 kwarg dupe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 kwarg dupe/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 kwarg dupe/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -project('dupe kwarg', 'c') - -dupedict = {'install': true} - -executable('prog', 'prog.c', install: true, - kwargs: dupedict) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 kwarg dupe/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 kwarg dupe/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 kwarg dupe/prog.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 kwarg dupe/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#include - -int main(int argc, char **argv) { - printf("I don't get built. It makes me saaaaaad. :(\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 pch source different folder/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 pch source different folder/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 pch source different folder/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 pch source different folder/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +project('pch', 'c') +# It is not allowed to have the PCH implementation in a different +# folder than the header. +exe = executable('prog', 'prog.c', + c_pch : ['include/pch.h', 'src/pch.c']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 pch source different folder/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 pch source different folder/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 pch source different folder/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 pch source different folder/prog.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +int main(void) {} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 pch source different folder/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 pch source different folder/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/91 pch source different folder/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/91 pch source different folder/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/91 pch source different folder/meson.build:4:0: ERROR: PCH files must be stored in the same folder." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/92 missing pch file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/92 missing pch file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/92 missing pch file/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/92 missing pch file/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('pch test', 'c') -exe = executable('prog', 'prog.c', -c_pch : ['pch/prog_pch.c', 'pch/prog.h']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/92 missing pch file/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/92 missing pch file/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/92 missing pch file/prog.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/92 missing pch file/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(int argc, char **argv) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/92 unknown config tool/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/92 unknown config tool/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/92 unknown config tool/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/92 unknown config tool/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('no-such-config-tool') +dependency('no-such-config-tool', method:'config-tool') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/92 unknown config tool/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/92 unknown config tool/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/92 unknown config tool/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/92 unknown config tool/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/92 unknown config tool/meson.build:2:0: ERROR: Dependency \"no-such-config-tool\" not found" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 custom target install data/Info.plist.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 custom target install data/Info.plist.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 custom target install data/Info.plist.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 custom target install data/Info.plist.cpp" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +Some data which gets processed before installation diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 custom target install data/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 custom target install data/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 custom target install data/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 custom target install data/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,11 @@ +project('custom target install data') + +preproc = find_program('preproc.py') + +t = custom_target('Info.plist', + command: [preproc, '@INPUT@', '@OUTPUT@'], + input: 'Info.plist.cpp', + output: 'Info.plist', +) + +install_data(t) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 custom target install data/preproc.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 custom target install data/preproc.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 custom target install data/preproc.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 custom target install data/preproc.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import sys + +if len(sys.argv) != 3: + print(sys.argv[0], '', '') + +inf = sys.argv[1] +outf = sys.argv[2] + +with open(outf, 'wb') as o: + with open(inf, 'rb') as i: + o.write(i.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 custom target install data/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 custom target install data/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 custom target install data/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 custom target install data/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/93 custom target install data/meson.build:11:0: ERROR: install_data argument 1 was of type \"CustomTarget\" but should have been one of: \"str\", \"File\"" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 pch source different folder/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 pch source different folder/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 pch source different folder/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 pch source different folder/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('pch', 'c') -# It is not allowed to have the PCH implementation in a different -# folder than the header. -exe = executable('prog', 'prog.c', - c_pch : ['include/pch.h', 'src/pch.c']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 pch source different folder/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 pch source different folder/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/93 pch source different folder/prog.c" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/93 pch source different folder/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(void) {} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/94 add dict non string key/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/94 add dict non string key/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/94 add dict non string key/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/94 add dict non string key/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ +project('add dictionary entry using non-string key') + +dict = {} + +# An integer variable to be used as a key +key = 1 + +# Add new entry using integer variable as key should fail +dict += {key : 'myValue'} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/94 add dict non string key/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/94 add dict non string key/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/94 add dict non string key/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/94 add dict non string key/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/94 add dict non string key/meson.build:9:0: ERROR: Key must be a string" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/94 vala without c/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/94 vala without c/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/94 vala without c/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/94 vala without c/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('vala without c') -add_languages('vala') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/95 add dict duplicate keys/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/95 add dict duplicate keys/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/95 add dict duplicate keys/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/95 add dict duplicate keys/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,9 @@ +project('add dictionary entries with duplicate keys') + +dict = {} + +# A variable to be used as a key +key = 'myKey' + +# Add two entries with duplicate keys should fail +dict += {key : 'myValue1', key : 'myValue2'} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/95 add dict duplicate keys/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/95 add dict duplicate keys/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/95 add dict duplicate keys/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/95 add dict duplicate keys/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/95 add dict duplicate keys/meson.build:9:0: ERROR: Duplicate dictionary key: myKey" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/95 unknown config tool/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/95 unknown config tool/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/95 unknown config tool/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/95 unknown config tool/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -project('no-such-config-tool') -dependency('no-such-config-tool', method:'config-tool') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 custom target install data/Info.plist.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 custom target install data/Info.plist.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 custom target install data/Info.plist.cpp" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 custom target install data/Info.plist.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Some data which gets processed before installation diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 custom target install data/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 custom target install data/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 custom target install data/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 custom target install data/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -project('custom target install data') - -preproc = find_program('preproc.py') - -t = custom_target('Info.plist', - command: [preproc, '@INPUT@', '@OUTPUT@'], - input: 'Info.plist.cpp', - output: 'Info.plist', -) - -install_data(t) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 custom target install data/preproc.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 custom target install data/preproc.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 custom target install data/preproc.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 custom target install data/preproc.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -if len(sys.argv) != 3: - print(sys.argv[0], '', '') - -inf = sys.argv[1] -outf = sys.argv[2] - -with open(outf, 'wb') as o: - with open(inf, 'rb') as i: - o.write(i.read()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 no host get_external_property/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 no host get_external_property/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 no host get_external_property/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 no host get_external_property/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('missing property') + +message(meson.get_external_property('nonexisting')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 no host get_external_property/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 no host get_external_property/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/96 no host get_external_property/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/96 no host get_external_property/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/96 no host get_external_property/meson.build:3:0: ERROR: Unknown property for host machine: nonexisting" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/97 add dict non string key/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/97 add dict non string key/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/97 add dict non string key/meson.build" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/97 add dict non string key/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('add dictionary entry using non-string key') - -dict = {} - -# An integer variable to be used as a key -key = 1 - -# Add new entry using integer variable as key should fail -dict += {key : 'myValue'} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/97 no native compiler/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/97 no native compiler/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/97 no native compiler/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/97 no native compiler/main.c" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/97 no native compiler/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/97 no native compiler/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/97 no native compiler/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/97 no native compiler/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,12 @@ +project('no native compiler') + +if not meson.is_cross_build() + error('MESON_SKIP_TEST test only applicable when cross building.') +endif + +if add_languages('c', required: false, native: true) + error('MESON_SKIP_TEST test only applicable when native compiler not available.') +endif + +add_languages('c') +executable('main', 'main.c', native: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/97 no native compiler/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/97 no native compiler/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/97 no native compiler/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/97 no native compiler/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/97 no native compiler/meson.build:12:0: ERROR: No host machine compiler for \"main.c\"" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/98 add dict duplicate keys/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/98 add dict duplicate keys/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/98 add dict duplicate keys/meson.build" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/98 add dict duplicate keys/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project('add dictionary entries with duplicate keys') - -dict = {} - -# A variable to be used as a key -key = 'myKey' - -# Add two entries with duplicate keys should fail -dict += {key : 'myValue1', key : 'myValue2'} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/98 subdir parse error/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/98 subdir parse error/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/98 subdir parse error/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/98 subdir parse error/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,2 @@ +project('subdir false plusassign', 'c') +subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/98 subdir parse error/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/98 subdir parse error/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/98 subdir parse error/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/98 subdir parse error/subdir/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +3 += 4 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/98 subdir parse error/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/98 subdir parse error/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/98 subdir parse error/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/98 subdir parse error/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/98 subdir parse error/subdir/meson.build:1:0: ERROR: Plusassignment target must be an id." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/99 invalid option file/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/99 invalid option file/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/99 invalid option file/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/99 invalid option file/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +project('invalid option file') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/99 invalid option file/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/99 invalid option file/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/99 invalid option file/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/99 invalid option file/meson_options.txt" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1 @@ +' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/99 invalid option file/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/99 invalid option file/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/99 invalid option file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/99 invalid option file/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/99 invalid option file/meson_options.txt:1:0: ERROR: lexer" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/9 missing extra file/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/9 missing extra file/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing/9 missing extra file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing/9 missing extra file/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/9 missing extra file/meson.build:3:0: ERROR: File missing.txt does not exist." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing build/3 pch disabled/c/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing build/3 pch disabled/c/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing build/3 pch disabled/c/prog.c" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing build/3 pch disabled/c/prog.c" 2021-11-02 19:58:07.000000000 +0000 @@ -7,4 +7,3 @@ int main(int argc, char **argv) { return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing build/5 failed pickled/false.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing build/5 failed pickled/false.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing build/5 failed pickled/false.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing build/5 failed pickled/false.py" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +import sys +sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing build/5 failed pickled/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing build/5 failed pickled/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing build/5 failed pickled/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing build/5 failed pickled/meson.build" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,7 @@ +project('failed pickled command') + +custom_target('failure', + command: [find_program('false.py'), '\n'], + output: 'output.txt', + build_by_default: true, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing test/5 tap tests/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing test/5 tap tests/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing test/5 tap tests/meson.build" 2020-01-07 21:10:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing test/5 tap tests/meson.build" 2021-10-23 16:51:24.000000000 +0000 @@ -1,6 +1,9 @@ project('test features', 'c') tester = executable('tester', 'tester.c') -test('nonzero return code', tester, args : [], protocol: 'tap') +test_with_status = executable('test-with-status', 'tester_with_status.c') +test('nonzero return code no tests', tester, args : [], protocol: 'tap') +test('nonzero return code with tests', test_with_status, protocol: 'tap') test('missing test', tester, args : ['1..1'], protocol: 'tap') test('incorrect skip', tester, args : ['1..1 # skip\nok 1'], protocol: 'tap') +test('partially skipped', tester, args : ['not ok 1\nok 2 # skip'], protocol: 'tap') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing test/5 tap tests/tester_with_status.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing test/5 tap tests/tester_with_status.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/failing test/5 tap tests/tester_with_status.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/failing test/5 tap tests/tester_with_status.c" 2021-04-01 21:13:39.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char **argv) { + puts("1..1"); + puts("not ok 1 - some test"); + return 2; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/10 find library/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/10 find library/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/10 find library/main.f90" 2019-02-07 09:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/10 find library/main.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,4 +1,4 @@ - +program main use iso_fortran_env, only: stderr=>error_unit use iso_c_binding, only: c_int, c_char, c_null_char, c_ptr use gzip, only: gzopen, gzwrite, gzclose diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/11 compiles links runs/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/11 compiles links runs/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/11 compiles links runs/meson.build" 2020-01-07 21:13:04.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/11 compiles links runs/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -15,6 +15,3 @@ if fc.run(code).returncode() != 123 error('Fortran 2008 code failed to run') endif - - - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/12 submodule/child.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/12 submodule/child.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/12 submodule/child.f90" 2019-08-25 19:17:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/12 submodule/child.f90" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,4 @@ -submodule (parent) parent +submodule (parent) child contains @@ -10,5 +10,4 @@ print *, 'Good!' end procedure good -end submodule parent - +end submodule child diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/12 submodule/parent.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/12 submodule/parent.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/12 submodule/parent.f90" 2019-08-25 19:17:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/12 submodule/parent.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -13,6 +13,7 @@ end module parent +program main use parent diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/13 coarray/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/13 coarray/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/13 coarray/main.f90" 2019-02-28 20:43:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/13 coarray/main.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main implicit none if (this_image() == 1) print *, 'number of Fortran coarray images:', num_images() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/14 fortran links c/f_call_c.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/14 fortran links c/f_call_c.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/14 fortran links c/f_call_c.f90" 2019-05-05 19:11:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/14 fortran links c/f_call_c.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main implicit none interface diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/include_hierarchy.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/include_hierarchy.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/include_hierarchy.f90" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/include_hierarchy.f90" 2021-04-01 21:12:21.000000000 +0000 @@ -1,3 +1,4 @@ +program test_include_hier implicit none diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/include_syntax.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/include_syntax.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/include_syntax.f90" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/include_syntax.f90" 2021-04-01 21:12:21.000000000 +0000 @@ -1,3 +1,5 @@ +program test_include_syntax + implicit none integer :: x, y @@ -20,4 +22,4 @@ print *, 'OK: Fortran include tests: x=',x -end program \ No newline at end of file +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/include_tests.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/include_tests.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/include_tests.f90" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/include_tests.f90" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -implicit none - -integer :: x, y - -x = 1 -y = 0 - -! include "timestwo.f90" - -! double quote and inline comment check -include "timestwo.f90" ! inline comment check -if (x/=2) error stop 'failed on first include' - -! leading space and single quote check - include 'timestwo.f90' -if (x/=4) error stop 'failed on second include' - -! Most Fortran compilers can't handle the non-standard #include, -! including (ha!) Flang, Gfortran, Ifort and PGI. -! #include "timestwo.f90" - -print *, 'OK: Fortran include tests: x=',x - -end program \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/meson.build" 2020-01-07 21:13:07.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -1,8 +1,19 @@ project('Inclusive', 'fortran', meson_version: '>= 0.51.1') +cm = import('cmake') + hier_exe = executable('include_hierarchy', 'include_hierarchy.f90') test('Fortran include file hierarchy', hier_exe) syntax_exe = executable('include_syntax', 'include_syntax.f90') -test('Fortran include file syntax', syntax_exe) \ No newline at end of file +test('Fortran include file syntax', syntax_exe) + +# older CI runs into problems with too-old Ninja and CMake and Fortran +ninja_version = run_command('ninja', '--version', check: true).stdout().strip() +cmake_version = run_command('cmake', '--version', check: true).stdout().split()[2] +if ninja_version.version_compare('>=1.10.0') and cmake_version.version_compare('>=3.17.0') + cm.subproject('cmake_inc') +else + message('SKIP: CMake Fortran subproject with include. Ninja >= 1.10 and CMake >= 3.17 needed. You have Ninja ' + ninja_version + ' and CMake ' + cmake_version) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/subprojects/cmake_inc/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/subprojects/cmake_inc/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/subprojects/cmake_inc/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/subprojects/cmake_inc/CMakeLists.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.17) +project(cmake_inc LANGUAGES Fortran) + +add_executable(main main.f90) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/subprojects/cmake_inc/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/subprojects/cmake_inc/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/subprojects/cmake_inc/main.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/subprojects/cmake_inc/main.f90" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,9 @@ +program test_subproject_inc + +implicit none + +include 'thousand.f90' + +if (thousand /= 1000) error stop 'did not include properly' + +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/subprojects/cmake_inc/thousand.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/subprojects/cmake_inc/thousand.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/15 include/subprojects/cmake_inc/thousand.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/15 include/subprojects/cmake_inc/thousand.f90" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1 @@ +integer, parameter :: thousand = 1000 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/16 openmp/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/16 openmp/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/16 openmp/main.f90" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/16 openmp/main.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main use, intrinsic :: iso_fortran_env, only: stderr=>error_unit use omp_lib, only: omp_get_max_threads implicit none diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/18 first_arg/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/18 first_arg/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/18 first_arg/main.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/18 first_arg/main.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -0,0 +1,3 @@ +program main +i = 3 +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/18 first_arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/18 first_arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/18 first_arg/meson.build" 2020-01-07 21:13:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/18 first_arg/meson.build" 2021-10-23 16:53:54.000000000 +0000 @@ -24,3 +24,23 @@ assert(l1.length() == 1, 'First supported returned wrong result.') assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') assert(l2.length() == 0, 'First supported did not return empty array.') + +# --- test with an actual program, here for implicit none + +in0 = fc.first_supported_argument('-fimplicit-none', '-Mdclchk', '/warn:declarations', '-warn').get(0, '') +impnone = { +'intel-cl': '/warn:declarations', +'intel': '-warn', +'gcc': '-fimplicit-none', +'pgi': '-Mdclchk', +} + +arg = impnone.get(fc.get_id(), '') +if arg != '' + assert(in0 == arg, 'implicit none argument ' + arg + ' not matching ' + in0) +endif + +in1 = fc.get_supported_arguments('-fimplicit-none', '/warn:declarations', '/warn:errors', '-Mdclchk') +if in1.length() > 0 + assert(not fc.compiles(files('main.f90'), args: in1, name:'will fail implicit none'), 'implicit none should have failed') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/legacy.f" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/legacy.f" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/legacy.f" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/legacy.f" 2021-10-23 16:36:11.000000000 +0000 @@ -1,7 +1,8 @@ + program main ! non-integer loop indices are deleted in Fortran 95 standard real a do 10 a=0,0.5,0.1 10 continue - end program \ No newline at end of file + end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/std2003.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/std2003.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/std2003.f90" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/std2003.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main use, intrinsic :: iso_fortran_env, only : error_unit implicit none @@ -33,4 +34,4 @@ end subroutine timestwo -end program \ No newline at end of file +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/std2008.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/std2008.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/std2008.f90" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/std2008.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main use, intrinsic :: iso_fortran_env, only : error_unit, sp=>real32, dp=>real64 implicit none @@ -29,4 +30,4 @@ end subroutine timestwo -end program \ No newline at end of file +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/std2018.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/std2018.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/std2018.f90" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/std2018.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main use, intrinsic :: iso_fortran_env, only : error_unit, sp=>real32, dp=>real64 implicit none @@ -31,4 +32,4 @@ end subroutine timestwo -end program \ No newline at end of file +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/std95.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/std95.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/19 fortran_std/std95.f90" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/19 fortran_std/std95.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main implicit none integer :: i, j @@ -10,4 +11,4 @@ A(i,j) = 1 end forall -end program \ No newline at end of file +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/1 basic/simple.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/1 basic/simple.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/1 basic/simple.f90" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/1 basic/simple.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,2 +1,3 @@ +program main print *, "Fortran compilation is working." end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/20 buildtype/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/20 buildtype/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/20 buildtype/main.f90" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/20 buildtype/main.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1 +1,2 @@ +program main end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/main.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/main.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -0,0 +1,5 @@ +program main +use main_lib +implicit none +call main_hello() +end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/main_lib.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/main_lib.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/main_lib.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/main_lib.f90" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,16 @@ +module main_lib + + use static_hello + implicit none + + private + public :: main_hello + + contains + + subroutine main_hello + call static_say_hello() + print *, "Main hello routine finished." + end subroutine main_hello + +end module main_lib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/meson.build" 2021-10-23 16:54:02.000000000 +0000 @@ -0,0 +1,20 @@ +# Based on 'fortran/5 static', but: +# - Uses a subproject dependency +# - Is an install:true static library to trigger certain codepath (promotion to link_whole) +# - Does fortran code 'generation' with configure_file +# - Uses .F90 ext (capital F typically denotes a dependence on preprocessor treatment, which however is not used) +project('try-static-subproject-dependency', 'fortran') + +static_dep = dependency('static_hello', fallback: ['static_hello', 'static_hello_dep']) + +mainsrc = 'main_lib.f90' +mainsrc = configure_file( + copy: true, + input: mainsrc, + output: 'main_lib_output.F90' +) +main_lib = library('mainstatic', mainsrc, dependencies: static_dep, install: true) +main_dep = declare_dependency(link_with: main_lib) + +main_exe = executable('main_exe', 'main.f90', dependencies: main_dep) +test('static_subproject_test', main_exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/subprojects/static_hello/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/subprojects/static_hello/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/subprojects/static_hello/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/subprojects/static_hello/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,12 @@ +project('static-hello', 'fortran') + +# staticlibsource = 'static_hello.f90' +staticlibsource = configure_file( + copy: true, + input: 'static_hello.f90', + output: 'static_hello_output.F90' +) + +static_hello_lib = static_library('static_hello', staticlibsource, install: false) + +static_hello_dep = declare_dependency(link_with: static_hello_lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,17 @@ +module static_hello +implicit none + +private +public :: static_say_hello + +interface static_say_hello + module procedure say_hello +end interface static_say_hello + +contains + +subroutine say_hello + print *, "Static library called." +end subroutine say_hello + +end module static_hello diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/21 install static/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/21 install static/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "installed": [ + {"file": "usr/lib/libmainstatic.a", "type": "file"} + ], + "matrix": { + "options": { + "default_library": [ { "val": "static" } ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/2 modules/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/2 modules/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/2 modules/meson.build" 2020-01-07 21:12:54.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/2 modules/meson.build" 2021-10-23 16:53:39.000000000 +0000 @@ -3,6 +3,7 @@ commented = library('commented', 'comment_mod.f90') -e = executable('modprog', 'mymod.f90', 'prog.f90', +# Have one file with an upper case file extension. +e = executable('modprog', 'mymod.F90', 'prog.f90', link_with: commented) test('moduletest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/2 modules/mymod.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/2 modules/mymod.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/2 modules/mymod.f90" 2019-08-25 19:17:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/2 modules/mymod.f90" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -! module circle to be sure module regex doesn't allow commented modules - -module circle -implicit none - -real, parameter :: pi = 4.*atan(1.) -real :: radius -end module circle diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/2 modules/mymod.F90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/2 modules/mymod.F90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/2 modules/mymod.F90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/2 modules/mymod.F90" 2021-04-10 09:22:14.000000000 +0000 @@ -0,0 +1,8 @@ +! module circle to be sure module regex doesn't allow commented modules + +module circle +implicit none + +real, parameter :: pi = 4.*atan(1.) +real :: radius +end module circle diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/2 modules/prog.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/2 modules/prog.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/2 modules/prog.f90" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/2 modules/prog.f90" 2021-11-02 19:58:07.000000000 +0000 @@ -1,3 +1,4 @@ +program main use circle, only: pi use line, only: length implicit none @@ -8,4 +9,3 @@ print *, length end program - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/5 static/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/5 static/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/5 static/main.f90" 2019-02-07 09:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/5 static/main.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,4 +1,4 @@ - +program main use static_hello implicit none diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/6 dynamic/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/6 dynamic/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/6 dynamic/main.f90" 2019-02-07 09:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/6 dynamic/main.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main use dynamic, only: hello implicit none diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/meson.build" 2020-01-07 21:12:58.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,12 +1,29 @@ # Tests whether fortran sources files created during configuration are properly # scanned for dependency information -project('generated', 'fortran') +project('generated', 'fortran', + default_options : ['default_library=static']) conf_data = configuration_data() conf_data.set('ONE', 1) conf_data.set('TWO', 2) +mod3_f = custom_target( + 'mod3.f', + input : 'mod3.f90', + output : 'mod3.f90', + # We need a platform agnostic way to do a copy a file, using a custom_target + # and we need to use the @OUTDIR@, not @OUTPUT@ in order to exercise + # https://github.com/mesonbuild/meson/issues/9258 + command : [ + find_program('python', 'python3'), '-c', + 'import sys, shutil; shutil.copy(sys.argv[1], sys.argv[2])', + '@INPUT@', '@OUTDIR@', + ], +) + +three = library('mod3', mod3_f) + templates_basenames = ['mod2', 'mod1'] generated_sources = [] foreach template_basename : templates_basenames @@ -18,5 +35,5 @@ endforeach sources = ['prog.f90'] + generated_sources -exe = executable('generated', sources) +exe = executable('generated', sources, link_with: three) test('generated', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/mod1.fpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/mod1.fpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/mod1.fpp" 2017-05-17 21:09:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/mod1.fpp" 2020-08-15 16:27:05.000000000 +0000 @@ -1,6 +1,6 @@ module mod1 - implicit none +implicit none - integer, parameter :: modval1 = @ONE@ +integer, parameter :: modval1 = @ONE@ end module mod1 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/mod2.fpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/mod2.fpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/mod2.fpp" 2017-05-17 21:09:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/mod2.fpp" 2020-08-15 16:27:05.000000000 +0000 @@ -1,7 +1,7 @@ module mod2 - use mod1 - implicit none +use mod1, only : modval1 +implicit none - integer, parameter :: modval2 = @TWO@ +integer, parameter :: modval2 = @TWO@ end module mod2 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/mod3.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/mod3.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/mod3.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/mod3.f90" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +module mod3 +implicit none + +integer, parameter :: modval3 = 3 + +end module mod3 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/prog.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/prog.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/7 generated/prog.f90" 2019-02-28 20:43:18.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/7 generated/prog.f90" 2020-08-15 16:27:05.000000000 +0000 @@ -1,7 +1,8 @@ -program prog -use mod2 +program generated +use mod2, only : modval1, modval2 +use mod3, only : modval3 implicit none -if (modval1 + modval2 /= 3) stop 1 +if (modval1 + modval2 + modval3 /= 6) error stop -end program prog +end program generated diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/8 module names/test.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/8 module names/test.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/8 module names/test.f90" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/8 module names/test.f90" 2021-10-23 16:36:11.000000000 +0000 @@ -1,3 +1,4 @@ +program main use mymod1 use MyMod2 ! test inline comment diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/9 cpp/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/9 cpp/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/9 cpp/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/9 cpp/main.c" 2021-04-01 21:13:39.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +double fortran(void); + +int main(void) { + printf("FORTRAN gave us this number: %lf.\n", fortran()); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/9 cpp/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/9 cpp/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fortran/9 cpp/meson.build" 2020-01-07 21:13:04.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fortran/9 cpp/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,12 +1,8 @@ -project('C++ and FORTRAN', 'cpp', 'fortran') +project('C, C++ and Fortran', 'c', 'cpp', 'fortran') cpp = meson.get_compiler('cpp') fc = meson.get_compiler('fortran') -if cpp.get_id() == 'clang' - error('MESON_SKIP_TEST Clang C++ does not find -lgfortran for some reason.') -endif - if build_machine.system() == 'windows' and cpp.get_id() != fc.get_id() error('MESON_SKIP_TEST mixing gfortran with non-GNU C++ does not work.') endif @@ -17,9 +13,17 @@ endif e = executable( + 'cfort', + ['main.c', 'fortran.f'], + dependencies : link_with, +) + +test('C and Fortran', e) + +e2 = executable( 'cppfort', ['main.cpp', 'fortran.f'], dependencies : link_with, ) -test('C++ FORTRAN', e) +test('C++ and Fortran', e2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fpga/1 simple/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fpga/1 simple/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fpga/1 simple/meson.build" 2020-01-07 21:13:24.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fpga/1 simple/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -6,4 +6,3 @@ 'spin.v', constraint_file : 'spin.pcf', ) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fpga/1 simple/spin.v" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fpga/1 simple/spin.v" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/fpga/1 simple/spin.v" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/fpga/1 simple/spin.v" 2021-11-02 19:58:07.000000000 +0000 @@ -1,29 +1,29 @@ module top(input clk, output LED1, output LED2, output LED3, output LED4, output LED5); - + reg ready = 0; reg [23:0] divider; reg [3:0] spin; - + always @(posedge clk) begin - if (ready) + if (ready) begin - if (divider == 6000000) + if (divider == 6000000) begin divider <= 0; spin <= {spin[2], spin[3], spin[0], spin[1]}; end - else + else divider <= divider + 1; end - else + else begin ready <= 1; spin <= 4'b1010; divider <= 0; end end - + assign LED1 = spin[0]; assign LED2 = spin[1]; assign LED3 = spin[2]; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml" 2021-06-07 17:35:22.000000000 +0000 @@ -35,7 +35,7 @@ - + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-sections.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-sections.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-sections.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-sections.txt" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,15 @@ +
+foo +FooObj +FooObj +FooObjClass +foo_do_something +
+ +
+version +version +FOO_MAJOR_VERSION +FOO_MINOR_VERSION +FOO_MICRO_VERSION +
diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar.types" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar.types" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar.types" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar.types" 2021-06-07 17:35:22.000000000 +0000 @@ -0,0 +1,4 @@ +% This include is useless it's a regression test for https://github.com/mesonbuild/meson/issues/8744 +#include + +foo_obj_get_type diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build" 2022-01-17 10:50:38.000000000 +0000 @@ -1,5 +1,15 @@ +png = configure_file(input: 'baz.png.in', + output: 'baz.png', + copy: true) + gnome.gtkdoc('foobar', - src_dir : inc, + src_dir : [inc, '.'], main_sgml : 'foobar-docs.sgml', content_files : [docbook, version_xml], - install : true) + 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, + check: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build" 2022-01-17 10:50:38.000000000 +0000 @@ -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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/foo.c" 2021-06-07 17:35:22.000000000 +0000 @@ -0,0 +1,30 @@ +#include + + +struct _FooObj { + GObject parent; + int dummy; +}; + +G_DEFINE_TYPE(FooObj, foo_obj, G_TYPE_OBJECT) + +static void foo_obj_init (FooObj *self) +{ +} + +static void foo_obj_class_init (FooObjClass *klass) +{ +} + +/** + * foo_do_something: + * @self: self + * + * Useless function. + * + * Returns: 0. + */ +int foo_do_something(FooObj *self) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/include/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/include/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/include/foo.h" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/include/foo.h" 2021-06-07 17:35:22.000000000 +0000 @@ -1,5 +1,7 @@ #pragma once +#include + /** * FooIndecision: * @FOO_MAYBE: Something maybe @@ -13,3 +15,19 @@ FOO_POSSIBLY, } FooIndecision; +/** + * FooObjClass: + * + * The class + */ + +/** + * FooObj: + * + * The instance + */ + +#define FOO_TYPE_OBJ foo_obj_get_type() +G_DECLARE_FINAL_TYPE(FooObj, foo_obj, FOO, OBJ, GObject) + +int foo_do_something(FooObj *self); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/installed_files.txt" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -usr/include/foo-version.h -usr/share/gtk-doc/html/foobar/BAR.html -usr/share/gtk-doc/html/foobar/foobar.devhelp2 -usr/share/gtk-doc/html/foobar/foobar.html -usr/share/gtk-doc/html/foobar/foobar-foo.html -usr/share/gtk-doc/html/foobar/foobar-foo-version.html -usr/share/gtk-doc/html/foobar/home.png -usr/share/gtk-doc/html/foobar/index.html -usr/share/gtk-doc/html/foobar/left.png -usr/share/gtk-doc/html/foobar/left-insensitive.png -usr/share/gtk-doc/html/foobar/right.png -usr/share/gtk-doc/html/foobar/right-insensitive.png -usr/share/gtk-doc/html/foobar/style.css -usr/share/gtk-doc/html/foobar/up.png -usr/share/gtk-doc/html/foobar/up-insensitive.png -usr/share/gtk-doc/html/foobar2/BAR.html -usr/share/gtk-doc/html/foobar2/foobar2.devhelp2 -usr/share/gtk-doc/html/foobar2/foobar.html -usr/share/gtk-doc/html/foobar2/foobar2-foo.html -usr/share/gtk-doc/html/foobar2/foobar2-foo-version.html -usr/share/gtk-doc/html/foobar2/home.png -usr/share/gtk-doc/html/foobar2/index.html -usr/share/gtk-doc/html/foobar2/left.png -usr/share/gtk-doc/html/foobar2/left-insensitive.png -usr/share/gtk-doc/html/foobar2/right.png -usr/share/gtk-doc/html/foobar2/right-insensitive.png -usr/share/gtk-doc/html/foobar2/style.css -usr/share/gtk-doc/html/foobar2/up.png -usr/share/gtk-doc/html/foobar2/up-insensitive.png -usr/share/gtk-doc/html/foobar-3.0/BAR.html -usr/share/gtk-doc/html/foobar-3.0/foobar-3.0.devhelp2 -usr/share/gtk-doc/html/foobar-3.0/foobar.html -usr/share/gtk-doc/html/foobar-3.0/foobar-foo.html -usr/share/gtk-doc/html/foobar-3.0/foobar-foo-version.html -usr/share/gtk-doc/html/foobar-3.0/home.png -usr/share/gtk-doc/html/foobar-3.0/index.html -usr/share/gtk-doc/html/foobar-3.0/left.png -usr/share/gtk-doc/html/foobar-3.0/left-insensitive.png -usr/share/gtk-doc/html/foobar-3.0/right.png -usr/share/gtk-doc/html/foobar-3.0/right-insensitive.png -usr/share/gtk-doc/html/foobar-3.0/style.css -usr/share/gtk-doc/html/foobar-3.0/up.png -usr/share/gtk-doc/html/foobar-3.0/up-insensitive.png -usr/share/gtk-doc/html/foobar3/BAR.html -usr/share/gtk-doc/html/foobar3/foobar2-3.0.devhelp2 -usr/share/gtk-doc/html/foobar3/foobar.html -usr/share/gtk-doc/html/foobar3/foobar2-foo.html -usr/share/gtk-doc/html/foobar3/foobar2-foo-version.html -usr/share/gtk-doc/html/foobar3/home.png -usr/share/gtk-doc/html/foobar3/index.html -usr/share/gtk-doc/html/foobar3/left.png -usr/share/gtk-doc/html/foobar3/left-insensitive.png -usr/share/gtk-doc/html/foobar3/right.png -usr/share/gtk-doc/html/foobar3/right-insensitive.png -usr/share/gtk-doc/html/foobar3/style.css -usr/share/gtk-doc/html/foobar3/up.png -usr/share/gtk-doc/html/foobar3/up-insensitive.png diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/meson.build" 2020-01-07 21:14:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -15,7 +15,7 @@ # disable this test unless a bug fix for spaces in pathnames is present # https://bugzilla.gnome.org/show_bug.cgi?id=753145 -result = run_command(gtkdoc, ['--version']) +result = run_command(gtkdoc, ['--version'], check: true) gtkdoc_ver = result.stdout().strip() if gtkdoc_ver == '' gtkdoc_ver = result.stderr().strip() @@ -24,4 +24,16 @@ error('MESON_SKIP_TEST gtk-doc test requires gtkdoc >= 1.26.') endif +gobject = dependency('gobject-2.0') + +libfoo = shared_library('foo', 'foo.c', + include_directories: inc, + dependencies: gobject, +) + +foo_dep = declare_dependency( + link_with: libfoo, + include_directories: inc, +) + subdir('doc') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/10 gtk-doc/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/10 gtk-doc/test.json" 2022-01-17 10:50:38.000000000 +0000 @@ -0,0 +1,64 @@ +{ + "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"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/foo-version.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/home.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/index.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/left.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/left-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/right.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/right-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/style.css"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/up.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar/up-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/BAR.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/foobar2.devhelp2"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/foobar.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/foobar2-foo.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/foobar2-foo-version.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/home.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/index.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/left.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/left-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/right.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/right-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/style.css"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/up.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar2/up-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/BAR.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/foobar-3.0.devhelp2"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/foobar.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/foobar-foo.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/foobar-foo-version.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/home.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/index.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/left.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/left-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/right.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/right-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/style.css"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/up.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar-3.0/up-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/BAR.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/foobar2-3.0.devhelp2"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/foobar.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/foobar2-foo.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/foobar2-foo-version.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/home.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/index.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/left.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/left-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/right.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/right-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/style.css"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/up.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/up-insensitive.png"} + ], + "skip_on_jobname": ["azure", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/11 gir subproject/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/11 gir subproject/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/11 gir subproject/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/11 gir subproject/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -usr/lib/girepository-1.0/Meson-1.0.typelib -usr/lib/girepository-1.0/MesonSub-1.0.typelib -usr/share/gir-1.0/Meson-1.0.gir -usr/share/gir-1.0/MesonSub-1.0.gir -usr/lib/?libgirsubproject.so -?cygwin:usr/lib/libgirlib.dll.a -usr/lib/?libgirlib.so -?cygwin:usr/lib/libgirsubproject.dll.a diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/11 gir subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/11 gir subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/11 gir subproject/meson.build" 2020-01-07 21:14:44.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/11 gir subproject/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -7,7 +7,7 @@ python3 = import('python3') py3 = python3.find_python() -if run_command(py3, '-c', 'import gi;').returncode() != 0 +if run_command(py3, '-c', 'import gi;', check: false).returncode() != 0 error('MESON_SKIP_TEST python3-gi not found') endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/11 gir subproject/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/11 gir subproject/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/11 gir subproject/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/11 gir subproject/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,13 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/girepository-1.0/Meson-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonSub-1.0.typelib"}, + {"type": "file", "file": "usr/share/gir-1.0/Meson-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonSub-1.0.gir"}, + {"type": "expr", "file": "usr/lib/?libgirsubproject.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirlib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libgirlib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirsubproject.dll.a"} + ], + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/gir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/gir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/gir/meson.build" 2016-09-27 19:54:51.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/gir/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -22,7 +22,8 @@ symbol_prefix : 'meson_sub_', identifier_prefix : 'MesonSub', includes : ['GObject-2.0', meson_gir], - install : true + install : true, + install_dir_gir: false, ) message('TEST: ' + girsubproject.outdir()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -usr/lib/girepository-1.0/Meson-1.0.typelib -usr/lib/girepository-1.0/MesonSub-1.0.typelib -usr/lib/?libgirlib.so -?cygwin:usr/lib/libgirlib.dll.a -usr/lib/?libgirsubproject.so -?cygwin:usr/lib/libgirsubproject.dll.a -usr/share/gir-1.0/Meson-1.0.gir -usr/share/gir-1.0/MesonSub-1.0.gir diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/meson.build" 2020-01-07 21:14:44.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -1,4 +1,4 @@ -project('multiple-gobject-introspection', 'c') +project('multiple-gobject-introspection', 'c', meson_version: '>=0.50.0') gir = find_program('g-ir-scanner', required: false) if not gir.found() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/mesongir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/mesongir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/mesongir/meson.build" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/mesongir/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -24,7 +24,8 @@ identifier_prefix : 'Meson', includes : ['GObject-2.0'], export_packages : 'meson', - install : true + install : true, + install_gir: false, ) meson_gir = girtarget[0] meson_typelib = girtarget[1] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/12 multiple gir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/12 multiple gir/test.json" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,17 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/girepository-1.0/Meson-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonSub-1.0.typelib"}, + {"type": "expr", "file": "usr/lib/?libgirlib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirlib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libgirsubproject.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirsubproject.dll.a"} + ], + "skip_on_jobname": ["azure", "macos", "msys2"], + "stdout": [ + { + "comment": "This will either match in the future-deprecated notice summary, or match the warning summary", + "line": " * 0.61.0: {'\"gnome.generate_gir\" keyword argument \"install_dir_gir\" value \"False\"'}" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/help/C/index2.page" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/help/C/index2.page" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/help/C/index2.page" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/help/C/index2.page" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ + + + Hello! + + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/help/C/index3.page" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/help/C/index3.page" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/help/C/index3.page" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/help/C/index3.page" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,8 @@ + + + Hello! + + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/help/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/help/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/help/meson.build" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/help/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -8,14 +8,14 @@ ) 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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/installed_files.txt" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -usr/share/help/C/meson/index.page -usr/share/help/C/meson/media/test.txt -usr/share/help/es/meson/index.page -usr/share/help/es/meson/media/test.txt -usr/share/help/de/meson/index.page -usr/share/help/de/meson/media/test.txt -usr/share/help/C/meson-symlink/index.page -usr/share/help/C/meson-symlink/media/test.txt -usr/share/help/es/meson-symlink/media/test.txt -usr/share/help/es/meson-symlink/index.page -usr/share/help/de/meson-symlink/index.page -usr/share/help/de/meson-symlink/media/test.txt -usr/share/help/C/meson-linguas/index.page -usr/share/help/C/meson-linguas/media/test.txt -usr/share/help/es/meson-linguas/media/test.txt -usr/share/help/es/meson-linguas/index.page -usr/share/help/de/meson-linguas/index.page -usr/share/help/de/meson-linguas/media/test.txt diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/13 yelp/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/13 yelp/test.json" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,23 @@ +{ + "installed": [ + {"type": "file", "file": "usr/share/help/C/meson/index.page"}, + {"type": "file", "file": "usr/share/help/C/meson/media/test.txt"}, + {"type": "file", "file": "usr/share/help/es/meson/index.page"}, + {"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/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/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/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/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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/14 doxygen/doc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/14 doxygen/doc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/14 doxygen/doc/meson.build" 2017-03-05 16:38:07.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/14 doxygen/doc/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -14,4 +14,3 @@ command: [doxygen, doxyfile], install: true, install_dir: datadir) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/14 doxygen/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/14 doxygen/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/14 doxygen/installed_files.txt" 2017-05-10 21:18:30.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/14 doxygen/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -usr/share/doc/spede/html/annotated.html -usr/share/doc/spede/html/bc_s.png -usr/share/doc/spede/html/bdwn.png -usr/share/doc/spede/html/classComedy_1_1Comedian.html -usr/share/doc/spede/html/classComedy_1_1Comedian.png -usr/share/doc/spede/html/classComedy_1_1Comedian-members.html -usr/share/doc/spede/html/classComedy_1_1Spede.html -usr/share/doc/spede/html/classComedy_1_1Spede.png -usr/share/doc/spede/html/classComedy_1_1Spede-members.html -usr/share/doc/spede/html/classes.html -usr/share/doc/spede/html/closed.png -usr/share/doc/spede/html/comedian_8h_source.html -usr/share/doc/spede/html/dir_7bdce917e28dfbd493cadd1d2e5c7d80.html -usr/share/doc/spede/html/dir_44a4667d36a4476878de085754f6d2b9.html -usr/share/doc/spede/html/dir_68b523c5b3a2dcea45d5ce70397fb722.html -usr/share/doc/spede/html/dir_a7e6472d2301212032fd74682f8217f3.html -usr/share/doc/spede/html/dir_ee191f21c02d247cc959e80c1a3acadf.html -usr/share/doc/spede/html/doc.png -usr/share/doc/spede/html/doxygen.css -usr/share/doc/spede/html/doxygen.png -usr/share/doc/spede/html/dynsections.js -usr/share/doc/spede/html/files.html -usr/share/doc/spede/html/folderclosed.png -usr/share/doc/spede/html/folderopen.png -usr/share/doc/spede/html/functions.html -usr/share/doc/spede/html/functions_func.html -usr/share/doc/spede/html/hierarchy.html -usr/share/doc/spede/html/index.html -usr/share/doc/spede/html/jquery.js -usr/share/doc/spede/html/menu.js -usr/share/doc/spede/html/menudata.js -usr/share/doc/spede/html/namespaceComedy.html -usr/share/doc/spede/html/namespacemembers.html -usr/share/doc/spede/html/namespacemembers_func.html -usr/share/doc/spede/html/namespaces.html -usr/share/doc/spede/html/nav_f.png -usr/share/doc/spede/html/nav_g.png -usr/share/doc/spede/html/nav_h.png -usr/share/doc/spede/html/open.png -usr/share/doc/spede/html/search/all_0.html -usr/share/doc/spede/html/search/all_0.js -usr/share/doc/spede/html/search/all_1.html -usr/share/doc/spede/html/search/all_1.js -usr/share/doc/spede/html/search/all_2.html -usr/share/doc/spede/html/search/all_2.js -usr/share/doc/spede/html/search/all_3.html -usr/share/doc/spede/html/search/all_3.js -usr/share/doc/spede/html/search/classes_0.html -usr/share/doc/spede/html/search/classes_0.js -usr/share/doc/spede/html/search/classes_1.html -usr/share/doc/spede/html/search/classes_1.js -usr/share/doc/spede/html/search/close.png -usr/share/doc/spede/html/search/files_0.html -usr/share/doc/spede/html/search/files_0.js -usr/share/doc/spede/html/search/functions_0.html -usr/share/doc/spede/html/search/functions_0.js -usr/share/doc/spede/html/search/functions_1.html -usr/share/doc/spede/html/search/functions_1.js -usr/share/doc/spede/html/search/functions_2.html -usr/share/doc/spede/html/search/functions_2.js -usr/share/doc/spede/html/search/mag_sel.png -usr/share/doc/spede/html/search/namespaces_0.html -usr/share/doc/spede/html/search/namespaces_0.js -usr/share/doc/spede/html/search/nomatches.html -usr/share/doc/spede/html/search/pages_0.html -usr/share/doc/spede/html/search/pages_0.js -usr/share/doc/spede/html/search/search.css -usr/share/doc/spede/html/search/search.js -usr/share/doc/spede/html/search/searchdata.js -usr/share/doc/spede/html/search/search_l.png -usr/share/doc/spede/html/search/search_m.png -usr/share/doc/spede/html/search/search_r.png -usr/share/doc/spede/html/spede_8cpp.html -usr/share/doc/spede/html/spede_8h.html -usr/share/doc/spede/html/spede_8h_source.html -usr/share/doc/spede/html/splitbar.png -usr/share/doc/spede/html/sync_off.png -usr/share/doc/spede/html/sync_on.png -usr/share/doc/spede/html/tabs.css -usr/share/doc/spede/html/tab_a.png -usr/share/doc/spede/html/tab_b.png -usr/share/doc/spede/html/tab_h.png -usr/share/doc/spede/html/tab_s.png diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/14 doxygen/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/14 doxygen/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/14 doxygen/meson.build" 2020-01-07 21:14:41.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/14 doxygen/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -25,4 +25,3 @@ endif subdir('doc') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/14 doxygen/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/14 doxygen/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/14 doxygen/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/14 doxygen/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "dir", "file": "usr/share/doc/spede/html"} + ], + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/15 llvm/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/15 llvm/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/15 llvm/meson.build" 2020-01-07 21:15:03.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/15 llvm/meson.build" 2021-10-23 16:55:43.000000000 +0000 @@ -1,28 +1,23 @@ project('llvmtest', ['c', 'cpp'], default_options : ['c_std=c99']) -d = dependency('llvm', required : false, method : 'config-tool') +method = get_option('method') +static = get_option('link-static') +d = dependency('llvm', required : false, method : method, static : static) if not d.found() - d = dependency('llvm', required : false, static : true) - if not d.found() - error('MESON_SKIP_TEST llvm not found.') - else - static = true - endif -else - static = false + error('MESON_SKIP_TEST llvm not found.') endif -d = dependency('llvm', modules : 'not-found', required : false, static : static) +d = dependency('llvm', modules : 'not-found', required : false, static : static, method : method) assert(d.found() == false, 'not-found llvm module found') -d = dependency('llvm', version : '<0.1', required : false, static : static) +d = dependency('llvm', version : '<0.1', required : false, static : static, method : method) assert(d.found() == false, 'ancient llvm module found') -d = dependency('llvm', optional_modules : 'not-found', required : false, static : static) +d = dependency('llvm', optional_modules : 'not-found', required : false, static : static, method : method) assert(d.found() == true, 'optional module stopped llvm from being found.') # Check we can apply a version constraint -d = dependency('llvm', version : ['< 500', '>=@0@'.format(d.version())], required: false, static : static) +d = dependency('llvm', version : ['< 500', '>=@0@'.format(d.version())], required: false, static : static, method : method) assert(d.found() == true, 'Cannot set version constraints') dep_tinfo = dependency('tinfo', required : false) @@ -31,29 +26,26 @@ dep_tinfo = cpp.find_library('tinfo', required: false) endif -foreach method : ['config-tool', 'cmake'] - foreach static : [true, false] - message('Trying method @0@ for @1@ link'.format(method, static ? 'static' : 'dynamic')) - llvm_dep = dependency( - 'llvm', - modules : ['bitwriter', 'asmprinter', 'executionengine', 'target', - 'mcjit', 'nativecodegen', 'amdgpu'], - required : false, - static : static, - method : method, - ) - if llvm_dep.found() - name = static ? 'static' : 'dynamic' - executable( - 'sum-@0@-@1@'.format(name, method), - 'sum.c', - dependencies : [ - llvm_dep, dep_tinfo, - # zlib will be statically linked on windows - dependency('zlib', required : host_machine.system() != 'windows'), - meson.get_compiler('c').find_library('dl', required : false), - ] - ) - endif - endforeach -endforeach +llvm_dep = dependency( + 'llvm', + modules : ['bitwriter', 'asmprinter', 'executionengine', 'target', + 'mcjit', 'nativecodegen', 'amdgpu'], + required : false, + static : static, + method : method, +) + +if not llvm_dep.found() + error('MESON_SKIP_TEST required llvm modules not found.') +endif + +executable( + 'sum', + 'sum.c', + dependencies : [ + llvm_dep, dep_tinfo, + # zlib will be statically linked on windows + dependency('zlib', required : host_machine.system() != 'windows'), + meson.get_compiler('c').find_library('dl', required : false), + ] + ) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/15 llvm/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/15 llvm/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/15 llvm/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/15 llvm/meson_options.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,10 @@ +option( + 'method', + type : 'combo', + choices : ['config-tool', 'cmake'] +) +option( + 'link-static', + type : 'boolean', + value : false, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/15 llvm/sum.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/15 llvm/sum.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/15 llvm/sum.c" 2017-05-05 10:22:41.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/15 llvm/sum.c" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,4 @@ -/** This code is public domain, and taken from +/** This code is public domain, and taken from * https://github.com/paulsmith/getting-started-llvm-c-api/blob/master/sum.c */ /** diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/15 llvm/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/15 llvm/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/15 llvm/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/15 llvm/test.json" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,18 @@ +{ + "matrix": { + "options": { + "method": [ + { "val": "config-tool", "skip_on_jobname": ["msys2-gcc"]}, + { "val": "cmake", "skip_on_jobname": ["msys2-gcc"] } + ], + "link-static": [ + { "val": true, "skip_on_jobname": ["opensuse"] }, + { "val": false } + ] + }, + "exclude": [ + { "method": "cmake", "link-static": false } + ] + }, + "skip_on_jobname": ["azure", "cygwin"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/16 sdl2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/16 sdl2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/16 sdl2/meson.build" 2020-01-07 21:14:46.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/16 sdl2/meson.build" 2021-10-23 16:55:30.000000000 +0000 @@ -1,6 +1,8 @@ project('sdl2 test', 'c') -sdl2_dep = dependency('sdl2', version : '>=2.0.0', required: false) +method = get_option('method') + +sdl2_dep = dependency('sdl2', version : '>=2.0.0', required : false, method : method) if not sdl2_dep.found() error('MESON_SKIP_TEST sdl2 not found.') @@ -9,19 +11,3 @@ e = executable('sdl2prog', 'sdl2prog.c', dependencies : sdl2_dep) test('sdl2test', e) - -if sdl2_dep.type_name() == 'extraframeworks' - # The SDL OSX framework does not ship with detection executables - # so skip the remaining tests. - subdir_done() -endif - -# Ensure that we can find it with sdl2-config too, using the legacy method name -configdep = dependency('sdl2', method : 'sdlconfig') - -# And the modern method name -configdep = dependency('sdl2', method : 'config-tool') - -# Check we can apply a version constraint -dependency('sdl2', version: '>=@0@'.format(sdl2_dep.version()), method: 'pkg-config') -dependency('sdl2', version: '>=@0@'.format(sdl2_dep.version()), method: 'config-tool') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/16 sdl2/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/16 sdl2/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/16 sdl2/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/16 sdl2/meson_options.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +option( + 'method', + type : 'combo', + choices : ['auto', 'pkg-config', 'config-tool', 'sdlconfig', 'extraframework'], + value : 'auto', +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/16 sdl2/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/16 sdl2/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/16 sdl2/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/16 sdl2/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,14 @@ +{ + "matrix": { + "options": { + "method": [ + { "val": "auto" }, + { "val": "pkg-config" }, + { "val": "config-tool" }, + { "val": "sdlconfig" }, + { "val": "extraframework", "skip_on_os": ["!darwin"], "skip_on_jobname": ["macos"] } + ] + } + }, + "skip_on_jobname": ["azure", "cygwin", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/17 mpi/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/17 mpi/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/17 mpi/meson.build" 2020-01-07 21:14:56.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/17 mpi/meson.build" 2021-10-23 16:55:39.000000000 +0000 @@ -1,7 +1,9 @@ project('mpi', 'c', 'cpp', default_options: ['b_asneeded=false']) +method = get_option('method') + cc = meson.get_compiler('c') -mpic = dependency('mpi', language : 'c', required : false) +mpic = dependency('mpi', language : 'c', required : false, method : method) if not mpic.found() error('MESON_SKIP_TEST: MPI not found, skipping.') endif @@ -9,12 +11,12 @@ 'main.c', dependencies : [mpic]) -test('MPI C', exec, timeout: 10) +test('MPI C', exec, timeout: 20) # C++ MPI not supported by MS-MPI cpp = meson.get_compiler('cpp') -mpicpp = dependency('mpi', language : 'cpp', required: false) +mpicpp = dependency('mpi', language : 'cpp', required: false, method : method) if not cpp.links(''' #include #include @@ -26,12 +28,12 @@ 'main.cpp', dependencies : [mpicpp]) -test('MPI C++', execpp, timeout: 10) +test('MPI C++', execpp, timeout: 20) if add_languages('fortran', required : false) fc = meson.get_compiler('fortran') - mpif = dependency('mpi', language : 'fortran', required: false) + mpif = dependency('mpi', language : 'fortran', required: false, method : method) if not fc.links('use mpi; end', dependencies: mpif, name: 'Fortran MPI') mpif = disabler() endif @@ -40,11 +42,11 @@ 'main.f90', dependencies : mpif) - test('MPI Fortran', exef, timeout: 10) + test('MPI Fortran', exef, timeout: 20) endif # Check we can apply a version constraint if mpic.version() != 'unknown' - dependency('mpi', version: '>=@0@'.format(mpic.version())) + dependency('mpi', version: '>=@0@'.format(mpic.version()), method : method) endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/17 mpi/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/17 mpi/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/17 mpi/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/17 mpi/meson_options.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +option( + 'method', + type : 'combo', + choices : ['auto', 'pkg-config', 'config-tool', 'system'], + value : 'auto', +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/17 mpi/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/17 mpi/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/17 mpi/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/17 mpi/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,17 @@ +{ + "matrix": { + "options": { + "method": [ + { "val": "auto" }, + { "val": "pkg-config" }, + { "val": "config-tool", + "skip_on_jobname": ["fedora"] }, + { + "val": "system", + "compilers": { "c" :"msvc", "cpp": "msvc" } + } + ] + } + }, + "skip_on_jobname": ["azure", "cygwin", "msys2", "opensuse"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/18 vulkan/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/18 vulkan/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/18 vulkan/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/18 vulkan/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/19 pcap/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/19 pcap/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/19 pcap/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/19 pcap/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/meson.build" 2020-01-23 21:41:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,82 +1,66 @@ # this test requires the following on Ubuntu: libboost-{system,python,log,thread,test}-dev project('boosttest', 'cpp', - default_options : ['cpp_std=c++11']) + default_options : ['cpp_std=c++14']) -add_project_arguments(['-DBOOST_LOG_DYN_LINK'], - language : 'cpp' -) +s = get_option('static') -dep = dependency('boost', required: false) +dep = dependency('boost', static: s, required: false) if not dep.found() error('MESON_SKIP_TEST boost not found.') endif -compiler = meson.get_compiler('cpp') -if compiler.has_argument('-permissive') - # boost 1.64, the version we test against, doesn't work with -permissive - add_project_arguments('-permissive', language: 'cpp') -endif - # We want to have multiple separate configurations of Boost # within one project. The need to be independent of each other. # Use one without a library dependency and one with it. -linkdep = dependency('boost', modules : ['thread', 'system', 'test']) -staticdep = dependency('boost', modules : ['thread', 'system'], static : true) -testdep = dependency('boost', modules : ['unit_test_framework']) -nomoddep = dependency('boost') -extralibdep = dependency('boost', modules : ['thread', 'system', 'log_setup', 'log']) +linkdep = dependency('boost', static: s, modules : ['thread', 'system', 'date_time']) +testdep = dependency('boost', static: s, modules : ['unit_test_framework']) +nomoddep = dependency('boost', static: s) +extralibdep = dependency('boost', static: s, modules : ['thread', 'system', 'date_time', 'log_setup', 'log', 'filesystem', 'regex']) +notfound = dependency('boost', static: s, modules : ['this_should_not_exist_on_any_systen'], required: false) + +assert(not notfound.found()) +require_bp = host_machine.system() in ['linux', 'darwin'] pymod = import('python') -python2 = pymod.find_installation('python2', required: host_machine.system() == 'linux', disabler: true) -python3 = pymod.find_installation('python3', required: host_machine.system() == 'linux', disabler: true) -python2dep = python2.dependency(required: host_machine.system() == 'linux', embed: true, disabler: true) -python3dep = python3.dependency(required: host_machine.system() == 'linux', embed: true, disabler: true) +python2 = pymod.find_installation('python2', required: false , disabler: true) +python3 = pymod.find_installation('python3', required: require_bp , disabler: true) +python2dep = python2.dependency(required: false , embed: true, disabler: true) +python3dep = python3.dependency(required: require_bp, embed: true, disabler: true) # compile python 2/3 modules only if we found a corresponding python version -if(python2dep.found() and host_machine.system() == 'linux') - if(dep.version().version_compare('>=1.67')) - # if we have a new version of boost, we need to construct the module name based - # on the installed version of python (and hope that they match the version boost - # was compiled against) - py2version_string = ''.join(python2dep.version().split('.')) - bpython2dep = dependency('boost', modules : ['python' + py2version_string], required: false, disabler: true) - else - # if we have an older version of boost, we need to use the old module names - bpython2dep = dependency('boost', modules : ['python'], required: false, disabler: true) - endif +if(python2dep.found() and require_bp and not s) + bpython2dep = dependency('boost', static: s, modules : ['python'], required: false, disabler: true) else python2dep = disabler() bpython2dep = disabler() endif -if(python3dep.found() and host_machine.system() == 'linux') - if(dep.version().version_compare('>=1.67')) - py3version_string = ''.join(python3dep.version().split('.')) - bpython3dep = dependency('boost', modules : ['python' + py3version_string], required: false, disabler: true) - else - bpython3dep = dependency('boost', modules : ['python3'], required: false, disabler: true) - endif +if(python3dep.found() and require_bp and not s) + bpython3dep = dependency('boost', static: s, modules : ['python3']) else python3dep = disabler() bpython3dep = disabler() endif linkexe = executable('linkedexe', 'linkexe.cc', dependencies : linkdep) -staticexe = executable('staticlinkedexe', 'linkexe.cc', dependencies : staticdep) unitexe = executable('utf', 'unit_test.cpp', dependencies: testdep) nomodexe = executable('nomod', 'nomod.cpp', dependencies : nomoddep) extralibexe = executable('extralibexe', 'extralib.cpp', dependencies : extralibdep) # python modules are shared libraries -python2module = shared_library('python2_module', ['python_module.cpp'], dependencies: [python2dep, bpython2dep], name_prefix: '', cpp_args: ['-DMOD_NAME=python2_module']) -python3module = shared_library('python3_module', ['python_module.cpp'], dependencies: [python3dep, bpython3dep], name_prefix: '', cpp_args: ['-DMOD_NAME=python3_module']) +python2module = python2.extension_module('python2_module', ['python_module.cpp'], dependencies: [python2dep, bpython2dep], cpp_args: ['-DMOD_NAME=python2_module']) +python3module = python3.extension_module('python3_module', ['python_module.cpp'], dependencies: [python3dep, bpython3dep], cpp_args: ['-DMOD_NAME=python3_module']) -test('Boost linktest', linkexe) -test('Boost statictest', staticexe) -test('Boost UTF test', unitexe) + +test('Boost linktest', linkexe, timeout: 60) +test('Boost UTF test', unitexe, timeout: 60) test('Boost nomod', nomodexe) -test('Boost extralib test', extralibexe) +if host_machine.system() != 'darwin' or s + # Segfaults on macOS with dynamic linking since Boost 1.73 + # https://github.com/mesonbuild/meson/issues/7535 + test('Boost extralib test', extralibexe) +endif # explicitly use the correct python interpreter so that we don't have to provide two different python scripts that have different shebang lines python2interpreter = find_program(python2.path(), required: false, disabler: true) @@ -87,4 +71,4 @@ subdir('partial_dep') # check we can apply a version constraint -dependency('boost', version: '>=@0@'.format(dep.version())) +dependency('boost', static: s, version: '>=@0@'.format(dep.version())) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/meson_options.txt" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1 @@ +option('static', type: 'boolean', value: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/partial_dep/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/partial_dep/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/partial_dep/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/partial_dep/main.cpp" 2021-11-02 19:58:07.000000000 +0000 @@ -25,4 +25,3 @@ return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,22 @@ +{ + "matrix": { + "options": { + "static": [ + { "val": "true", "skip_on_env": [ "SKIP_STATIC_BOOST" ] }, + { "val": "false" } + ], + "b_vscrt": [ + { "val": null }, + { "val": "md", "compilers": { "cpp": "msvc" } }, + { "val": "mdd", "compilers": { "cpp": "msvc" } }, + { "val": "mt", "compilers": { "cpp": "msvc" } }, + { "val": "mtd", "compilers": { "cpp": "msvc" } } + ] + }, + "exclude": [ + { "static": "false", "b_vscrt": "mt" }, + { "static": "false", "b_vscrt": "mtd" } + ] + }, + "skip_on_jobname": ["azure", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/test_python_module.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/test_python_module.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/test_python_module.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/test_python_module.py" 2021-11-02 19:58:07.000000000 +0000 @@ -19,9 +19,9 @@ w.set(msg) - assert(msg == w.greet()) + assert msg == w.greet() version_string = str(sys.version_info[0]) + "." + str(sys.version_info[1]) - assert(version_string == w.version()) + assert version_string == w.version() if __name__ == '__main__': run() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/unit_test.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/unit_test.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/1 boost/unit_test.cpp" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/1 boost/unit_test.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -1,4 +1,3 @@ -#define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE "MesonTest" #define BOOST_TEST_MAIN #include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/20 cups/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/20 cups/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/20 cups/meson.build" 2020-01-07 21:14:58.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/20 cups/meson.build" 2021-10-23 16:55:41.000000000 +0000 @@ -12,9 +12,10 @@ # ensure we can find the cups dependency via the legacy and modern config-tool # options -dep = dependency('cups', version : '>=1.4', method : 'cups-config') -dep = dependency('cups', version : '>=1.4', method : 'config-tool') +depCC = dependency('cups', version : '>=1.4', method : 'cups-config') +depCT = dependency('cups', version : '>=1.4', method : 'config-tool') +depCM = dependency('cups', version : '>=1.4', method : 'cmake') # check we can apply a version constraint -dependency('cups', version: '>=@0@'.format(dep.version()), method: 'pkg-config', required: false) -dependency('cups', version: '>=@0@'.format(dep.version()), method: 'config-tool') +dependency('cups', version: '>=@0@'.format(depCT.version()), method: 'pkg-config', required: false) +dependency('cups', version: '>=@0@'.format(depCT.version()), method: 'config-tool') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/20 cups/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/20 cups/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/20 cups/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/20 cups/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/21 libwmf/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/21 libwmf/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/21 libwmf/meson.build" 2020-01-07 21:14:56.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/21 libwmf/meson.build" 2021-10-23 16:55:41.000000000 +0000 @@ -1,7 +1,7 @@ project('libwmf test', 'c') wm = find_program('libwmf-config', required : false) -if not wm.found() +if not wm.found() or meson.is_cross_build() error('MESON_SKIP_TEST: libwmf-config not installed') endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/21 libwmf/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/21 libwmf/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/21 libwmf/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/21 libwmf/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/22 gir link order/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/22 gir link order/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/22 gir link order/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/22 gir link order/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/23 hotdoc/doc/sitemap.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/23 hotdoc/doc/sitemap.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/23 hotdoc/doc/sitemap.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/23 hotdoc/doc/sitemap.txt" 2021-11-02 19:58:07.000000000 +0000 @@ -1,3 +1,2 @@ index.md c-index - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/23 hotdoc/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/23 hotdoc/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/23 hotdoc/installed_files.txt" 2019-07-09 16:34:14.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/23 hotdoc/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,314 +0,0 @@ -usr/share/doc/foobar/html/foo.html -usr/share/doc/foobar/html/c-index.html -usr/share/doc/foobar/html/index.html -usr/share/doc/foobar/html/dumped.trie -usr/share/doc/foobar/html/assets/theme.json -usr/share/doc/foobar/html/assets/css/prism-tomorrow.css -usr/share/doc/foobar/html/assets/css/bootstrap-toc.min.css -usr/share/doc/foobar/html/assets/css/frontend.css -usr/share/doc/foobar/html/assets/css/dumped.trie -usr/share/doc/foobar/html/assets/css/jquery.mCustomScrollbar.min.css -usr/share/doc/foobar/html/assets/css/custom_bootstrap.css -usr/share/doc/foobar/html/assets/templates/navbar_links.html -usr/share/doc/foobar/html/assets/templates/scripts.html -usr/share/doc/foobar/html/assets/templates/stylesheets.html -usr/share/doc/foobar/html/assets/templates/multi_return_value.html -usr/share/doc/foobar/html/assets/templates/parameters.html -usr/share/doc/foobar/html/assets/templates/base_page.html -usr/share/doc/foobar/html/assets/templates/footer.html -usr/share/doc/foobar/html/assets/templates/extra_head.html -usr/share/doc/foobar/html/assets/templates/parameter_detail.html -usr/share/doc/foobar/html/assets/templates/navbar_center.html -usr/share/doc/foobar/html/assets/templates/enum_member.html -usr/share/doc/foobar/html/assets/templates/member_list.html -usr/share/doc/foobar/html/assets/templates/return_item.html -usr/share/doc/foobar/html/assets/templates/subpages.html -usr/share/doc/foobar/html/assets/templates/dumped.trie -usr/share/doc/foobar/html/assets/templates/page_content.html -usr/share/doc/foobar/html/assets/templates/navbar.html -usr/share/doc/foobar/html/assets/templates/site_navigation.html -usr/share/doc/foobar/html/assets/templates/field_detail.html -usr/share/doc/foobar/html/assets/templates/brand-logo.html -usr/share/doc/foobar/html/assets/js/prism_autoloader_path_override.js -usr/share/doc/foobar/html/assets/js/jquery.js -usr/share/doc/foobar/html/assets/js/scrollspy.js -usr/share/doc/foobar/html/assets/js/isotope.pkgd.min.js -usr/share/doc/foobar/html/assets/js/utils.js -usr/share/doc/foobar/html/assets/js/typeahead.jquery.min.js -usr/share/doc/foobar/html/assets/js/language_switching.js -usr/share/doc/foobar/html/assets/js/tag_filtering.js -usr/share/doc/foobar/html/assets/js/prism-autoloader.js -usr/share/doc/foobar/html/assets/js/navbar_offset_scroller.js -usr/share/doc/foobar/html/assets/js/lines_around_headings.js -usr/share/doc/foobar/html/assets/js/trie_index.js -usr/share/doc/foobar/html/assets/js/search.js -usr/share/doc/foobar/html/assets/js/trie.js -usr/share/doc/foobar/html/assets/js/bootstrap.js -usr/share/doc/foobar/html/assets/js/navigation.js -usr/share/doc/foobar/html/assets/js/bootstrap-toc.min.js -usr/share/doc/foobar/html/assets/js/anchor.min.js -usr/share/doc/foobar/html/assets/js/prism-core.js -usr/share/doc/foobar/html/assets/js/sitemap.js -usr/share/doc/foobar/html/assets/js/dumped.trie -usr/share/doc/foobar/html/assets/js/mustache.min.js -usr/share/doc/foobar/html/assets/js/compare-versions.js -usr/share/doc/foobar/html/assets/js/jquery.touchSwipe.min.js -usr/share/doc/foobar/html/assets/js/jquery.mCustomScrollbar.concat.min.js -usr/share/doc/foobar/html/assets/js/search/members -usr/share/doc/foobar/html/assets/js/search/Hello -usr/share/doc/foobar/html/assets/js/search/hello -usr/share/doc/foobar/html/assets/js/search/type -usr/share/doc/foobar/html/assets/js/search/FooIndecision -usr/share/doc/foobar/html/assets/js/search/fooindecision -usr/share/doc/foobar/html/assets/js/search/Members -usr/share/doc/foobar/html/assets/js/search/dumped.trie -usr/share/doc/foobar/html/assets/js/search/indecision -usr/share/doc/foobar/html/assets/js/search/hotdoc_fragments/index.html-hello-world.fragment -usr/share/doc/foobar/html/assets/js/search/hotdoc_fragments/dumped.trie -usr/share/doc/foobar/html/assets/js/search/hotdoc_fragments/foo.html-FooIndecision.fragment -usr/share/doc/foobar/html/assets/js/search/Subpages -usr/share/doc/foobar/html/assets/js/search/foo -usr/share/doc/foobar/html/assets/js/search/API -usr/share/doc/foobar/html/assets/js/search/Reference -usr/share/doc/foobar/html/assets/js/search/api -usr/share/doc/foobar/html/assets/js/search/reference -usr/share/doc/foobar/html/assets/js/search/subpages -usr/share/doc/foobar/html/assets/js/search/hotdoc_fragments/index.html-subpages.fragment -usr/share/doc/foobar/html/assets/js/search/hotdoc_fragments/c-index.html-subpages.fragment -usr/share/doc/foobar/html/assets/prism_components/prism-inform7.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-pascal.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-bro.js -usr/share/doc/foobar/html/assets/prism_components/prism-nim.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-gherkin.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-stylus.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-ocaml.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-powershell.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-smalltalk.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-verilog.js -usr/share/doc/foobar/html/assets/prism_components/prism-puppet.js -usr/share/doc/foobar/html/assets/prism_components/prism-aspnet.js -usr/share/doc/foobar/html/assets/prism_components/prism-parigp.js -usr/share/doc/foobar/html/assets/prism_components/prism-objectivec.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-processing.js -usr/share/doc/foobar/html/assets/prism_components/prism-objectivec.js -usr/share/doc/foobar/html/assets/prism_components/prism-jsx.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-nginx.js -usr/share/doc/foobar/html/assets/prism_components/prism-powershell.js -usr/share/doc/foobar/html/assets/prism_components/prism-php.js -usr/share/doc/foobar/html/assets/prism_components/prism-smarty.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-roboconf.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-batch.js -usr/share/doc/foobar/html/assets/prism_components/prism-vhdl.js -usr/share/doc/foobar/html/assets/prism_components/prism-protobuf.js -usr/share/doc/foobar/html/assets/prism_components/prism-textile.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-crystal.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-scss.js -usr/share/doc/foobar/html/assets/prism_components/prism-bro.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-smarty.js -usr/share/doc/foobar/html/assets/prism_components/prism-bison.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-tcl.js -usr/share/doc/foobar/html/assets/prism_components/prism-pure.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-makefile.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-applescript.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-css-extras.js -usr/share/doc/foobar/html/assets/prism_components/prism-stylus.js -usr/share/doc/foobar/html/assets/prism_components/prism-q.js -usr/share/doc/foobar/html/assets/prism_components/prism-dart.js -usr/share/doc/foobar/html/assets/prism_components/prism-oz.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-haskell.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-clike.js -usr/share/doc/foobar/html/assets/prism_components/prism-kotlin.js -usr/share/doc/foobar/html/assets/prism_components/prism-http.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-bash.js -usr/share/doc/foobar/html/assets/prism_components/prism-apl.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-docker.js -usr/share/doc/foobar/html/assets/prism_components/prism-sass.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-basic.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-nasm.js -usr/share/doc/foobar/html/assets/prism_components/prism-kotlin.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-abap.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-perl.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-rust.js -usr/share/doc/foobar/html/assets/prism_components/prism-c.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-scala.js -usr/share/doc/foobar/html/assets/prism_components/prism-glsl.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-lua.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-coffeescript.js -usr/share/doc/foobar/html/assets/prism_components/prism-jade.js -usr/share/doc/foobar/html/assets/prism_components/prism-keyman.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-crystal.js -usr/share/doc/foobar/html/assets/prism_components/prism-rest.js -usr/share/doc/foobar/html/assets/prism_components/prism-json.js -usr/share/doc/foobar/html/assets/prism_components/prism-roboconf.js -usr/share/doc/foobar/html/assets/prism_components/prism-twig.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-dart.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-vim.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-handlebars.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-cpp.js -usr/share/doc/foobar/html/assets/prism_components/prism-fsharp.js -usr/share/doc/foobar/html/assets/prism_components/prism-sas.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-brainfuck.js -usr/share/doc/foobar/html/assets/prism_components/prism-haxe.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-julia.js -usr/share/doc/foobar/html/assets/prism_components/prism-jade.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-python.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-nim.js -usr/share/doc/foobar/html/assets/prism_components/prism-typescript.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-csharp.js -usr/share/doc/foobar/html/assets/prism_components/prism-brainfuck.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-asciidoc.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-groovy.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-applescript.js -usr/share/doc/foobar/html/assets/prism_components/prism-elixir.js -usr/share/doc/foobar/html/assets/prism_components/prism-diff.js -usr/share/doc/foobar/html/assets/prism_components/prism-scheme.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-parser.js -usr/share/doc/foobar/html/assets/prism_components/prism-qore.js -usr/share/doc/foobar/html/assets/prism_components/prism-yaml.js -usr/share/doc/foobar/html/assets/prism_components/prism-j.js -usr/share/doc/foobar/html/assets/prism_components/prism-mel.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-css-extras.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-erlang.js -usr/share/doc/foobar/html/assets/prism_components/prism-icon.js -usr/share/doc/foobar/html/assets/prism_components/prism-actionscript.js -usr/share/doc/foobar/html/assets/prism_components/prism-cpp.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-makefile.js -usr/share/doc/foobar/html/assets/prism_components/prism-q.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-nsis.js -usr/share/doc/foobar/html/assets/prism_components/prism-mizar.js -usr/share/doc/foobar/html/assets/prism_components/prism-wiki.js -usr/share/doc/foobar/html/assets/prism_components/prism-csharp.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-julia.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-coffeescript.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-sql.js -usr/share/doc/foobar/html/assets/prism_components/prism-php-extras.js -usr/share/doc/foobar/html/assets/prism_components/prism-basic.js -usr/share/doc/foobar/html/assets/prism_components/prism-swift.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-haxe.js -usr/share/doc/foobar/html/assets/prism_components/prism-apacheconf.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-javascript.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-markup.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-keyman.js -usr/share/doc/foobar/html/assets/prism_components/prism-sql.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-php-extras.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-scheme.js -usr/share/doc/foobar/html/assets/prism_components/prism-python.js -usr/share/doc/foobar/html/assets/prism_components/prism-autoit.js -usr/share/doc/foobar/html/assets/prism_components/prism-gherkin.js -usr/share/doc/foobar/html/assets/prism_components/prism-java.js -usr/share/doc/foobar/html/assets/prism_components/prism-parigp.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-autohotkey.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-ruby.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-nginx.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-core.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-fortran.js -usr/share/doc/foobar/html/assets/prism_components/prism-nasm.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-ini.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-protobuf.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-jsx.js -usr/share/doc/foobar/html/assets/prism_components/prism-markdown.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-nix.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-nsis.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-oz.js -usr/share/doc/foobar/html/assets/prism_components/prism-less.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-abap.js -usr/share/doc/foobar/html/assets/prism_components/prism-puppet.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-nix.js -usr/share/doc/foobar/html/assets/prism_components/prism-pascal.js -usr/share/doc/foobar/html/assets/prism_components/prism-latex.js -usr/share/doc/foobar/html/assets/prism_components/prism-verilog.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-aspnet.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-go.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-glsl.js -usr/share/doc/foobar/html/assets/prism_components/prism-inform7.js -usr/share/doc/foobar/html/assets/prism_components/prism-yaml.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-matlab.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-lua.js -usr/share/doc/foobar/html/assets/prism_components/prism-mizar.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-c.js -usr/share/doc/foobar/html/assets/prism_components/prism-fsharp.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-haml.js -usr/share/doc/foobar/html/assets/prism_components/prism-rust.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-icon.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-fortran.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-qore.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-batch.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-eiffel.js -usr/share/doc/foobar/html/assets/prism_components/prism-vim.js -usr/share/doc/foobar/html/assets/prism_components/prism-j.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-eiffel.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-elixir.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-erlang.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-matlab.js -usr/share/doc/foobar/html/assets/prism_components/prism-tcl.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-ruby.js -usr/share/doc/foobar/html/assets/prism_components/prism-d.js -usr/share/doc/foobar/html/assets/prism_components/prism-swift.js -usr/share/doc/foobar/html/assets/prism_components/prism-wiki.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-lolcode.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-latex.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-prolog.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-php.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-scss.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-vhdl.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-lolcode.js -usr/share/doc/foobar/html/assets/prism_components/prism-prolog.js -usr/share/doc/foobar/html/assets/prism_components/prism-apacheconf.js -usr/share/doc/foobar/html/assets/prism_components/prism-core.js -usr/share/doc/foobar/html/assets/prism_components/prism-diff.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-json.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-ini.js -usr/share/doc/foobar/html/assets/prism_components/dumped.trie -usr/share/doc/foobar/html/assets/prism_components/prism-r.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-markup.js -usr/share/doc/foobar/html/assets/prism_components/prism-apl.js -usr/share/doc/foobar/html/assets/prism_components/prism-markdown.js -usr/share/doc/foobar/html/assets/prism_components/prism-asciidoc.js -usr/share/doc/foobar/html/assets/prism_components/prism-ocaml.js -usr/share/doc/foobar/html/assets/prism_components/prism-javascript.js -usr/share/doc/foobar/html/assets/prism_components/prism-autohotkey.js -usr/share/doc/foobar/html/assets/prism_components/prism-less.js -usr/share/doc/foobar/html/assets/prism_components/prism-pure.js -usr/share/doc/foobar/html/assets/prism_components/prism-groovy.js -usr/share/doc/foobar/html/assets/prism_components/prism-bison.js -usr/share/doc/foobar/html/assets/prism_components/prism-sass.js -usr/share/doc/foobar/html/assets/prism_components/prism-css.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-haml.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-handlebars.js -usr/share/doc/foobar/html/assets/prism_components/prism-textile.js -usr/share/doc/foobar/html/assets/prism_components/prism-parser.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-docker.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-monkey.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-http.js -usr/share/doc/foobar/html/assets/prism_components/prism-git.js -usr/share/doc/foobar/html/assets/prism_components/prism-sas.js -usr/share/doc/foobar/html/assets/prism_components/prism-go.js -usr/share/doc/foobar/html/assets/prism_components/prism-mel.js -usr/share/doc/foobar/html/assets/prism_components/prism-rest.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-clike.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-d.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-haskell.js -usr/share/doc/foobar/html/assets/prism_components/prism-git.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-java.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-rip.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-perl.js -usr/share/doc/foobar/html/assets/prism_components/prism-typescript.js -usr/share/doc/foobar/html/assets/prism_components/prism-actionscript.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-autoit.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-rip.js -usr/share/doc/foobar/html/assets/prism_components/prism-twig.js -usr/share/doc/foobar/html/assets/prism_components/prism-monkey.js -usr/share/doc/foobar/html/assets/prism_components/prism-processing.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-scala.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-smalltalk.js -usr/share/doc/foobar/html/assets/prism_components/prism-bash.min.js -usr/share/doc/foobar/html/assets/prism_components/prism-r.js -usr/share/doc/foobar/html/assets/prism_components/prism-css.js -usr/share/doc/foobar/html/assets/fonts/glyphicons-halflings-regular.woff -usr/share/doc/foobar/html/assets/fonts/glyphicons-halflings-regular.woff2 -usr/share/doc/foobar/html/assets/fonts/glyphicons-halflings-regular.svg -usr/share/doc/foobar/html/assets/fonts/glyphicons-halflings-regular.ttf -usr/share/doc/foobar/html/assets/fonts/glyphicons-halflings-regular.eot -usr/share/doc/foobar/html/assets/fonts/dumped.trie -usr/share/doc/foobar/html/assets/images/home.svg -usr/share/doc/foobar/html/assets/images/dumped.trie diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/23 hotdoc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/23 hotdoc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/23 hotdoc/meson.build" 2018-12-09 14:27:23.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/23 hotdoc/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -12,4 +12,3 @@ assert(hotdoc.has_extensions(['gi-extension', 'no-way-you-exist-extension']) == false, 'A hotdoc extension called "no-way-you-exist-extension" should never be found.') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/23 hotdoc/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/23 hotdoc/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/23 hotdoc/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/23 hotdoc/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "installed": [ + {"type": "dir", "file": "usr/share/doc/foobar/html"} + ], + "tools": { + "hotdoc": ">=0.1.0" + }, + "skip_on_jobname": ["msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/24 libgcrypt/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/24 libgcrypt/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/24 libgcrypt/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/24 libgcrypt/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/25 hdf5/main.f90" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/25 hdf5/main.f90" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/25 hdf5/main.f90" 2019-02-07 09:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/25 hdf5/main.f90" 2021-11-02 19:58:07.000000000 +0000 @@ -13,5 +13,5 @@ call h5close_f(ier) if (ier /= 0) error stop 'Unable to close HDF5 library' - + end program diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/25 hdf5/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/25 hdf5/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/25 hdf5/meson.build" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/25 hdf5/meson.build" 2021-04-01 21:12:21.000000000 +0000 @@ -2,8 +2,10 @@ # NOTE: all HDF5 languages must have HDF5 C library working. +method = get_option('method') + # --- C tests -h5c = dependency('hdf5', language : 'c', required : false) +h5c = dependency('hdf5', language : 'c', required : false, method : method) if not h5c.found() error('MESON_SKIP_TEST: HDF5 C library not found.') endif @@ -12,16 +14,31 @@ # --- C++ tests if add_languages('cpp', required: false) - h5cpp = dependency('hdf5', language : 'cpp', required : false, disabler: true) + h5cpp = dependency('hdf5', language : 'cpp', required : false, disabler: true, method : method) execpp = executable('execpp', 'main.cpp', dependencies : h5cpp) test('HDF5 C++', execpp, timeout: 30) endif -# --- Fortran tests -if add_languages('fortran', required: false) - h5f = dependency('hdf5', language : 'fortran', required : false, disabler: true) - exef = executable('exef', 'main.f90', dependencies : h5f) - test('HDF5 Fortran', exef, timeout: 30) +test_fortran = add_languages('fortran', required: false) + +if test_fortran + cpp = meson.get_compiler('cpp') + fc = meson.get_compiler('fortran') + + if host_machine.system() == 'darwin' and cpp.get_id() == 'clang' and fc.get_id() == 'gcc' + # Search paths don't work correctly here and -lgfortran doesn't work + test_fortran = false + elif host_machine.system() == 'windows' and cpp.get_id() != 'gcc' and fc.get_id() == 'gcc' + # mixing gfotran with non-gcc doesn't work on windows + test_fortran = false + endif + + # --- Fortran tests + if test_fortran + h5f = dependency('hdf5', language : 'fortran', required : false, disabler: true, method : method) + exef = executable('exef', 'main.f90', dependencies : h5f) + test('HDF5 Fortran', exef, timeout: 30) + endif endif # Check we can apply a version constraint diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/25 hdf5/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/25 hdf5/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/25 hdf5/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/25 hdf5/meson_options.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,6 @@ +option( + 'method', + type : 'combo', + choices : ['pkg-config', 'config-tool'], + value : 'pkg-config' +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/25 hdf5/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/25 hdf5/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/25 hdf5/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/25 hdf5/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,11 @@ +{ + "matrix": { + "options": { + "method": [ + { "val": "pkg-config", "skip_on_jobname": ["macos"] }, + { "val": "config-tool" } + ] + } + }, + "skip_on_jobname": ["azure", "cygwin", "fedora", "msys2", "opensuse"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/26 netcdf/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/26 netcdf/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/26 netcdf/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/26 netcdf/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "bionic", "cygwin", "fedora", "macos", "msys2", "opensuse", "ubuntu"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/27 gpgme/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/27 gpgme/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/27 gpgme/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/27 gpgme/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/28 gir link order 2/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/28 gir link order 2/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/28 gir link order 2/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/28 gir link order 2/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/29 blocks/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/29 blocks/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/29 blocks/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/29 blocks/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "gcc", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/2 gtest/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/2 gtest/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/2 gtest/meson.build" 2020-01-07 21:13:32.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/2 gtest/meson.build" 2021-10-23 16:55:01.000000000 +0000 @@ -8,7 +8,7 @@ gtest_nomain = dependency('gtest', main : false, method : 'system') e = executable('testprog', 'test.cc', dependencies : gtest) -test('gtest test', e) +test('gtest test', e, protocol : 'gtest') e = executable('testprog_nomain', 'test_nomain.cc', dependencies : gtest_nomain) -test('gtest nomain test', e) +test('gtest nomain test', e, protocol : 'gtest') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/2 gtest/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/2 gtest/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/2 gtest/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/2 gtest/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/30 scalapack/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/30 scalapack/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/30 scalapack/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/30 scalapack/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "bionic", "cygwin", "fedora", "msys2", "opensuse"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/31 curses/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/31 curses/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/31 curses/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/31 curses/main.c" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +#include "curses.h" + +int main(void) { +initscr(); +endwin(); +return 0; +} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/31 curses/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/31 curses/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/31 curses/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/31 curses/meson.build" 2021-10-23 16:55:47.000000000 +0000 @@ -0,0 +1,13 @@ +project('curses', 'c') + +curses = dependency('curses', required: false, method : get_option('method'), version : '>= 0') +if not curses.found() + error('MESON_SKIP_TEST: Curses library not found') +endif + +exec = executable('basic', 'main.c', dependencies: curses) +# didn't run the test because in general graphics fail on CI + +# this should fail +not_found = dependency('curses', required: false, method : get_option('method'), version : '> 1000000') +assert(not_found.found() == false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/31 curses/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/31 curses/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/31 curses/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/31 curses/meson_options.txt" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,6 @@ +option( + 'method', + type : 'combo', + choices : ['pkg-config', 'config-tool', 'system'], + value : 'pkg-config', +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/31 curses/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/31 curses/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/31 curses/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/31 curses/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,12 @@ +{ + "matrix": { + "options": { + "method": [ + { "val": "pkg-config" }, + { "val": "config-tool", "skip_on_jobname": ["msys2"] }, + { "val": "system", "skip_on_os": ["windows"] } + ] + } + }, + "skip_on_jobname": ["azure", "cygwin"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/32 boost root/boost/include/boost/version.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/32 boost root/boost/include/boost/version.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/32 boost root/boost/include/boost/version.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/32 boost root/boost/include/boost/version.hpp" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,3 @@ +#define BOOST_VERSION 100 + +#error This is not a real version of boost diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/32 boost root/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/32 boost root/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/32 boost root/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/32 boost root/meson.build" 2021-10-23 16:55:47.000000000 +0000 @@ -0,0 +1,6 @@ +project('boosttest', 'cpp') + +dep = dependency('boost', modules : 'regex', required: false) + +assert(dep.found(), 'expected to find a fake version of boost') +assert(dep.version() == '0.1.0', 'expected to find version 0.1.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/32 boost root/nativefile.ini.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/32 boost root/nativefile.ini.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/32 boost root/nativefile.ini.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/32 boost root/nativefile.ini.in" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,2 @@ +[properties] +boost_root = '@MESON_TEST_ROOT@/boost' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,3 @@ +#define BOOST_VERSION 200 + +#error This is not a real version of boost diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/33 boost split root/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/33 boost split root/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/33 boost split root/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/33 boost split root/meson.build" 2021-10-23 16:55:48.000000000 +0000 @@ -0,0 +1,6 @@ +project('boosttest', 'cpp') + +dep = dependency('boost', modules : 'regex', required: false) + +assert(dep.found(), 'expected to find a fake version of boost') +assert(dep.version() == '0.2.0', 'expected to find version 0.2.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/33 boost split root/nativefile.ini.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/33 boost split root/nativefile.ini.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/33 boost split root/nativefile.ini.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/33 boost split root/nativefile.ini.in" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,3 @@ +[properties] +boost_includedir = '@MESON_TEST_ROOT@/boost/extra-dir/include' +boost_librarydir = '@MESON_TEST_ROOT@/boost/lib' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/meson.build" 2021-10-23 16:55:51.000000000 +0000 @@ -0,0 +1,18 @@ +project('gobject-introspection-static-helper', 'c') + +gir = find_program('g-ir-scanner', required: false) +if not gir.found() + error('MESON_SKIP_TEST g-ir-scanner not found.') +endif + +gobject_introspection = dependency('gobject-introspection-1.0') +# This won't work without https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/72 +if gobject_introspection.version().version_compare('< 1.58.1') + error('MESON_SKIP_TEST gobject-introspection is too old to support static libraries') +endif + +gnome = import('gnome') +gobj = dependency('gobject-2.0') + +subdir('statichelper') +subdir('subdir/gir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/statichelper/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/statichelper/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/statichelper/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/statichelper/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,22 @@ +conf = configuration_data() +conf.set('HEADER', 'glib-object.h') + +meson_sample_header = configure_file( + input : 'meson-sample.h.in', + output : 'meson-sample.h', + configuration : conf) + +statichelper_sources = files('meson-sample.c') + [meson_sample_header] + +statichelper_lib = static_library( + 'statichelper', + sources : statichelper_sources, + dependencies : gobj, +) + +statichelper_inc = include_directories('.') +statichelper_dep = declare_dependency( + link_with: statichelper_lib, + dependencies : gobj, + include_directories : [statichelper_inc], +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/statichelper/meson-sample.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/statichelper/meson-sample.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/statichelper/meson-sample.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/statichelper/meson-sample.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,126 @@ +#include "meson-sample.h" + +typedef struct _MesonSamplePrivate +{ + gchar *msg; +} MesonSamplePrivate; + + +G_DEFINE_TYPE_WITH_PRIVATE (MesonSample, meson_sample, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_sample_new: + * @msg: The message to set. + * + * Allocates a new #MesonSample. + * + * Returns: (transfer full): a #MesonSample. + */ +MesonSample * +meson_sample_new (const gchar *msg) +{ + g_return_val_if_fail (msg != NULL, NULL); + + return g_object_new (MESON_TYPE_SAMPLE, + "message", msg, + NULL); +} + +static void +meson_sample_finalize (GObject *object) +{ + MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object); + + g_clear_pointer (&priv->msg, g_free); + + G_OBJECT_CLASS (meson_sample_parent_class)->finalize (object); +} + +static void +meson_sample_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, priv->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_sample_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object); + + switch (prop_id) + { + case PROP_MSG: + priv->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_sample_class_init (MesonSampleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_sample_finalize; + object_class->get_property = meson_sample_get_property; + object_class->set_property = meson_sample_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_sample_init (MesonSample *self) +{ +} + +/** + * meson_sample_print_message: + * @self: a #MesonSample. + * + * Prints the message. + * + */ +void +meson_sample_print_message (MesonSample *self) +{ + MesonSamplePrivate *priv; + + g_return_if_fail (MESON_IS_SAMPLE (self)); + + priv = meson_sample_get_instance_private (self); + + g_print ("Message: %s\n", priv->msg); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,22 @@ +#ifndef MESON_SAMPLE_H +#define MESON_SAMPLE_H + +#include <@HEADER@> + +G_BEGIN_DECLS + +#define MESON_TYPE_SAMPLE (meson_sample_get_type()) + +G_DECLARE_DERIVABLE_TYPE (MesonSample, meson_sample, MESON, SAMPLE, GObject) + +struct _MesonSampleClass { + GObjectClass parent_class; +}; + + +MesonSample *meson_sample_new (const gchar *msg); +void meson_sample_print_message (MesonSample *self); + +G_END_DECLS + +#endif /* MESON_SAMPLE_H */ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/subdir/gir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/subdir/gir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/subdir/gir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/subdir/gir/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,28 @@ +libsources = ['meson-subsample.c', 'meson-subsample.h'] + +girlib = shared_library( + 'girlib', + sources : libsources, + dependencies : [gobj, statichelper_dep], + install : true +) + +girexe = executable( + 'girprog', + sources : 'prog.c', + dependencies : [gobj, statichelper_dep], + link_with : girlib +) + +gnome.generate_gir( + girlib, statichelper_lib, + sources : [ libsources, statichelper_sources ], + nsversion : '1.0', + namespace : 'Meson', + symbol_prefix : 'meson_', + identifier_prefix : 'Meson', + includes : ['GObject-2.0'], + install : true +) + +test('gobject introspection/subproject/c', girexe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,124 @@ +#include "meson-subsample.h" + +struct _MesonSubSample +{ + MesonSample parent_instance; + + gchar *msg; +}; + +G_DEFINE_TYPE (MesonSubSample, meson_sub_sample, MESON_TYPE_SAMPLE) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_sub_sample_new: + * @msg: The message to set. + * + * Allocates a new #MesonSubSample. + * + * Returns: (transfer full): a #MesonSubSample. + */ +MesonSubSample * +meson_sub_sample_new (const gchar *msg) +{ + g_return_val_if_fail (msg != NULL, NULL); + + return g_object_new (MESON_TYPE_SUB_SAMPLE, + "message", msg, + NULL); +} + +static void +meson_sub_sample_finalize (GObject *object) +{ + MesonSubSample *self = (MesonSubSample *)object; + + g_clear_pointer (&self->msg, g_free); + + G_OBJECT_CLASS (meson_sub_sample_parent_class)->finalize (object); +} + +static void +meson_sub_sample_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonSubSample *self = MESON_SUB_SAMPLE (object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, self->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_sub_sample_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonSubSample *self = MESON_SUB_SAMPLE (object); + + switch (prop_id) + { + case PROP_MSG: + self->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_sub_sample_class_init (MesonSubSampleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_sub_sample_finalize; + object_class->get_property = meson_sub_sample_get_property; + object_class->set_property = meson_sub_sample_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_sub_sample_init (MesonSubSample *self) +{ +} + +/** + * meson_sub_sample_print_message: + * @self: a #MesonSubSample. + * + * Prints the message. + * + * Returns: Nothing. + */ +void +meson_sub_sample_print_message (MesonSubSample *self) +{ + g_return_if_fail (MESON_IS_SUB_SAMPLE (self)); + + g_print ("Message: %s\n", self->msg); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,17 @@ +#ifndef MESON_SUB_SAMPLE_H +#define MESON_SUB_SAMPLE_H + +#include +#include + +G_BEGIN_DECLS + +#define MESON_TYPE_SUB_SAMPLE (meson_sub_sample_get_type()) + +G_DECLARE_FINAL_TYPE (MesonSubSample, meson_sub_sample, MESON, SUB_SAMPLE, MesonSample) + +MesonSubSample *meson_sub_sample_new (const gchar *msg); + +G_END_DECLS + +#endif /* MESON_SUB_SAMPLE_H */ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/subdir/gir/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/subdir/gir/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/subdir/gir/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/subdir/gir/prog.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,12 @@ +#include "meson-subsample.h" + +gint +main (gint argc, + gchar *argv[]) +{ + MesonSample * i = (MesonSample*) meson_sub_sample_new ("Hello, sub/meson/c!"); + meson_sample_print_message (i); + g_object_unref (i); + + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/34 gir static lib/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/34 gir static lib/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/girepository-1.0/Meson-1.0.typelib"}, + {"type": "expr", "file": "usr/lib/?libgirlib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirlib.dll.a"}, + {"type": "file", "file": "usr/share/gir-1.0/Meson-1.0.gir"} + ], + "skip_on_jobname": ["azure", "bionic", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/include/boost/version.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/include/boost/version.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/include/boost/version.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/include/boost/version.hpp" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +#define BOOST_VERSION 300 + +#error This is not a real version of boost diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/35 boost symlinks/boost/include/boost/version.hpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/35 boost symlinks/boost/include/boost/version.hpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/35 boost symlinks/boost/include/boost/version.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/35 boost symlinks/boost/include/boost/version.hpp" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +#define BOOST_VERSION 300 + +#error This is not a real version of boost diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/35 boost symlinks/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/35 boost symlinks/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/35 boost symlinks/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/35 boost symlinks/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +project('boosttestsymlinks', 'cpp') + +dep = dependency('boost', modules : ['regex', 'python'], required: false) + +assert(dep.found(), 'expected to find a fake version of boost') +assert(dep.version() == '0.3.0', 'expected to find version 0.3.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/35 boost symlinks/nativefile.ini.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/35 boost symlinks/nativefile.ini.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/35 boost symlinks/nativefile.ini.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/35 boost symlinks/nativefile.ini.in" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,2 @@ +[properties] +boost_root = '@MESON_TEST_ROOT@/boost' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/3 gmock/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/3 gmock/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/3 gmock/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/3 gmock/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/main.cpp" 2021-10-11 16:26:46.000000000 +0000 @@ -1,4 +1,6 @@ #include +#include +#include #include "mainWindow.h" #if QT_VERSION > 0x050000 @@ -16,6 +18,13 @@ Q_INIT_RESOURCE(stuff2); #endif QApplication app(argc, argv); + + auto *translator = new QTranslator; + if (translator->load(QLocale(), QT "embedded", "_", ":/lang")) + qApp->installTranslator(translator); + + qDebug() << QObject::tr("Translate me!"); + MainWindow *win = new MainWindow(); QImage qi(":/thing.png"); if(qi.width() != 640) { diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/manualinclude.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/manualinclude.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/manualinclude.cpp" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/manualinclude.cpp" 2021-11-02 19:58:07.000000000 +0000 @@ -24,4 +24,3 @@ } #include"manualinclude.moc" - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/meson.build" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -3,10 +3,13 @@ default_options : ['cpp_std=c++11']) qt5_modules = ['Widgets'] -foreach qt : ['qt4', 'qt5'] +qt6_modules = ['Widgets'] +foreach qt : ['qt4', 'qt5', 'qt6'] qt_modules = ['Core', 'Gui'] if qt == 'qt5' qt_modules += qt5_modules + elif qt == 'qt6' + qt_modules += qt6_modules endif # Test that invalid modules are indeed not found @@ -42,15 +45,21 @@ qtdep = dependency(qt, modules : qt_modules, main : true, private_headers: true, required : required, method : get_option('method')) if qtdep.found() qtmodule = import(qt) + assert(qtmodule.has_tools()) # The following has two resource files because having two in one target # requires you to do it properly or you get linker symbol clashes. prep = qtmodule.preprocess( - moc_headers : ['mainWindow.h'], # These need to be fed through the moc tool before use. - ui_files : 'mainWindow.ui', # XML files that need to be compiled with the uic tol. + moc_headers : ['mainWindow.h'], # These need to be fed through the moc tool before use. method : get_option('method') ) + # XML files that need to be compiled with the uic tol. + prep += qtmodule.compile_ui(sources : 'mainWindow.ui', method: get_option('method')) + + qtmodule.preprocess( + ui_files : 'mainWindow.ui', + method: get_option('method')) # Resource file(s) for rcc compiler extra_cpp_args = [] @@ -62,16 +71,26 @@ endif # Test that setting a unique name with a positional argument works - qtmodule.preprocess(qt + 'teststuff', qresources : files(['stuff.qrc', 'stuff2.qrc']), method : get_option('method')) + qtmodule.compile_resources( + name : qt + 'teststuff', + sources : files(['stuff.qrc', 'stuff2.qrc']), + method : get_option('method') + ) # Test that passing extra arguments to rcc works # qt4-rcc and qt5-rcc take different arguments, for example qt4: ['-compress', '3']; qt5: '--compress=3' qtmodule.preprocess(qt + 'testrccarg', qresources : files(['stuff.qrc', 'stuff2.qrc']), rcc_extra_arguments : '--compress=3', method : get_option('method')) + translations_cpp = qtmodule.compile_translations(qresource: qt+'_lang.qrc') + # unity builds suck and definitely cannot handle two qrc embeds in one compilation unit + unityproof_translations = static_library(qt+'unityproof_translations', translations_cpp) + + extra_cpp_args += '-DQT="@0@"'.format(qt) qexe = executable(qt + 'app', sources : ['main.cpp', 'mainWindow.cpp', # Sources that don't need preprocessing. prep, prep_rcc], dependencies : qtdep, + link_with: unityproof_translations, cpp_args: extra_cpp_args, gui_app : true) @@ -91,12 +110,18 @@ # The build system needs to include the cpp files from # headers but the user must manually include moc # files from sources. - manpreprocessed = qtmodule.preprocess( - moc_extra_arguments : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `moc_extra_arguments` + qtmodule.preprocess( + moc_extra_arguments : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` moc_sources : 'manualinclude.cpp', moc_headers : 'manualinclude.h', method : get_option('method')) + manpreprocessed = qtmodule.compile_moc( + extra_args : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` + sources : 'manualinclude.cpp', + headers : 'manualinclude.h', + method : get_option('method')) + qtmaninclude = executable(qt + 'maninclude', sources : ['manualinclude.cpp', manpreprocessed], dependencies : qtcore) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/qt4embedded_fr.ts" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/qt4embedded_fr.ts" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/qt4embedded_fr.ts" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/qt4embedded_fr.ts" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,12 @@ + + + + + QObject + + + Translate me! + Traduisez moi! + + + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/qt4_lang.qrc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/qt4_lang.qrc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/qt4_lang.qrc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/qt4_lang.qrc" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,6 @@ + + + qt4embedded_fr.qm + + + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/qt5embedded_fr.ts" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/qt5embedded_fr.ts" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/qt5embedded_fr.ts" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/qt5embedded_fr.ts" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,12 @@ + + + + + QObject + + + Translate me! + Traduisez moi! + + + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/qt5_lang.qrc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/qt5_lang.qrc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/qt5_lang.qrc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/qt5_lang.qrc" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,6 @@ + + + qt5embedded_fr.qm + + + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/4 qt/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/4 qt/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,12 @@ +{ + "matrix": { + "options": { + "method": [ + { "val": "config-tool", "skip_on_jobname": ["fedora", "opensuse"] }, + { "val": "qmake", "skip_on_jobname": ["fedora", "opensuse"] }, + { "val": "pkg-config" } + ] + } + }, + "skip_on_jobname": ["cygwin", "msys2", "azure"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/5 protocol buffers/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/5 protocol buffers/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/5 protocol buffers/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/5 protocol buffers/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/data3/test.desktop.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/data3/test.desktop.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/data3/test.desktop.in" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/data3/test.desktop.in" 2021-11-02 19:58:07.000000000 +0000 @@ -3,4 +3,3 @@ GenericName=Application Comment=Test Application Type=Application - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/meson.build" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/meson.build" 2021-08-18 11:22:25.000000000 +0000 @@ -27,4 +27,32 @@ install_dir: join_paths(get_option('datadir'), 'applications') ) +# Regression test when passing File object as input and '@BASENAME@' as output +# in multiple i18n.merge_file() calls. It used to make target name collision. +# https://github.com/mesonbuild/meson/issues/9022 +i18n.merge_file( + input: configure_file( + input: 'test5.desktop.in.in', + output: '@BASENAME@', + configuration: { 'NAME': 'Application' }, + ), + output: '@BASENAME@', + type: 'desktop', + po_dir: '../po', + install: true, + install_dir: join_paths(get_option('datadir'), 'applications') +) +i18n.merge_file( + input: configure_file( + input: 'test6.desktop.in.in', + output: '@BASENAME@', + configuration: { 'NAME': 'Application' }, + ), + output: '@BASENAME@', + type: 'desktop', + po_dir: '../po', + install: true, + install_dir: join_paths(get_option('datadir'), 'applications') +) + subdir('data3') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/test2.desktop.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/test2.desktop.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/test2.desktop.in" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/test2.desktop.in" 2021-11-02 19:58:07.000000000 +0000 @@ -3,4 +3,3 @@ GenericName=Application Comment=Test Application Type=Application - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/test5.desktop.in.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/test5.desktop.in.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/test5.desktop.in.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/test5.desktop.in.in" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,5 @@ +[Desktop Entry] +Name=Test 2 +GenericName=@NAME@ +Comment=Test Application +Type=Application diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/test6.desktop.in.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/test6.desktop.in.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/test6.desktop.in.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/test6.desktop.in.in" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,5 @@ +[Desktop Entry] +Name=Test 2 +GenericName=@NAME@ +Comment=Test Application +Type=Application diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/test.desktop.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/test.desktop.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data/test.desktop.in" 2016-12-13 21:40:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data/test.desktop.in" 2021-11-02 19:58:07.000000000 +0000 @@ -3,4 +3,3 @@ GenericName=Application Comment=Test Application Type=Application - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data2/test.desktop.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data2/test.desktop.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/data2/test.desktop.in" 2019-05-02 18:59:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/data2/test.desktop.in" 2021-11-02 19:58:07.000000000 +0000 @@ -3,4 +3,3 @@ GenericName=Application Description=Test Application Type=Application - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/installed_files.txt" 2019-05-02 18:59:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -usr/bin/intlprog?exe -usr/share/locale/de/LC_MESSAGES/intltest.mo -usr/share/locale/fi/LC_MESSAGES/intltest.mo -usr/share/locale/ru/LC_MESSAGES/intltest.mo -usr/share/applications/something.desktop -usr/share/applications/test.desktop -usr/share/applications/test.plugin -usr/share/applications/test2.desktop -usr/share/applications/test3.desktop -usr/share/applications/test4.desktop diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/meson.build" 2020-01-23 21:41:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -10,8 +10,9 @@ error('MESON_SKIP_TEST xgettext not found.') endif -if not meson.get_compiler('c').has_header('libintl.h') - error('MESON_SKIP_TEST libintl.h not found.') +intl = dependency('intl', required: false, static: get_option('static')) +if not intl.found() + error('MESON_SKIP_TEST libintl/gettext functions not found.') endif i18n = import('i18n') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/meson_options.txt" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +option('static', type : 'boolean', value : false, description : 'build statically linked binaries') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/po/LINGUAS" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/po/LINGUAS" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/po/LINGUAS" 2019-05-02 18:59:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/po/LINGUAS" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,3 @@ de fi ru - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/src/meson.build" 2016-09-04 20:08:25.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/src/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -1,2 +1,2 @@ executable('intlprog', 'intlmain.c', install : true, - dependencies : meson.get_compiler('c').find_library('intl', required : false)) + dependencies : intl) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/6 gettext/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/6 gettext/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,25 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/intlprog"}, + {"type": "file", "file": "usr/share/locale/de/LC_MESSAGES/intltest.mo"}, + {"type": "file", "file": "usr/share/locale/fi/LC_MESSAGES/intltest.mo"}, + {"type": "file", "file": "usr/share/locale/ru/LC_MESSAGES/intltest.mo"}, + {"type": "file", "file": "usr/share/applications/something.desktop"}, + {"type": "file", "file": "usr/share/applications/test.desktop"}, + {"type": "file", "file": "usr/share/applications/test.plugin"}, + {"type": "file", "file": "usr/share/applications/test2.desktop"}, + {"type": "file", "file": "usr/share/applications/test3.desktop"}, + {"type": "file", "file": "usr/share/applications/test4.desktop"}, + {"type": "file", "file": "usr/share/applications/test5.desktop"}, + {"type": "file", "file": "usr/share/applications/test6.desktop"} + ], + "matrix": { + "options": { + "static": [ + { "val": "true" }, + { "val": "false" } + ] + } + }, + "skip_on_jobname": ["azure", "cygwin"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml" 2022-01-17 10:50:38.000000000 +0000 @@ -6,5 +6,9 @@ + + + + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gdbus/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gdbus/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gdbus/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gdbus/meson.build" 2022-02-14 19:03:13.000000000 +0000 @@ -6,6 +6,32 @@ ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true'] ], ) + +# check that empty annotations work +gdbus_src2 = gnome.gdbus_codegen( + 'generated-gdbus-no-docbook2', + 'data/com.example.Sample.xml', + interface_prefix : 'com.example.', + namespace : 'Sample', + annotations : [], +) + +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') @@ -15,7 +41,8 @@ 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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/genmarshal/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/genmarshal/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/genmarshal/main.c" 2016-10-03 18:54:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/genmarshal/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -#include -#include -#include -#include"marshaller.h" - -static int singleton = 42; - -void foo(gpointer user_data, gpointer data) { - if (user_data != &singleton) { - fprintf(stderr, "Invoked foo function was passed incorrect user data.\n"); - exit(1); - } -} - -void bar(gpointer user_data, gint param1, gpointer data) { - if (param1 != singleton) { - fprintf(stderr, "Invoked bar function was passed incorrect param1, but %d.\n", param1); - exit(2); - } - if (user_data != &singleton) { - fprintf(stderr, "Invoked bar function was passed incorrect user data.\n"); - exit(3); - } -} - -gfloat baz(gpointer user_data, gboolean param1, guchar param2, gpointer data) { - if (param1 != TRUE) { - fprintf(stderr, "Invoked baz function was passed incorrect param1.\n"); - exit(4); - } - if (param2 != singleton) { - fprintf(stderr, "Invoked baz function was passed incorrect param2.\n"); - exit(5); - } - if (user_data != &singleton) { - fprintf(stderr, "Invoked baz function was passed incorrect user data.\n"); - exit(6); - } - return (gfloat)param2; -} - -int main(int argc, char **argv) { - GClosure *cc_foo, *cc_bar, *cc_baz; - GValue return_value = G_VALUE_INIT; - GValue param_values[3] = {G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT}; - - fprintf(stderr, "Invoking foo function.\n"); - cc_foo = g_cclosure_new(G_CALLBACK(foo), NULL, NULL); - g_closure_set_marshal(cc_foo, g_cclosure_user_marshal_VOID__VOID); - g_value_init(¶m_values[0], G_TYPE_POINTER); - g_value_set_pointer(¶m_values[0], &singleton); - g_closure_invoke(cc_foo, &return_value, 1, param_values, NULL); - if (G_VALUE_TYPE(&return_value) != G_TYPE_INVALID) { - fprintf(stderr, "Invoked foo function did not return empty value, but %s.\n", - G_VALUE_TYPE_NAME(&return_value)); - return 7; - } - g_value_unset(¶m_values[0]); - g_value_unset(&return_value); - g_closure_unref(cc_foo); - - fprintf(stderr, "Invoking bar function.\n"); - cc_bar = g_cclosure_new(G_CALLBACK(bar), NULL, NULL); - g_closure_set_marshal(cc_bar, g_cclosure_user_marshal_VOID__INT); - g_value_init(¶m_values[0], G_TYPE_POINTER); - g_value_set_pointer(¶m_values[0], &singleton); - g_value_init(¶m_values[1], G_TYPE_INT); - g_value_set_int(¶m_values[1], 42); - g_closure_invoke(cc_bar, &return_value, 2, param_values, NULL); - if (G_VALUE_TYPE(&return_value) != G_TYPE_INVALID) { - fprintf(stderr, "Invoked bar function did not return empty value.\n"); - return 8; - } - g_value_unset(¶m_values[0]); - g_value_unset(¶m_values[1]); - g_value_unset(&return_value); - g_closure_unref(cc_bar); - - fprintf(stderr, "Invoking baz function.\n"); - cc_baz = g_cclosure_new(G_CALLBACK(baz), NULL, NULL); - g_closure_set_marshal(cc_baz, g_cclosure_user_marshal_FLOAT__BOOLEAN_UCHAR); - g_value_init(¶m_values[0], G_TYPE_POINTER); - g_value_set_pointer(¶m_values[0], &singleton); - g_value_init(¶m_values[1], G_TYPE_BOOLEAN); - g_value_set_boolean(¶m_values[1], TRUE); - g_value_init(¶m_values[2], G_TYPE_UCHAR); - g_value_set_uchar(¶m_values[2], 42); - g_value_init(&return_value, G_TYPE_FLOAT); - g_closure_invoke(cc_baz, &return_value, 3, param_values, NULL); - if (g_value_get_float(&return_value) != 42.0f) { - fprintf(stderr, "Invoked baz function did not return expected value.\n"); - return 9; - } - g_value_unset(¶m_values[0]); - g_value_unset(¶m_values[1]); - g_value_unset(¶m_values[2]); - g_value_unset(&return_value); - g_closure_unref(cc_baz); - - fprintf(stderr, "All ok.\n"); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/genmarshal/main.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/genmarshal/main.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/genmarshal/main.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/genmarshal/main.c.in" 2022-01-17 10:50:38.000000000 +0000 @@ -0,0 +1,102 @@ +#include +#include +#include +#include @MARSHALLER_HEADER@ + +static int singleton = 42; + +void foo(gpointer user_data, gpointer data) { + if (user_data != &singleton) { + fprintf(stderr, "Invoked foo function was passed incorrect user data.\n"); + exit(1); + } +} + +void bar(gpointer user_data, gint param1, gpointer data) { + if (param1 != singleton) { + fprintf(stderr, "Invoked bar function was passed incorrect param1, but %d.\n", param1); + exit(2); + } + if (user_data != &singleton) { + fprintf(stderr, "Invoked bar function was passed incorrect user data.\n"); + exit(3); + } +} + +gfloat baz(gpointer user_data, gboolean param1, guchar param2, gpointer data) { + if (param1 != TRUE) { + fprintf(stderr, "Invoked baz function was passed incorrect param1.\n"); + exit(4); + } + if (param2 != singleton) { + fprintf(stderr, "Invoked baz function was passed incorrect param2.\n"); + exit(5); + } + if (user_data != &singleton) { + fprintf(stderr, "Invoked baz function was passed incorrect user data.\n"); + exit(6); + } + return (gfloat)param2; +} + +int main(int argc, char **argv) { + GClosure *cc_foo, *cc_bar, *cc_baz; + GValue return_value = G_VALUE_INIT; + GValue param_values[3] = {G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT}; + + fprintf(stderr, "Invoking foo function.\n"); + cc_foo = g_cclosure_new(G_CALLBACK(foo), NULL, NULL); + g_closure_set_marshal(cc_foo, g_cclosure_user_marshal_VOID__VOID); + g_value_init(¶m_values[0], G_TYPE_POINTER); + g_value_set_pointer(¶m_values[0], &singleton); + g_closure_invoke(cc_foo, &return_value, 1, param_values, NULL); + if (G_VALUE_TYPE(&return_value) != G_TYPE_INVALID) { + fprintf(stderr, "Invoked foo function did not return empty value, but %s.\n", + G_VALUE_TYPE_NAME(&return_value)); + return 7; + } + g_value_unset(¶m_values[0]); + g_value_unset(&return_value); + g_closure_unref(cc_foo); + + fprintf(stderr, "Invoking bar function.\n"); + cc_bar = g_cclosure_new(G_CALLBACK(bar), NULL, NULL); + g_closure_set_marshal(cc_bar, g_cclosure_user_marshal_VOID__INT); + g_value_init(¶m_values[0], G_TYPE_POINTER); + g_value_set_pointer(¶m_values[0], &singleton); + g_value_init(¶m_values[1], G_TYPE_INT); + g_value_set_int(¶m_values[1], 42); + g_closure_invoke(cc_bar, &return_value, 2, param_values, NULL); + if (G_VALUE_TYPE(&return_value) != G_TYPE_INVALID) { + fprintf(stderr, "Invoked bar function did not return empty value.\n"); + return 8; + } + g_value_unset(¶m_values[0]); + g_value_unset(¶m_values[1]); + g_value_unset(&return_value); + g_closure_unref(cc_bar); + + fprintf(stderr, "Invoking baz function.\n"); + cc_baz = g_cclosure_new(G_CALLBACK(baz), NULL, NULL); + g_closure_set_marshal(cc_baz, g_cclosure_user_marshal_FLOAT__BOOLEAN_UCHAR); + g_value_init(¶m_values[0], G_TYPE_POINTER); + g_value_set_pointer(¶m_values[0], &singleton); + g_value_init(¶m_values[1], G_TYPE_BOOLEAN); + g_value_set_boolean(¶m_values[1], TRUE); + g_value_init(¶m_values[2], G_TYPE_UCHAR); + g_value_set_uchar(¶m_values[2], 42); + g_value_init(&return_value, G_TYPE_FLOAT); + g_closure_invoke(cc_baz, &return_value, 3, param_values, NULL); + if (g_value_get_float(&return_value) != 42.0f) { + fprintf(stderr, "Invoked baz function did not return expected value.\n"); + return 9; + } + g_value_unset(¶m_values[0]); + g_value_unset(¶m_values[1]); + g_value_unset(¶m_values[2]); + g_value_unset(&return_value); + g_closure_unref(cc_baz); + + fprintf(stderr, "All ok.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/genmarshal/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/genmarshal/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/genmarshal/meson.build" 2017-07-25 15:40:53.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/genmarshal/meson.build" 2022-01-17 10:50:38.000000000 +0000 @@ -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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/copy.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/copy.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/copy.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/copy.py" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021 Intel Corproation + +import argparse +import shutil + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('src') + parser.add_argument('dest') + args = parser.parse_args() + + shutil.copy(args.src, args.dest) + + +if __name__ == "__main__": + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,124 @@ +#include "dep3.h" + +struct _MesonDep3 +{ + GObject parent_instance; + + gchar *msg; +}; + +G_DEFINE_TYPE (MesonDep3, meson_dep3, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_dep3_new: + * @msg: The message to set. + * + * Allocates a new #MesonDep3. + * + * Returns: (transfer full): a #MesonDep3. + */ +MesonDep3 * +meson_dep3_new (const gchar *msg) +{ + g_return_val_if_fail (msg != NULL, NULL); + + return g_object_new (MESON_TYPE_DEP3, + "message", msg, + NULL); +} + +static void +meson_dep3_finalize (GObject *object) +{ + MesonDep3 *self = (MesonDep3 *)object; + + g_clear_pointer (&self->msg, g_free); + + G_OBJECT_CLASS (meson_dep3_parent_class)->finalize (object); +} + +static void +meson_dep3_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonDep3 *self = MESON_DEP3 (object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, self->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep3_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonDep3 *self = MESON_DEP3 (object); + + switch (prop_id) + { + case PROP_MSG: + self->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep3_class_init (MesonDep3Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_dep3_finalize; + object_class->get_property = meson_dep3_get_property; + object_class->set_property = meson_dep3_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_dep3_init (MesonDep3 *self) +{ +} + +/** + * meson_dep3_return_message: + * @self: a #MesonDep3. + * + * Returns the message. + * + * Returns: (transfer none): a const gchar* + */ +const gchar* +meson_dep3_return_message (MesonDep3 *self) +{ + g_return_val_if_fail (MESON_IS_DEP3 (self), NULL); + + return (const gchar*) self->msg; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,21 @@ +#ifndef MESON_DEP3_H +#define MESON_DEP3_H + +#if !defined (MESON_TEST) +#error "MESON_TEST not defined." +#endif + +#include + +G_BEGIN_DECLS + +#define MESON_TYPE_DEP3 (meson_dep3_get_type()) + +G_DECLARE_FINAL_TYPE (MesonDep3, meson_dep3, MESON, DEP3, GObject) + +MesonDep3 *meson_dep3_new (const gchar *msg); +const gchar *meson_dep3_return_message (MesonDep3 *self); + +G_END_DECLS + +#endif /* MESON_DEP3_H */ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,22 @@ +dep3sources = ['dep3.c', 'dep3.h'] + +dep3lib = shared_library( + 'dep3lib', + sources : dep3sources, + dependencies : gobj, + install : true +) + +dep3gir = gnome.generate_gir( + dep3lib, + sources : dep3sources, + nsversion : '1.0', + namespace : 'MesonDep3', + symbol_prefix : 'meson', + identifier_prefix : 'Meson', + includes : ['GObject-2.0'], + install : true +) + +dep3_dep = declare_dependency(link_with : dep3lib, + sources : [dep3gir]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/dep1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/dep1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/dep1/meson.build" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/dep1/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -1,4 +1,5 @@ subdir('dep2') +subdir('dep3') dep1sources = ['dep1.c', 'dep1.h'] @@ -20,11 +21,11 @@ symbol_prefix : 'meson', identifier_prefix : 'Meson', header: 'dep1.h', - includes : ['GObject-2.0', 'MesonDep2-1.0'], + includes : ['GObject-2.0', 'MesonDep2-1.0', dep3gir[0]], dependencies : [dep2_dep], install : true ) dep1_dep = declare_dependency(link_with : dep1lib, - dependencies : [dep2_dep], + dependencies : [dep2_dep, dep3_dep], sources : [dep1gir]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/gir/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/gir/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -3,6 +3,14 @@ libsources = ['meson-sample.c', 'meson-sample.h'] lib2sources = ['meson-sample2.c', 'meson-sample2.h'] +gen_source = custom_target( + 'meson_smaple3.h', + input : 'meson-sample.h', + output : 'meson-sample3.h', + command : [find_program('copy.py'), '@INPUT@', '@OUTPUT@'], + build_by_default : false, # this will force a race condition if one exists +) + girlib = shared_library( 'gir_lib', sources : libsources, @@ -28,7 +36,7 @@ gnome.generate_gir( girlib, girlib2, - sources : libsources + lib2sources, + sources : [libsources, lib2sources, gen_source], nsversion : '1.0', namespace : 'Meson', symbol_prefix : 'meson', @@ -38,14 +46,10 @@ dependencies : [[fake_dep, dep1_dep]], install : true, build_by_default : true, - # Test that unknown kwargs do not crash the parser. - # Unknown kwargs will eventually become a hard error. - # Once that happens remove this. - unknown_kwarg : true, ) test('gobject introspection/c', girexe) -gir_paths = ':'.join([girlib.outdir(), dep1lib.outdir(), dep2lib.outdir()]) +gir_paths = ':'.join([girlib.outdir(), dep1lib.outdir(), dep2lib.outdir(), dep3lib.outdir()]) envdata = environment() envdata.append('GI_TYPELIB_PATH', gir_paths, separator : ':') envdata.append('LD_LIBRARY_PATH', gir_paths) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -usr/include/enums.h -usr/include/enums2.h -usr/include/enums3.h -usr/include/enums5.h -usr/include/marshaller.h -usr/lib/?libgir_lib.so -?cygwin:usr/lib/libgir_lib.dll.a -usr/lib/?libgir_lib2.so -?cygwin:usr/lib/libgir_lib2.dll.a -usr/lib/?libdep1lib.so -?cygwin:usr/lib/libdep1lib.dll.a -usr/lib/?libdep2lib.so -?cygwin:usr/lib/libdep2lib.dll.a -usr/lib/girepository-1.0/Meson-1.0.typelib -usr/lib/girepository-1.0/MesonDep1-1.0.typelib -usr/lib/girepository-1.0/MesonDep2-1.0.typelib -usr/share/gir-1.0/Meson-1.0.gir -usr/share/gir-1.0/MesonDep1-1.0.gir -usr/share/gir-1.0/MesonDep2-1.0.gir -usr/share/glib-2.0/schemas/com.github.meson.gschema.xml -usr/share/simple-resources.gresource -usr/include/enums6.h -usr/include/simple-resources.h -usr/include/generated-gdbus.h diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/meson.build" 2020-01-23 21:41:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -12,7 +12,7 @@ python3 = import('python3') py3 = python3.find_python() -if run_command(py3, '-c', 'import gi;').returncode() != 0 +if run_command(py3, '-c', 'import gi;', check: false).returncode() != 0 error('MESON_SKIP_TEST python3-gi not found') endif @@ -33,7 +33,7 @@ ''' pretend_glib_old = false -res = run_command(py3, '-c', pycode) +res = run_command(py3, '-c', pycode, check: false) if res.returncode() == 0 pretend_glib_old = true endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/mkenums/enums2.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/mkenums/enums2.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/mkenums/enums2.c.in" 2016-10-03 18:54:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/mkenums/enums2.c.in" 2021-04-01 21:13:00.000000000 +0000 @@ -13,9 +13,9 @@ /*** BEGIN value-header ***/ GType @enum_name@_get_type(void) { - static volatile gsize g_define_type_id__volatile = 0; + static gsize static_g_define_type_id = 0; - if(g_once_init_enter(&g_define_type_id__volatile)) { + if(g_once_init_enter(&static_g_define_type_id)) { static const G@Type@Value values [] = { /*** END value-header ***/ @@ -29,10 +29,10 @@ GType g_define_type_id = g_@type@_register_static(g_intern_static_string("@EnumName@"), values); - g_once_init_leave(&g_define_type_id__volatile, g_define_type_id); + g_once_init_leave(&static_g_define_type_id, g_define_type_id); } - return g_define_type_id__volatile; + return static_g_define_type_id; } /*** END value-tail ***/ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/mkenums/enums.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/mkenums/enums.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/mkenums/enums.c.in" 2016-10-03 18:54:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/mkenums/enums.c.in" 2021-04-01 21:13:00.000000000 +0000 @@ -13,9 +13,9 @@ /*** BEGIN value-header ***/ GType @enum_name@_get_type(void) { - static volatile gsize g_define_type_id__volatile = 0; + static gsize static_g_define_type_id = 0; - if(g_once_init_enter(&g_define_type_id__volatile)) { + if(g_once_init_enter(&static_g_define_type_id)) { static const G@Type@Value values [] = { /*** END value-header ***/ @@ -29,10 +29,10 @@ GType g_define_type_id = g_@type@_register_static(g_intern_static_string("@EnumName@"), values); - g_once_init_leave(&g_define_type_id__volatile, g_define_type_id); + g_once_init_leave(&static_g_define_type_id, g_define_type_id); } - return g_define_type_id__volatile; + return static_g_define_type_id; } /*** END value-tail ***/ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/mkenums/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/mkenums/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/mkenums/meson.build" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/mkenums/meson.build" 2021-11-02 19:58:13.000000000 +0000 @@ -34,9 +34,9 @@ sources : 'meson-sample.h', depends : [enums_h1, enums_h2], c_template : 'enums2.c.in', - ftail : '/* trailing source file info */', - install_header : true, - install_dir : get_option('includedir')) + ftail : '/* trailing source file info */') +# explicitly don't set install_dir here, for bug testing +# See https://github.com/mesonbuild/meson/issues/9472 conf = configuration_data() conf.set('ENUM_FILE', 'enums2.h') @@ -89,9 +89,9 @@ vhead : ''' GType @enum_name@_get_type(void) { - static volatile gsize g_define_type_id__volatile = 0; + static gsize static_g_define_type_id = 0; - if(g_once_init_enter(&g_define_type_id__volatile)) { + if(g_once_init_enter(&static_g_define_type_id)) { static const G@Type@Value values [] = { ''', vprod : ''' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },''', @@ -100,10 +100,10 @@ GType g_define_type_id = g_@type@_register_static(g_intern_static_string("@EnumName@"), values); - g_once_init_leave(&g_define_type_id__volatile, g_define_type_id); + g_once_init_leave(&static_g_define_type_id, g_define_type_id); } - return g_define_type_id__volatile; + return static_g_define_type_id; } ''') @@ -126,6 +126,14 @@ install_header : true, decorator : 'MESON_EXPORT', header_prefix : '#include "meson-decls.h"') + +conf = configuration_data() +conf.set('ENUM_FILE', 'enums5.h') +main = configure_file( + input : 'main.c', + output : 'main5.c', + configuration : conf) + enumexe5 = executable('enumprog5', main, enums5, dependencies : gobj) # Generate template then use as input to mkenums diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/resources/resources.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/resources/resources.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/resources/resources.py" 2016-12-13 21:40:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/resources/resources.py" 2021-11-02 19:58:07.000000000 +0000 @@ -7,4 +7,4 @@ Gio.Resource._register(res) data = Gio.resources_lookup_data('/com/example/myprog/res1.txt', Gio.ResourceLookupFlags.NONE) - assert(data.get_data() == b'This is a resource.\n') + assert data.get_data() == b'This is a resource.\n' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/7 gnome/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/7 gnome/test.json" 2022-01-17 10:50:38.000000000 +0000 @@ -0,0 +1,38 @@ +{ + "installed": [ + {"type": "file", "file": "usr/include/enums.h"}, + {"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/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"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgir_lib2.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep1lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep1lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep2lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep2lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep3lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep3lib.dll.a"}, + {"type": "file", "file": "usr/lib/girepository-1.0/Meson-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep1-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep2-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep3-1.0.typelib"}, + {"type": "file", "file": "usr/share/gir-1.0/Meson-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep1-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep2-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep3-1.0.gir"}, + {"type": "file", "file": "usr/share/glib-2.0/schemas/com.github.meson.gschema.xml"}, + {"type": "file", "file": "usr/share/simple-resources.gresource"}, + {"type": "file", "file": "usr/include/enums6.h"}, + {"type": "file", "file": "usr/include/simple-resources.h"}, + {"type": "file", "file": "usr/include/generated-gdbus.h"} + ], + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/lexer.l" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/lexer.l" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/lexer.l" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/lexer.l" 2021-11-02 19:58:07.000000000 +0000 @@ -1,8 +1,13 @@ %{ #include #include "parser.tab.h" + +extern int yylex(void); +extern int yyerror(); %} -%% +%option noyywrap nounput noinput + +%% ("true"|"false") {return BOOLEAN;} . { yyerror(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/meson.build" 2020-01-07 21:14:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -28,6 +28,9 @@ pfiles = pgen.process('parser.y') e = executable('pgen', 'prog.c', -lfiles, pfiles) + lfiles, + pfiles, + override_options: 'unity=off') -test('parsertest', e) +test('parsertest', e, + args: [meson.current_source_dir() / 'testfile']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/parser.y" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/parser.y" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/parser.y" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/parser.y" 2021-04-01 21:13:00.000000000 +0000 @@ -1,3 +1,8 @@ +%{ +extern int yylex(void); +extern int yyerror(); +%} + %token BOOLEAN %% diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/prog.c" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/prog.c" 2021-11-02 19:58:07.000000000 +0000 @@ -9,25 +9,15 @@ extern int yyparse(); int main(int argc, char **argv) { - /* int input; if(argc != 2) { - printf("%s "); + printf("%s \n", argv[0]); return 1; } input = open(argv[1], O_RDONLY); dup2(input, STDIN_FILENO); close(input); return yyparse(); - */ - /* We really should test that the - * generated parser works with input - * but it froze and I don't want to waste - * time debugging that. For this test what - * we care about is that it compiles and links. - */ - void* __attribute__((unused)) dummy = (void*)yyparse; - return 0; } int yywrap(void) { diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/testfile" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/testfile" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/testfile" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/testfile" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +true diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/frameworks/8 flex/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/frameworks/8 flex/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "cygwin"] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/1 basic/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/1 basic/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/1 basic/installed_files.txt" 2017-02-06 21:49:56.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/1 basic/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/bin/myprog.jar diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/1 basic/meson.build" 2020-01-07 21:11:01.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/1 basic/meson.build" 2021-10-23 16:51:52.000000000 +0000 @@ -5,3 +5,7 @@ install : true, install_dir : get_option('bindir')) test('mytest', javaprog) + +jc = meson.get_compiler('java') +message(jc.get_id()) +message(jc.get_linker_id()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/1 basic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/1 basic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/1 basic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/1 basic/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/myprog.jar"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/2 subdir/sub/com/mesonbuild/TextPrinter.java" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/2 subdir/sub/com/mesonbuild/TextPrinter.java" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/2 subdir/sub/com/mesonbuild/TextPrinter.java" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/2 subdir/sub/com/mesonbuild/TextPrinter.java" 2021-11-02 19:58:07.000000000 +0000 @@ -3,11 +3,11 @@ class TextPrinter { private String msg; - + TextPrinter(String s) { msg = s; } - + public void print() { System.out.println(msg); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/3 args/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/3 args/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/3 args/meson.build" 2020-01-07 21:11:01.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/3 args/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,9 +1,8 @@ project('simplejava', 'java') -add_project_arguments('-target', '1.6', language : 'java') +add_project_arguments('-target', '1.7', language : 'java') javaprog = jar('myprog', 'com/mesonbuild/Simple.java', main_class : 'com.mesonbuild.Simple', - java_args : ['-source', '1.6']) + java_args : ['-source', '1.7']) test('mytest', javaprog) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/5 includedirs/com/mesonbuild/TextPrinter.java" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/5 includedirs/com/mesonbuild/TextPrinter.java" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/5 includedirs/com/mesonbuild/TextPrinter.java" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/5 includedirs/com/mesonbuild/TextPrinter.java" 2021-11-02 19:58:07.000000000 +0000 @@ -3,11 +3,11 @@ class TextPrinter { private String msg; - + TextPrinter(String s) { msg = s; } - + public void print() { System.out.println(msg); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/6 codegen/com/mesonbuild/TextPrinter.java" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/6 codegen/com/mesonbuild/TextPrinter.java" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/6 codegen/com/mesonbuild/TextPrinter.java" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/6 codegen/com/mesonbuild/TextPrinter.java" 2021-11-02 19:58:07.000000000 +0000 @@ -3,11 +3,11 @@ class TextPrinter { private String msg; - + TextPrinter(String s) { msg = s; } - + public void print() { System.out.println(msg); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/lib/com_mesonbuild_JdkTest.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/lib/com_mesonbuild_JdkTest.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/lib/com_mesonbuild_JdkTest.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/lib/com_mesonbuild_JdkTest.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#include + +#include "com_mesonbuild_JdkTest.h" + +JNIEXPORT jint JNICALL Java_com_mesonbuild_JdkTest_jdk_1test + (JNIEnv *env, jclass clazz) +{ + return (jint)0xdeadbeef; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/lib/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,18 @@ +sources = [ + files( + 'native.c', + 'com_mesonbuild_JdkTest.c', + ), + native_header +] + +jdkjava = shared_module( + 'jdkjava', + sources, + dependencies : [jdk], + include_directories : [native_header_includes] +) + +jdkjava_dep = declare_dependency( + link_with : jdkjava, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/lib/native.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/lib/native.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/lib/native.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/lib/native.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#include + +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM *vm, void *reserved) +{ + return JNI_VERSION_1_8; +} + +JNIEXPORT void JNICALL +JNI_OnUnload(JavaVM *vm, void *reserved) +{} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,21 @@ +project('jdkjava', ['c', 'java']) + +if build_machine.system() == 'cygwin' + error('MESON_SKIP_TEST: cygwin test failures') +endif + +if build_machine.system() == 'windows' and build_machine.cpu_family() == 'x86' + error('MESON_SKIP_TEST: failing builds on 32bit Windows because a 32bit JDK isn not available in the Azure Pipelines Windows images') +endif + +fs = import('fs') +javamod = import('java') + +java = find_program('java') + +jdk = dependency('jdk', version : '>=1.8') + +# generate native headers +subdir('src/com/mesonbuild') +subdir('lib') +subdir('src') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/src/com/mesonbuild/JdkTest.java" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/src/com/mesonbuild/JdkTest.java" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/src/com/mesonbuild/JdkTest.java" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/src/com/mesonbuild/JdkTest.java" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,15 @@ +package com.mesonbuild; + +public final class JdkTest { + private static native int jdk_test(); + + public static void main(String[] args) { + if (jdk_test() != 0xdeadbeef) { + throw new RuntimeException("jdk_test() did not return 0"); + } + } + + static { + System.loadLibrary("jdkjava"); + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/src/com/mesonbuild/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/src/com/mesonbuild/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/src/com/mesonbuild/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/src/com/mesonbuild/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,2 @@ +native_header = javamod.generate_native_header('JdkTest.java', package: 'com.mesonbuild') +native_header_includes = include_directories('.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/java/9 jdk/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/java/9 jdk/src/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +jdkjar = jar( + 'jdkjar', + 'com' / 'mesonbuild' / 'JdkTest.java', + main_class : 'com.mesonbuild.JdkTest', +) + +test( + 'jdktest', + java, + args: [ + '-Djava.library.path=@0@'.format(fs.parent(jdkjava.full_path())), + '-jar', + jdkjar, + ], + protocol : 'exitcode', + depends : [jdkjava], +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/1 basic/.config" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/1 basic/.config" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/1 basic/.config" 2019-04-17 08:08:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/1 basic/.config" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -CONFIG_VAL1=y -# CONFIG_VAL2 is not set -CONFIG_VAL_VAL=4 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/1 basic/meson.build" 2020-01-07 21:10:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/1 basic/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -project('kconfig basic test') - -k = import('unstable-kconfig') -conf = k.load('.config') - -if not conf.has_key('CONFIG_VAL1') - error('Expected CONFIG_VAL1 to be set, but it wasn\'t') -endif - -if conf.has_key('CONFIG_VAL2') - error('Expected CONFIG_VAL2 not be set, but it was') -endif - -if conf.get('CONFIG_VAL_VAL').to_int() != 4 - error('Expected CONFIG_VAL_VAL to be 4') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/2 subdir/.config" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/2 subdir/.config" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/2 subdir/.config" 2019-04-17 08:08:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/2 subdir/.config" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -CONFIG_IS_SET=y -# CONFIG_NOT_IS_SET is not set diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/2 subdir/dir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/2 subdir/dir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/2 subdir/dir/meson.build" 2019-04-17 08:08:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/2 subdir/dir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -k = import('unstable-kconfig') - -conf = k.load(meson.source_root() / '.config') - -if not conf.has_key('CONFIG_IS_SET') - error('Expected CONFIG_IS_SET to be set, but it wasn\'t') -endif - -if conf.has_key('CONFIG_NOT_IS_SET') - error('Expected CONFIG_NOT_IS_SET not be set, but it was') -endif - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/2 subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/2 subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/2 subdir/meson.build" 2020-01-07 21:10:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/2 subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('kconfig subdir test') - -# Test into sub directory -subdir('dir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/3 load_config files/dir/config" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/3 load_config files/dir/config" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/3 load_config files/dir/config" 2019-04-17 08:08:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/3 load_config files/dir/config" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -CONFIG_IS_SET=y -# CONFIG_NOT_IS_SET is not set diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/3 load_config files/dir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/3 load_config files/dir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/3 load_config files/dir/meson.build" 2019-04-17 08:08:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/3 load_config files/dir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -k = import('unstable-kconfig') - -conf = k.load(files('config')) - -if not conf.has_key('CONFIG_IS_SET') - error('Expected CONFIG_IS_SET to be set, but it wasn\'t') -endif - -if conf.has_key('CONFIG_NOT_IS_SET') - error('Expected CONFIG_NOT_IS_SET not be set, but it was') -endif - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/3 load_config files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/3 load_config files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/3 load_config files/meson.build" 2020-01-07 21:10:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/3 load_config files/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('kconfig subdir test') - -# Test into sub directory -subdir('dir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/4 load_config builddir/config" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/4 load_config builddir/config" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/4 load_config builddir/config" 2019-04-17 08:08:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/4 load_config builddir/config" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -CONFIG_IS_SET=y -# CONFIG_NOT_IS_SET is not set diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/4 load_config builddir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/4 load_config builddir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/kconfig/4 load_config builddir/meson.build" 2020-01-07 21:10:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/kconfig/4 load_config builddir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('kconfig builddir test') - -k = import('unstable-kconfig') - -out_conf = configure_file(input: 'config', output: 'out-config', copy: true) -conf = k.load(out_conf) - -if not conf.has_key('CONFIG_IS_SET') - error('Expected CONFIG_IS_SET to be set, but it wasn\'t') -endif - -if conf.has_key('CONFIG_NOT_IS_SET') - error('Expected CONFIG_NOT_IS_SET not be set, but it was') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/1 basic/.config" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/1 basic/.config" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/1 basic/.config" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/1 basic/.config" 2020-06-29 17:00:07.000000000 +0000 @@ -0,0 +1,3 @@ +CONFIG_VAL1=y +# CONFIG_VAL2 is not set +CONFIG_VAL_VAL=4 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/1 basic/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/1 basic/meson.build" 2021-10-23 16:51:23.000000000 +0000 @@ -0,0 +1,18 @@ +project('keyval basic test') + +k = import('keyval') +conf = k.load('.config') + +if not conf.has_key('CONFIG_VAL1') + error('Expected CONFIG_VAL1 to be set, but it wasn\'t') +endif + +if conf.has_key('CONFIG_VAL2') + error('Expected CONFIG_VAL2 not be set, but it was') +endif + +if conf.get('CONFIG_VAL_VAL').to_int() != 4 + error('Expected CONFIG_VAL_VAL to be 4') +endif + +k = import('unstable-keyval') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/1 basic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/1 basic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/1 basic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/1 basic/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "WARNING: Module unstable-keyval is now stable, please use the keyval module instead." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/2 subdir/.config" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/2 subdir/.config" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/2 subdir/.config" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/2 subdir/.config" 2020-06-29 17:00:07.000000000 +0000 @@ -0,0 +1,2 @@ +CONFIG_IS_SET=y +# CONFIG_NOT_IS_SET is not set diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/2 subdir/dir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/2 subdir/dir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/2 subdir/dir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/2 subdir/dir/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,12 @@ + +k = import('keyval') + +conf = k.load(meson.source_root() / '.config') + +if not conf.has_key('CONFIG_IS_SET') + error('Expected CONFIG_IS_SET to be set, but it wasn\'t') +endif + +if conf.has_key('CONFIG_NOT_IS_SET') + error('Expected CONFIG_NOT_IS_SET not be set, but it was') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/2 subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/2 subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/2 subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/2 subdir/meson.build" 2021-10-23 16:51:24.000000000 +0000 @@ -0,0 +1,4 @@ +project('keyval subdir test') + +# Test into sub directory +subdir('dir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/3 load_config files/dir/config" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/3 load_config files/dir/config" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/3 load_config files/dir/config" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/3 load_config files/dir/config" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,2 @@ +CONFIG_IS_SET=y +# CONFIG_NOT_IS_SET is not set diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/3 load_config files/dir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/3 load_config files/dir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/3 load_config files/dir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/3 load_config files/dir/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,12 @@ + +k = import('keyval') + +conf = k.load(files('config')) + +if not conf.has_key('CONFIG_IS_SET') + error('Expected CONFIG_IS_SET to be set, but it wasn\'t') +endif + +if conf.has_key('CONFIG_NOT_IS_SET') + error('Expected CONFIG_NOT_IS_SET not be set, but it was') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/3 load_config files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/3 load_config files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/3 load_config files/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/3 load_config files/meson.build" 2021-10-23 16:51:25.000000000 +0000 @@ -0,0 +1,4 @@ +project('keyval subdir test') + +# Test into sub directory +subdir('dir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/4 load_config builddir/config" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/4 load_config builddir/config" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/4 load_config builddir/config" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/4 load_config builddir/config" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,2 @@ +CONFIG_IS_SET=y +# CONFIG_NOT_IS_SET is not set diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/4 load_config builddir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/4 load_config builddir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/keyval/4 load_config builddir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/keyval/4 load_config builddir/meson.build" 2021-10-23 16:51:25.000000000 +0000 @@ -0,0 +1,14 @@ +project('keyval builddir test') + +k = import('keyval') + +out_conf = configure_file(input: 'config', output: 'out-config', copy: true) +conf = k.load(out_conf) + +if not conf.has_key('CONFIG_IS_SET') + error('Expected CONFIG_IS_SET to be set, but it wasn\'t') +endif + +if conf.has_key('CONFIG_NOT_IS_SET') + error('Expected CONFIG_NOT_IS_SET not be set, but it was') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake/FindImportedOldStyle.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake/FindImportedOldStyle.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake/FindImportedOldStyle.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake/FindImportedOldStyle.cmake" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,5 @@ +find_package(ZLIB) + +set(IMPORTEDOLDSTYLE_LIBRARIES ZLIB::ZLIB) +set(IMPORTEDOLDSTYLE_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}) +set(IMPORTEDOLDSTYLE_FOUND ON) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake" 2020-01-23 21:41:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake" 2021-04-01 21:12:21.000000000 +0000 @@ -4,6 +4,9 @@ include(CheckCXXSourceRuns) include(CheckCSourceRuns) +# Do something stupid (see https://github.com/mesonbuild/meson/issues/7501) +set("") + check_cxx_source_runs( " #include @@ -38,6 +41,10 @@ message(FATAL_ERROR "Running C source code failed") endif() +if(NOT SomethingLikeZLIB_FIND_COMPONENTS STREQUAL "required_comp") + message(FATAL_ERROR "Component 'required_comp' was not specified") +endif() + find_dependency(Threads) if(ZLIB_FOUND OR ZLIB_Found) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake" 2021-10-23 16:36:11.000000000 +0000 @@ -0,0 +1,11 @@ +find_package(ZLIB) + +if(ZLIB_FOUND OR ZLIB_Found) + set(cmMesonTestF1_FOUND ON) + set(cmMesonTestF1_LIBRARIES general ${ZLIB_LIBRARY}) + set(cmMesonTestF1_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) + + add_library(CMMesonTESTf1::evil_non_standard_trget UNKNOWN IMPORTED) +else() + set(cmMesonTestF1_FOUND OFF) +endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,9 @@ +find_package(ZLIB) + +if(ZLIB_FOUND OR ZLIB_Found) + set(cmMesonTestF2_FOUND ON) + set(cmMesonTestF2_LIBRARIES ${ZLIB_LIBRARY}) + set(cmMesonTestF2_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) +else() + set(cmMesonTestF2_FOUND OFF) +endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_fake3/lib/cmake/cmMesonTestF3/cmMesonTestF3Config.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_fake3/lib/cmake/cmMesonTestF3/cmMesonTestF3Config.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_fake3/lib/cmake/cmMesonTestF3/cmMesonTestF3Config.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_fake3/lib/cmake/cmMesonTestF3/cmMesonTestF3Config.cmake" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,9 @@ +find_package(ZLIB) + +if(ZLIB_FOUND OR ZLIB_Found) + set(cmMesonTestF3_FOUND ON) + set(cmMesonTestF3_LIBRARIES ${ZLIB_LIBRARY}) + set(cmMesonTestF3_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) +else() + set(cmMesonTestF3_FOUND OFF) +endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfig.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfig.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfig.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfig.cmake" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,9 @@ +find_package(ZLIB) + +if(ZLIB_FOUND OR ZLIB_Found) + set(cmMesonVersionedTestDep_FOUND ON) + set(cmMesonVersionedTestDep_LIBRARIES ${ZLIB_LIBRARY}) + set(cmMesonVersionedTestDep_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) +else() + set(cmMesonVersionedTestDep_FOUND OFF) +endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfigVersion.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfigVersion.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfigVersion.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfigVersion.cmake" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,12 @@ +set(PACKAGE_VERSION 3.1.4) + +if (${PACKAGE_FIND_VERSION_MAJOR} EQUAL 3) + if (${PACKAGE_FIND_VERSION} VERSION_LESS 3.1.4) + set(PACKAGE_VERSION_COMPATIBLE 1) + endif() + if (${PACKAGE_FIND_VERSION} VERSION_EQUAL 3.1.4) + set(PACKAGE_VERSION_EXACT 1) + endif() +else() + set(PACKAGE_VERSION_UNSUITABLE 1) +endif() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmVers.sh" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmVers.sh" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/cmVers.sh" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/cmVers.sh" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +VERS=$(cmake --version | grep "cmake version") +VERS=${VERS//cmake version/} + +echo -n $VERS diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/meson.build" 2020-01-23 21:41:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -6,6 +6,9 @@ error('MESON_SKIP_TEST cmake binary not available.') endif +# CMake version +cm_vers = run_command(find_program('./cmVers.sh'), check: true).stdout().strip() + # Zlib is probably on all dev machines. dep = dependency('ZLIB', version : '>=1.2', method : 'cmake') @@ -41,21 +44,45 @@ # Try to find cmMesonTestDep in a custom prefix # setup_env.json is used by run_project_tests.py:_run_test to point to ./cmake_pref_env/ depPrefEnv = dependency('cmMesonTestDep', required : true, method : 'cmake') +depPrefEnv1 = dependency('cmMesonTestF1', required : true, method : 'cmake') +depPrefEnv2 = dependency('cmMesonTestF2', required : true, method : 'cmake') +depPrefEnv3 = dependency('cmMesonTestF3', required : true, method : 'cmake') + +# Try to actually link with depPrefEnv1, since we are doing "fun" stuff there +exe3 = executable('zlibprog3', 'prog.c', dependencies : depPrefEnv1) +test('zlibtest3', exe3) # Try to find a dependency with a custom CMake module -depm1 = dependency('SomethingLikeZLIB', required : true, method : 'cmake', cmake_module_path : 'cmake') -depm2 = dependency('SomethingLikeZLIB', required : true, method : 'cmake', cmake_module_path : ['cmake']) -depm3 = dependency('SomethingLikeZLIB', required : true, cmake_module_path : 'cmake') - -# Test some edge cases with spaces, etc. - -testDep1 = dependency('ImportedTarget', required : true, method : 'cmake', cmake_module_path : 'cmake', modules: 'mesonTestLibDefs') -testDep2 = dependency('ImportedTarget', required : true, method : 'cmake', cmake_module_path : 'cmake', modules : ['MesonTest::TestLibDefs']) -testFlagSet1 = executable('testFlagSet1', ['testFlagSet.c'], dependencies: [testDep1]) -testFlagSet2 = executable('testFlagSet2', ['testFlagSet.c'], dependencies: [testDep2]) -test('testFlagSetTest1', testFlagSet1) -test('testFlagSetTest2', testFlagSet2) +depm1 = dependency('SomethingLikeZLIB', required : true, components : 'required_comp', method : 'cmake', cmake_module_path : 'cmake') +depm2 = dependency('SomethingLikeZLIB', required : true, components : 'required_comp', method : 'cmake', cmake_module_path : ['cmake']) +depm3 = dependency('SomethingLikeZLIB', required : true, components : ['required_comp'], cmake_module_path : 'cmake') + + +# Mix of imported targets and old style variables + +depio1 = dependency('ImportedOldStyle', required : true, cmake_module_path : 'cmake') + +# Try to actually link with depio1, since we are doing even more "fun" stuff there +exe4 = executable('zlibprog4', 'prog.c', dependencies : depio1) +test('zlibtest4', exe4) + +# Test some edge cases with spaces, etc. (but only for CMake >= 3.15) + +if cm_vers.version_compare('>=3.15') + testDep1 = dependency('ImportedTarget', required : true, method : 'cmake', cmake_module_path : 'cmake', modules: 'mesonTestLibDefs') + testDep2 = dependency('ImportedTarget', required : true, method : 'cmake', cmake_module_path : 'cmake', modules : ['MesonTest::TestLibDefs']) + testFlagSet1 = executable('testFlagSet1', ['testFlagSet.c'], dependencies: [testDep1]) + testFlagSet2 = executable('testFlagSet2', ['testFlagSet.c'], dependencies: [testDep2]) + test('testFlagSetTest1', testFlagSet1) + test('testFlagSetTest2', testFlagSet2) +endif + +# Try to find a dependency with a cmake module which requires a package version +# test.json sets CMAKE_PREFIX_PATH to include ./cmake_pref_env/ +verdep1 = dependency('cmMesonVersionedTestDep', required : true, method : 'cmake', cmake_package_version : '3.0') +verdep2 = dependency('cmMesonVersionedTestDep', required : false, method : 'cmake', cmake_package_version : '200.0') +assert(not verdep2.found(), 'found a version dep we shouldn\'t have') # Try to compile a test that takes a dep and an include_directories diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/setup_env.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/setup_env.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/setup_env.json" 2019-08-25 19:17:02.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/setup_env.json" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -{ - "CMAKE_PREFIX_PATH": "@ROOT@/cmake_pref_env" -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/13 cmake dependency/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/13 cmake dependency/test.json" 2021-10-23 16:36:11.000000000 +0000 @@ -0,0 +1,14 @@ +{ + "env": { + "CMAKE_PREFIX_PATH": "@ROOT@/cmake_fake1;@ROOT@/cmake_fake2:@ROOT@/cmake_pref_env", + "PATH": "@ROOT@/cmake_fake3/bin:@PATH@" + }, + "stdout": [ + { + "line": "WARNING: Could not find and exact match for the CMake dependency cmMesonTestF1." + }, + { + "line": " ['CMMesonTESTf1::evil_non_standard_trget']" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/14 static dynamic linkage/verify_static.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/14 static dynamic linkage/verify_static.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/14 static dynamic linkage/verify_static.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/14 static dynamic linkage/verify_static.py" 2020-08-15 16:27:05.000000000 +0000 @@ -13,7 +13,7 @@ def handle_cygwin(path): """Handle the Cygwin case.""" output = subprocess.check_output(['nm', path]).decode('utf-8') - if 'I __imp_zlibVersion' in output: + if (('I __imp_zlibVersion' in output) or ('D __imp_zlibVersion' in output)): return 1 return 0 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/15 ld binary/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/15 ld binary/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/15 ld binary/meson.build" 2020-01-23 22:34:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/15 ld binary/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -1,4 +1,4 @@ project('ld binary') ld = find_program('ld') -assert(run_command(ld, '--version').returncode() == 0) +assert(run_command(ld, '--version', check: false).returncode() == 0) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/2 external library/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/2 external library/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/2 external library/meson.build" 2020-01-07 21:10:26.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/2 external library/meson.build" 2021-10-23 16:51:28.000000000 +0000 @@ -18,6 +18,12 @@ ''' assert(cc.links(linkcode, args : '-lz', name : 'Test link against zlib'), 'Linking test failed.') +d1 = declare_dependency(compile_args: '-DSOMETHING', link_args: '-lz') +assert(cc.links(linkcode, dependencies : d1, + name : 'Test link against zlib via declare_dependency'), 'Linking test failed.') +d2 = declare_dependency(dependencies: d1) +assert(cc.links(linkcode, dependencies : d2, + name : 'Test link against zlib via indirect declare_dependency'), 'Linking test failed.') assert(not cc.links(nolinkcode, name : 'Failing link'), 'Linking succeeded when it should have failed.') e = executable('zprog', 'prog.c', dependencies : zlib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/3 linker script/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/3 linker script/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/3 linker script/meson.build" 2020-01-07 21:10:28.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/3 linker script/meson.build" 2021-10-23 16:51:30.000000000 +0000 @@ -1,5 +1,11 @@ project('linker script', 'c') +# Solaris 11.4 ld supports --version-script only when you also specify +# -z gnu-version-script-compat +if meson.get_compiler('c').get_linker_id() == 'ld.solaris' + add_project_link_arguments('-Wl,-z,gnu-version-script-compat', language: 'C') +endif + # Static map file mapfile = 'bob.map' vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/meson.build" 2020-01-07 21:10:34.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/meson.build" 2021-10-23 16:51:37.000000000 +0000 @@ -31,39 +31,39 @@ # Search for an external dependency that won't be found, but must later be # found via fallbacks -somelibnotfound = dependency('somelib', required : false) +somelibnotfound = dependency('somelib1', required : false) assert(somelibnotfound.found() == false, 'somelibnotfound was found?') # Find internal dependency without version -somelibver = dependency('somelib', +somelibver = dependency('somelib1', fallback : ['somelibnover', 'some_dep']) assert(somelibver.type_name() == 'internal', 'somelibver should be of type "internal", not ' + somelibver.type_name()) # Find an internal dependency again with the same name and a specific version -somelib = dependency('somelib', +somelib = dependency('somelib2', version : '== 0.1', fallback : ['somelib', 'some_dep']) # Find an internal dependency again even if required = false -somelib_reqfalse = dependency('somelib', +somelib_reqfalse = dependency('somelib3', required: false, fallback : ['somelib', 'some_dep']) assert(somelib_reqfalse.found(), 'somelib should have been found') # Find an internal dependency again with the same name and incompatible version -somelibver = dependency('somelib', +somelibver = dependency('somelib4', version : '>= 0.3', fallback : ['somelibver', 'some_dep']) # Find an internal dependency again with impossible multi-version -somelibver = dependency('somelib', +somelibver = dependency('somelib5', version : ['>= 0.3', '<0.3'], required : false, fallback : ['somelibver', 'some_dep']) assert(not somelibver.found(), 'Dependency should not be found') # Find somelib again, but with a fallback that will fail because subproject does not exist -somelibfail = dependency('somelib', +somelibfail = dependency('somelib6', version : '>= 0.2', required : false, fallback : ['somelibfail', 'some_dep']) assert(somelibfail.found() == false, 'somelibfail found via wrong fallback') # Find somelib again, but with a fallback that will fail because dependency does not exist -somefail_dep = dependency('somelib', +somefail_dep = dependency('somelib7', version : '>= 0.2', required : false, fallback : ['somelib', 'somefail_dep']) @@ -71,14 +71,21 @@ # Fallback should only be used if the primary was not found fallbackzlib_dep = dependency('zlib', - fallback : ['somelib', 'fakezlib_dep']) + fallback : ['fakezlib', 'fakezlib_dep']) assert(fallbackzlib_dep.type_name() == 'pkgconfig', 'fallbackzlib_dep should be of type "pkgconfig", not ' + fallbackzlib_dep.type_name()) # Check that the above dependency was pkgconfig because the fallback wasn't # checked, not because the fallback didn't work fakezlib_dep = dependency('fakezlib', - fallback : ['somelib', 'fakezlib_dep']) + fallback : ['fakezlib', 'fakezlib_dep']) assert(fakezlib_dep.type_name() == 'internal', 'fakezlib_dep should be of type "internal", not ' + fakezlib_dep.type_name()) +# Verify that once we got a system dependency, we won't fallback if a newer +# version is requested. +d = dependency('zlib', version: '>= 999', + fallback : ['donotexist', 'fakezlib_dep'], + required: false) +assert(not d.found(), 'version should not match and it should not fallback') + # Check that you can find a dependency by not specifying a version after not # finding it by specifying a version. We add `static: true` here so that the # previously cached zlib dependencies don't get checked. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/subprojects/fakezlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/subprojects/fakezlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/subprojects/fakezlib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/subprojects/fakezlib/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,3 @@ +project('some', 'c', version : '0.1') + +fakezlib_dep = declare_dependency() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build" 2016-10-17 18:14:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -1,7 +1,7 @@ # Define version only in project, should get inherited by declare_dependency project('some', 'c', version : '0.1') -somelib = shared_library('some', 'lib.c') +somelib = library('some', 'lib.c') someinc = include_directories('.') some_dep = declare_dependency(link_with : somelib, diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/subprojects/somelibnover/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/subprojects/somelibnover/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/subprojects/somelibnover/meson.build" 2016-06-05 11:27:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/subprojects/somelibnover/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -1,6 +1,6 @@ project('some', 'c') -somelib = shared_library('some', 'lib.c') +somelib = library('some', 'lib.c') someinc = include_directories('.') # Define version only in declare_dependency diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/subprojects/somelibver/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/subprojects/somelibver/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/5 dependency versions/subprojects/somelibver/meson.build" 2016-06-05 11:27:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/5 dependency versions/subprojects/somelibver/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -1,6 +1,6 @@ project('some', 'c') -somelib = shared_library('some', 'lib.c') +somelib = library('some', 'lib.c') someinc = include_directories('.') # Define version only in declare_dependency diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/7 library versions/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/7 library versions/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/7 library versions/installed_files.txt" 2017-04-15 14:27:38.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/7 library versions/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -usr/lib/libsome.so -usr/lib/libsome.so.0 -usr/lib/libsome.so.1.2.3 -usr/lib/libnoversion.so -usr/lib/libonlyversion.so -usr/lib/libonlyversion.so.1 -usr/lib/libonlyversion.so.1.4.5 -usr/lib/libonlysoversion.so -usr/lib/libonlysoversion.so.5 -usr/lib/libmodule.so diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/7 library versions/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/7 library versions/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/7 library versions/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/7 library versions/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,14 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/libsome.so"}, + {"type": "file", "file": "usr/lib/libsome.so.0"}, + {"type": "file", "file": "usr/lib/libsome.so.1.2.3"}, + {"type": "file", "file": "usr/lib/libnoversion.so"}, + {"type": "file", "file": "usr/lib/libonlyversion.so"}, + {"type": "file", "file": "usr/lib/libonlyversion.so.1"}, + {"type": "file", "file": "usr/lib/libonlyversion.so.1.4.5"}, + {"type": "file", "file": "usr/lib/libonlysoversion.so"}, + {"type": "file", "file": "usr/lib/libonlysoversion.so.5"}, + {"type": "file", "file": "usr/lib/libmodule.so"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/8 subproject library install/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/8 subproject library install/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/8 subproject library install/installed_files.txt" 2016-07-15 10:52:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/8 subproject library install/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/lib/libsublib.so -usr/lib/libsublib.so.5 -usr/lib/libsublib.so.2.1.0 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/8 subproject library install/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/8 subproject library install/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/linuxlike/8 subproject library install/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/linuxlike/8 subproject library install/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/libsublib.so"}, + {"type": "file", "file": "usr/lib/libsublib.so.5"}, + {"type": "file", "file": "usr/lib/libsublib.so.2.1.0"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/1 trivial/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/1 trivial/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/1 trivial/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/1 trivial/meson.build" 2021-10-23 16:50:49.000000000 +0000 @@ -0,0 +1,9 @@ +project('trivial native test', 'c') + +sources = 'trivial.c' +cc = meson.get_compiler('c', native: true) + +if meson.is_cross_build() + native_exe = executable('native-trivialprog', sources : sources, native : true) + test('native exe in cross build', native_exe) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/1 trivial/trivial.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/1 trivial/trivial.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/1 trivial/trivial.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/1 trivial/trivial.c" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("Trivial test is working.\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/2 global arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/2 global arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/2 global arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/2 global arg/meson.build" 2021-10-23 16:50:54.000000000 +0000 @@ -0,0 +1,14 @@ +project('global arg test', 'cpp', 'c') + +add_global_arguments('-DMYTHING', language : 'c', native : true) +add_global_arguments('-DMYCPPTHING', language : 'cpp', native : true) +add_global_arguments('-DGLOBAL_BUILD', language : 'c', native : true) + +build_c_args = ['-DARG_BUILD'] +c_args = ['-DARG_HOST'] + +add_global_arguments('-DMYCANDCPPTHING', language: ['c', 'cpp'], native: true) + +exe1 = executable('prog1', 'prog.c', c_args : build_c_args, native : true) + +test('prog1', exe1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/2 global arg/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/2 global arg/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/2 global arg/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/2 global arg/prog.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,43 @@ +#ifndef MYTHING + #error "Global argument not set" +#endif + +#ifdef MYCPPTHING + #error "Wrong global argument set" +#endif + +#ifndef MYCANDCPPTHING + #error "Global argument not set" +#endif + +#if !defined(GLOBAL_HOST) && !defined(GLOBAL_BUILD) + #error "Neither global_host nor glogal_build is set." +#endif + +#if defined(GLOBAL_HOST) && defined(GLOBAL_BUILD) + #error "Both global build and global host set." +#endif + +#ifdef GLOBAL_BUILD + #ifndef ARG_BUILD + #error "Global is build but arg_build is not set." + #endif + + #ifdef ARG_HOST + #error "Global is build but arg host is set." + #endif +#endif + +#ifdef GLOBAL_HOST + #ifndef ARG_HOST + #error "Global is host but arg_host is not set." + #endif + + #ifdef ARG_BUILD + #error "Global is host but arg_build is set." + #endif +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/2 global arg/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/2 global arg/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/2 global arg/prog.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/2 global arg/prog.cc" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,15 @@ +#ifdef MYTHING +#error "Wrong global argument set" +#endif + +#ifndef MYCPPTHING +#error "Global argument not set" +#endif + +#ifndef MYCANDCPPTHING +#error "Global argument not set" +#endif + +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/copyrunner.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/copyrunner.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/copyrunner.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/copyrunner.py" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys, subprocess + +prog, infile, outfile = sys.argv[1:] + +subprocess.check_call([prog, infile, outfile]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/filecopier.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/filecopier.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/filecopier.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/filecopier.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,23 @@ +#include +#include + +#define BUFSIZE 1024 + +int main(int argc, char **argv) { + char buffer[BUFSIZE]; + size_t num_read; + size_t num_written; + FILE *fin = fopen(argv[1], "rb"); + FILE *fout; + assert(argc>0); + assert(fin); + num_read = fread(buffer, 1, BUFSIZE, fin); + assert(num_read > 0); + fclose(fin); + fout = fopen(argv[2], "wb"); + assert(fout); + num_written = fwrite(buffer, 1, num_read, fout); + assert(num_written == num_read); + fclose(fout); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/libsrc.c.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/libsrc.c.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/libsrc.c.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/libsrc.c.in" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,3 @@ +int func(void) { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,11 @@ +runner = find_program('copyrunner.py') + +copier = executable('copier', 'filecopier.c', native: true) + +cg = generator(runner, + output: ['@BASENAME@.c'], + arguments: [copier.full_path(), '@INPUT@', '@OUTPUT@'], + depends: copier) + +test('generatordep', + executable('gd', 'prog.c', cg.process('libsrc.c.in'))) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/depends/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/depends/prog.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,5 @@ +int func(void); + +int main(void) { + return func() != 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/input_src.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/input_src.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/input_src.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/input_src.dat" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1 @@ +int func(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/meson.build" 2021-10-23 16:50:54.000000000 +0000 @@ -0,0 +1,23 @@ +project('pipeline test', 'c') + +# We need to run this executable locally so build it with +# the host compiler. +e1 = executable('srcgen', 'srcgen.c', native : true) + +# Generate a source file that needs to be included in the build. +gen = generator(e1, \ + depfile : '@BASENAME@.d', + output : '@BASENAME@.c', # Line continuation inside arguments should work without needing a "\". + arguments : ['@INPUT@', '@OUTPUT@', '@DEPFILE@']) + +generated = gen.process(['input_src.dat']) + +e2 = executable('prog', 'prog.c', generated) + +test('pipelined', e2) + +# This is in a subdirectory to make sure +# we write proper subdir paths to output. +subdir('src') + +subdir('depends') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/prog.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,5 @@ +int func(void); + +int main(void) { + return func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/src/input_src.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/src/input_src.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/src/input_src.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/src/input_src.dat" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1 @@ +#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/src/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,12 @@ +e1 = executable('srcgen', 'srcgen.c', native : true) + +# Generate a header file that needs to be included. +gen = generator(e1, + output : '@BASENAME@.h', + arguments : ['@INPUT@', '@OUTPUT@']) + +generated = gen.process('input_src.dat') + +e2 = executable('prog', 'prog.c', generated) + +test('pipelined', e2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/src/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/src/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/src/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/src/prog.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,9 @@ +#include"input_src.h" + +int main(void) { + void *foo = printf; + if(foo) { + return 0; + } + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/src/srcgen.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/src/srcgen.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/src/srcgen.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/src/srcgen.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,40 @@ +#include +#include + +#define ARRSIZE 80 + +int main(int argc, char **argv) { + char arr[ARRSIZE]; + char *ifilename; + char *ofilename; + FILE *ifile; + FILE *ofile; + size_t bytes; + + if(argc != 3) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + ifilename = argv[1]; + ofilename = argv[2]; + printf("%s\n", ifilename); + ifile = fopen(ifilename, "r"); + if(!ifile) { + fprintf(stderr, "Could not open source file %s.\n", ifilename); + return 1; + } + ofile = fopen(ofilename, "w"); + if(!ofile) { + fprintf(stderr, "Could not open target file %s\n", ofilename); + fclose(ifile); + return 1; + } + bytes = fread(arr, 1, ARRSIZE, ifile); + assert(bytes < 80); + assert(bytes > 0); + fwrite(arr, 1, bytes, ofile); + + fclose(ifile); + fclose(ofile); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/srcgen.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/srcgen.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/3 pipeline/srcgen.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/3 pipeline/srcgen.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,69 @@ +#include +#include +#include + +#define ARRSIZE 80 + +int main(int argc, char **argv) { + char arr[ARRSIZE]; + char *ofilename; + char *ifilename; + char *dfilename; + FILE *ifile; + FILE *ofile; + FILE *depfile; + size_t bytes; + int i; + + if(argc != 4) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + ifilename = argv[1]; + ofilename = argv[2]; + dfilename = argv[3]; + ifile = fopen(argv[1], "r"); + if(!ifile) { + fprintf(stderr, "Could not open source file %s.\n", argv[1]); + return 1; + } + ofile = fopen(ofilename, "w"); + if(!ofile) { + fprintf(stderr, "Could not open target file %s\n", ofilename); + fclose(ifile); + return 1; + } + bytes = fread(arr, 1, ARRSIZE, ifile); + assert(bytes < 80); + assert(bytes > 0); + fwrite(arr, 1, bytes, ofile); + + depfile = fopen(dfilename, "w"); + if(!depfile) { + fprintf(stderr, "Could not open depfile %s\n", ofilename); + fclose(ifile); + fclose(ofile); + return 1; + } + for(i=0; i +int main(void) { + printf("%s\n", "stdout"); + fprintf(stderr, "%s\n", "stderr"); + return 0; +} +''' + +error_code = '''int main(void) { + return 1; +} +''' + +no_compile_code = '''int main(void) { +''' + +INPUTS = [ + ['String', ok_code, error_code, no_compile_code], + ['File', files('ok.c'), files('error.c'), files('no_compile.c')], +] + +foreach cc : compilers + foreach input : INPUTS + type = input[0] + ok = cc.run(input[1], name : type + ' should succeed') + err = cc.run(input[2], name : type + ' should fail') + noc = cc.run(input[3], name : type + ' does not compile') + + if noc.compiled() + error(type + ' compilation fail test failed.') + else + message(type + ' fail detected properly.') + endif + + if ok.compiled() + message(type + ' compilation worked.') + else + error(type + ' compilation did not work.') + endif + + if ok.returncode() == 0 + message(type + ' return code ok.') + else + error(type + ' return code fail') + endif + + if err.returncode() == 1 + message(type + ' bad return code ok.') + else + error(type + ' bad return code fail.') + endif + + if ok.stdout().strip() == 'stdout' + message(type + ' stdout ok.') + else + message(type + ' bad stdout.') + endif + + if ok.stderr().strip() == 'stderr' + message(type + ' stderr ok.') + else + message(type + ' bad stderr.') + endif + endforeach +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/4 tryrun/no_compile.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/4 tryrun/no_compile.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/4 tryrun/no_compile.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/4 tryrun/no_compile.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1 @@ +int main(void) { diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/4 tryrun/ok.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/4 tryrun/ok.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/4 tryrun/ok.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/4 tryrun/ok.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +int main(void) { + printf("%s\n", "stdout"); + fprintf(stderr, "%s\n", "stderr"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/meson.build" 2021-10-23 16:50:54.000000000 +0000 @@ -0,0 +1,12 @@ +project('custom install script', 'c') + +# this is just to ensure that the install directory exists before exe is run +install_data('file.txt', install_dir: '.') + +subdir('src') + +meson.add_install_script(exe, 'generated.txt') +wrap = find_program('wrap.py') +# Yes, these are getting silly +meson.add_install_script(wrap, exe, 'wrapped.txt') +meson.add_install_script(wrap, wrap, exe, 'wrapped2.txt') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/src/exe.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/src/exe.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/src/exe.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/src/exe.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,27 @@ +#include +#include +#include + +int main(int argc, char * argv[]) { + if (argc != 2) { + fprintf(stderr, "Takes exactly 2 arguments\n"); + return 1; + } + + char * dirname = getenv("MESON_INSTALL_DESTDIR_PREFIX"); + char * fullname = malloc(strlen(dirname) + 1 + strlen(argv[1]) + 1); + strcpy(fullname, dirname); + strcat(fullname, "/"); + strcat(fullname, argv[1]); + + FILE * fp = fopen(fullname, "w"); + if (!fp) + return 1; + + fputs("Some text\n", fp); + fclose(fp); + + free(fullname); + + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/src/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/src/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/src/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/src/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1 @@ +exe = executable('exe', 'exe.c', install : false, native : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/test.json" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "installed": [ + {"type": "file", "file": "usr/file.txt"}, + {"type": "file", "file": "usr/generated.txt"}, + {"type": "file", "file": "usr/wrapped.txt"}, + {"type": "file", "file": "usr/wrapped2.txt"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/wrap.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/wrap.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/5 install script/wrap.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/5 install script/wrap.py" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import subprocess +import sys + +subprocess.run(sys.argv[1:]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/6 add language/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/6 add language/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/6 add language/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/6 add language/meson.build" 2021-10-23 16:50:59.000000000 +0000 @@ -0,0 +1,3 @@ +project('add language', 'c') +assert(add_languages('cpp', native: true), 'Add_languages returned false on success') +test('C++', executable('cppprog', 'prog.cc', native: true)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/6 add language/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/6 add language/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/6 add language/prog.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/6 add language/prog.cc" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(int, char**) { + std::cout << "I am C++.\n"; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/checkarg.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/checkarg.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/checkarg.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/checkarg.cpp" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(int argc, char *[]) { + assert(argc == 2); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/data.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/data.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/data.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/data.dat" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1 @@ +generated_function diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/mainprog.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/mainprog.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/mainprog.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/mainprog.cpp" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,5 @@ +#include"data.h" + +int main(void) { + return generated_function() != 52; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/meson.build" 2021-10-23 16:51:00.000000000 +0000 @@ -0,0 +1,39 @@ +project('selfbuilt custom', 'cpp') + +# Build an exe and use it in a custom target +# whose output is used to build a different exe. + +tool = executable('tool', 'tool.cpp', native : true) + +hfile = custom_target('datah', + output : 'data.h', + input : 'data.dat', + command : [tool, '@INPUT@', '@OUTPUT@'], +) + +main = executable('mainprog', 'mainprog.cpp', hfile) + +test('maintest', main) + +lib = library('libtool', 'tool.cpp') + +checkarg = executable('checkarg', 'checkarg.cpp', native : true) + +ctlib = custom_target('ctlib', + output : 'ctlib.out', + capture : true, + command : [checkarg, lib], + build_by_default : true, +) + +if meson.is_cross_build() and meson.can_run_host_binaries() + checkarg_host = executable('checkarg_host', 'checkarg.cpp') + + ctlib_host = custom_target( + 'ctlib_host', + output : 'ctlib.host.out', + capture : true, + command : [checkarg_host, lib], + build_by_default : true, + ) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/tool.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/tool.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/7 selfbuilt custom/tool.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/7 selfbuilt custom/tool.cpp" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,34 @@ +#include +#include +#include + +using namespace std; + +const char prefix[] = "int "; +const char suffix[] = " () {\n return 52;}\n"; + +int main(int argc, char **argv) { + if(argc != 3) { + cout << "You is fail.\n"; + return 1; + } + ifstream is(argv[1], ifstream::binary); + if(!is) { + cout << "Opening input file failed.\n"; + return 1; + } + string funcname; + is >> funcname; + ofstream os(argv[2], ofstream::binary); + if(!os) { + cout << "Opening output file failed.\n"; + return 1; + } + os << prefix << funcname << suffix; + os.close(); + if(!os.good()) { + cout << "Writing data out failed.\n"; + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/8 external program shebang parsing/input.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/8 external program shebang parsing/input.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/8 external program shebang parsing/input.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/8 external program shebang parsing/input.txt" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1 @@ +some stuff here diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/8 external program shebang parsing/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/8 external program shebang parsing/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/8 external program shebang parsing/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/8 external program shebang parsing/main.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include +#else + #include +#endif + +/* Who cares about stack sizes in test programs anyway */ +#define LINE_LENGTH 4096 + +static int +intrp_copyfile (char * src, char * dest) +{ +#ifdef _WIN32 + if (!CopyFile (src, dest, FALSE)) + return 1; + return 0; +#else + return execlp ("cp", "cp", src, dest, NULL); +#endif +} + +static void +parser_get_line (FILE * f, char line[LINE_LENGTH]) +{ + if (!fgets (line, LINE_LENGTH, f)) + fprintf (stderr, "%s\n", strerror (errno)); +} + +int +main (int argc, char * argv[]) +{ + FILE *f = NULL; + char line[LINE_LENGTH]; + + if (argc != 4) { + fprintf (stderr, "Invalid number of arguments: %i\n", argc); + goto err; + } + + if ((f = fopen (argv[1], "r")) == NULL) { + fprintf (stderr, "%s\n", strerror (errno)); + goto err; + } + + parser_get_line (f, line); + + if (!line || line[0] != '#' || line[1] != '!') { + fprintf (stderr, "Invalid script\n"); + goto err; + } + + parser_get_line (f, line); + + if (!line || strncmp (line, "copy", 4) != 0) { + fprintf (stderr, "Syntax error: %s\n", line); + goto err; + } + + return intrp_copyfile (argv[2], argv[3]); + +err: + fclose (f); + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/8 external program shebang parsing/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/8 external program shebang parsing/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/8 external program shebang parsing/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/8 external program shebang parsing/meson.build" 2021-10-23 16:50:59.000000000 +0000 @@ -0,0 +1,21 @@ +project('shebang parsing', 'c') + +interpreter = executable('aninterp', 'main.c', native : true) + +cdata = configuration_data() +cdata.set('INTRP', interpreter.full_path()) + +f = configure_file(input : 'script.int.in', + output : 'script.int', + configuration : cdata) + +# Test that parsing a shebang with spaces works properly. See `man execve`, +# specifically the section on "Interpreter scripts" and the one under "NOTES". +script = find_program(f) + +custom_target('interpthis', + input : 'input.txt', + output : 'output.txt', + depends : interpreter, + command : [script, '@INPUT@', '@OUTPUT@'], + build_by_default : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/8 external program shebang parsing/script.int.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/8 external program shebang parsing/script.int.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/8 external program shebang parsing/script.int.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/8 external program shebang parsing/script.int.in" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,2 @@ +#!/usr/bin/env @INTRP@ +copy diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/9 override with exe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/9 override with exe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/9 override with exe/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/9 override with exe/meson.build" 2021-10-23 16:51:01.000000000 +0000 @@ -0,0 +1,21 @@ +project('myexe', 'c', version: '0.1') +sub = subproject('sub') + +prog = find_program('foobar', version : '>= 2.0', required : false) +assert(not prog.found()) + +prog = find_program('foobar', version : '>= 1.0') +custom1 = custom_target('custom1', + build_by_default : true, + input : [], + output : 'main1.c', + command : [prog, '@OUTPUT@']) +gen = generator(prog, + output : '@BASENAME@.c', + arguments : ['@OUTPUT@']) +custom2 = gen.process('main2.input') + +message(prog.full_path()) + +executable('e1', custom1) +executable('e2', custom2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/9 override with exe/subprojects/sub/foobar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/9 override with exe/subprojects/sub/foobar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/9 override with exe/subprojects/sub/foobar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/9 override with exe/subprojects/sub/foobar.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,13 @@ +#include +#include + +int main(int argc, char* argv[]) { + assert(argc == 2); + FILE *f = fopen(argv[1], "w"); + const char msg[] = "int main(void) {return 0;}\n"; + size_t w = fwrite(msg, 1, sizeof(msg) - 1, f); + assert(w == sizeof(msg) - 1); + int r = fclose(f); + assert(r == 0); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/9 override with exe/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/9 override with exe/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/native/9 override with exe/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/native/9 override with exe/subprojects/sub/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,3 @@ +project('sub', 'c', version : '1.0') +foobar = executable('foobar', 'foobar.c', native : true) +meson.override_find_program('foobar', foobar) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/objc/1 simple/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/objc/1 simple/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/objc/1 simple/meson.build" 2020-01-07 21:12:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/objc/1 simple/meson.build" 2021-10-23 16:53:27.000000000 +0000 @@ -1,4 +1,4 @@ -project('objective c', 'objc') +project('objective c', 'objc', default_options: ['c_std=c99']) exe = executable('prog', 'prog.m') test('objctest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/objc/2 nsstring/stringprog.m" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/objc/2 nsstring/stringprog.m" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/objc/2 nsstring/stringprog.m" 2019-12-04 18:45:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/objc/2 nsstring/stringprog.m" 2021-11-02 19:58:07.000000000 +0000 @@ -7,4 +7,3 @@ [str release]; return result; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/objcpp/1 simple/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/objcpp/1 simple/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/objcpp/1 simple/meson.build" 2020-01-07 21:12:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/objcpp/1 simple/meson.build" 2021-10-23 16:53:32.000000000 +0000 @@ -1,4 +1,4 @@ -project('Objective C++', 'objcpp') +project('Objective C++', 'objcpp', default_options: 'cpp_std=c++14') exe = executable('objcppprog', 'prog.mm') test('objcpp', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/objcpp/1 simple/prog.mm" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/objcpp/1 simple/prog.mm" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/objcpp/1 simple/prog.mm" 2019-12-04 18:45:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/objcpp/1 simple/prog.mm" 2021-11-02 19:58:07.000000000 +0000 @@ -6,4 +6,3 @@ int main(void) { return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/2 library versions/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/2 library versions/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/2 library versions/installed_files.txt" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/2 library versions/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -usr/lib/libsome.dylib -usr/lib/libsome.7.dylib -usr/lib/libnoversion.dylib -usr/lib/libonlyversion.dylib -usr/lib/libonlyversion.1.dylib -usr/lib/libonlysoversion.dylib -usr/lib/libonlysoversion.5.dylib -usr/lib/libmodule.dylib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/2 library versions/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/2 library versions/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/2 library versions/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/2 library versions/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,12 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/libsome.dylib"}, + {"type": "file", "file": "usr/lib/libsome.7.dylib"}, + {"type": "file", "file": "usr/lib/libnoversion.dylib"}, + {"type": "file", "file": "usr/lib/libonlyversion.dylib"}, + {"type": "file", "file": "usr/lib/libonlyversion.1.dylib"}, + {"type": "file", "file": "usr/lib/libonlysoversion.dylib"}, + {"type": "file", "file": "usr/lib/libonlysoversion.5.dylib"}, + {"type": "file", "file": "usr/lib/libmodule.dylib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/4 framework/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/4 framework/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/4 framework/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/4 framework/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/prog -usr/lib/libstat.a diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/4 framework/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/4 framework/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/4 framework/meson.build" 2017-06-12 18:30:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/4 framework/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -3,21 +3,30 @@ # "Target Membership" of ... # - OpenGL.framework should be only to prog@exe # - Foundation.framework should be only to stat@sta -# "Build Phase" / "Link Binary with Libraries" for the target +# "Build Phase" / "Link Binary with Libraries" for the target # - "prog@exe" should be only "Foundation.framework" # - "stat@sta" should be only "OpenGL.framework" # see "xcode-frameworks.png" for an example -project('xcode framework test', 'c', default_options : ['libdir=libtest']) - -dep_libs = dependency('appleframeworks', modules : ['OpenGL'], required : false) -if not dep_libs.found() - error('OpenGL framework not found') -endif -assert(dep_libs.type_name() == 'appleframeworks', 'type_name is wrong') +project('xcode framework test', 'objc', default_options : ['libdir=libtest']) dep_main = dependency('appleframeworks', modules : ['Foundation']) -stlib = static_library('stat', 'stat.c', install : true, dependencies: dep_libs) -exe = executable('prog', 'prog.c', install : true, dependencies: dep_main) - +if meson.is_cross_build() + # This is only available in iOS, not macOS. Just test finding it. + uikit_dep = dependency('appleframeworks', modules: 'UIKit') +else + dep_libs = dependency('appleframeworks', modules : ['OpenGL'], required : false) + if not dep_libs.found() + error('OpenGL framework not found') + endif + assert(dep_libs.type_name() == 'appleframeworks', 'type_name is wrong') + # Only add the C compiler now, to ensure all lookups above were done with the ObjC one. + add_languages('c') + stlib = static_library('stat', 'stat.c', install : true, dependencies: dep_libs) + exe = executable('prog', 'prog.c', install : true, dependencies: dep_main) + uikit_dep = dependency('appleframeworks', modules: 'UIKit', required: false) + if uikit_dep.found() + error('UIKit found on macOS even though it should not be there.') + endif +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/4 framework/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/4 framework/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/4 framework/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/4 framework/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/lib/libstat.a"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/5 extra frameworks/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/5 extra frameworks/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/5 extra frameworks/installed_files.txt" 2019-02-07 09:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/5 extra frameworks/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/prog -usr/lib/libstat.a diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/5 extra frameworks/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/5 extra frameworks/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/5 extra frameworks/meson.build" 2019-02-07 09:08:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/5 extra frameworks/meson.build" 2021-11-25 22:00:46.000000000 +0000 @@ -6,8 +6,5 @@ dep_main = dependency('Foundation') assert(dep_main.type_name() == 'extraframeworks', 'type_name is ' + dep_main.type_name()) -dep_py = dependency('python', method : 'extraframework') -assert(dep_main.type_name() == 'extraframeworks', 'type_name is ' + dep_main.type_name()) - stlib = static_library('stat', 'stat.c', install : true, dependencies: dep_libs) exe = executable('prog', 'prog.c', install : true, dependencies: dep_main) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/5 extra frameworks/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/5 extra frameworks/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/5 extra frameworks/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/5 extra frameworks/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/lib/libstat.a"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/7 bitcode/libbar.mm" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/7 bitcode/libbar.mm" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/7 bitcode/libbar.mm" 2019-12-04 18:45:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/7 bitcode/libbar.mm" 2021-11-02 19:58:07.000000000 +0000 @@ -4,4 +4,3 @@ int EXPORT_PUBLIC libbar(void) { return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/7 bitcode/libfoo.m" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/7 bitcode/libfoo.m" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/osx/7 bitcode/libfoo.m" 2019-12-04 18:45:59.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/osx/7 bitcode/libfoo.m" 2021-11-02 19:58:07.000000000 +0000 @@ -4,4 +4,3 @@ int EXPORT_PUBLIC libfoo(void) { return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/1 basic/meson.build" 2020-01-07 21:13:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/1 basic/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,4 @@ -project('python sample', 'c') +project('python sample') py_mod = import('python') py = py_mod.find_installation('python3') @@ -9,13 +9,14 @@ endif py_purelib = py.get_path('purelib') -if not py_purelib.endswith('site-packages') +if not (py_purelib.endswith('site-packages') or py_purelib.endswith('dist-packages')) error('Python3 purelib path seems invalid? ' + py_purelib) endif +message('Python purelib path:', py_purelib) # could be 'lib64' or 'Lib' on some systems py_platlib = py.get_path('platlib') -if not py_platlib.endswith('site-packages') +if not (py_platlib.endswith('site-packages') or py_platlib.endswith('dist-packages')) error('Python3 platlib path seems invalid? ' + py_platlib) endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/1 basic/prog.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/1 basic/prog.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/1 basic/prog.py" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/1 basic/prog.py" 2021-04-01 21:12:21.000000000 +0000 @@ -1,9 +1,8 @@ #!/usr/bin/env python3 from gluon import gluonator -import sys print('Running mainprog from root dir.') if gluonator.gluoninate() != 42: - sys.exit(1) + raise ValueError("!= 42") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/1 basic/subdir/subprog.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/1 basic/subdir/subprog.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/1 basic/subdir/subprog.py" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/1 basic/subdir/subprog.py" 2021-04-01 21:12:21.000000000 +0000 @@ -4,9 +4,8 @@ # point to source root. from gluon import gluonator -import sys print('Running mainprog from subdir.') if gluonator.gluoninate() != 42: - sys.exit(1) + raise ValueError("!= 42") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/blaster.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/blaster.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/blaster.py" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/blaster.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 - -import tachyon -import sys - -result = tachyon.phaserize('shoot') - -if not isinstance(result, int): - print('Returned result not an integer.') - sys.exit(1) - -if result != 1: - print('Returned result {} is not 1.'.format(result)) - sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/blaster.py.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/blaster.py.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/blaster.py.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/blaster.py.in" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import @tachyon_module@ as tachyon + +result = tachyon.phaserize('shoot') + +if not isinstance(result, int): + raise SystemExit('Returned result not an integer.') + +if result != 1: + raise SystemExit(f'Returned result {result} is not 1.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/ext/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/ext/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/ext/meson.build" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/ext/meson.build" 2021-10-11 16:26:46.000000000 +0000 @@ -1,6 +1,10 @@ pylib = py.extension_module('tachyon', 'tachyon_module.c', dependencies : py_dep, + c_args: '-DMESON_MODULENAME="tachyon"', + install: true, ) +subdir('nested') +subdir('wrongdir') pypathdir = meson.current_build_dir() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/ext/nested/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/ext/nested/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/ext/nested/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/ext/nested/meson.build" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,16 @@ +py.extension_module('tachyon', + '../tachyon_module.c', + dependencies : py_dep, + c_args: '-DMESON_MODULENAME="nested.tachyon"', + install: true, + subdir: 'nested' +) +py.install_sources( + configure_file( + input: '../../blaster.py.in', + output: 'blaster.py', + configuration: {'tachyon_module': 'nested.tachyon'} + ), + pure: false, + subdir: 'nested', +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/ext/tachyon_module.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/ext/tachyon_module.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/ext/tachyon_module.c" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/ext/tachyon_module.c" 2021-10-11 16:26:46.000000000 +0000 @@ -38,7 +38,7 @@ static struct PyModuleDef tachyonmodule = { PyModuleDef_HEAD_INIT, - "tachyon", + MESON_MODULENAME, NULL, -1, TachyonMethods diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/ext/wrongdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/ext/wrongdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/ext/wrongdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/ext/wrongdir/meson.build" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,7 @@ +py.extension_module('tachyon', + '../tachyon_module.c', + dependencies : py_dep, + c_args: '-DMESON_MODULENAME="tachyon"', + install: true, + install_dir: get_option('libdir') +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/meson.build" 2020-01-07 21:13:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/meson.build" 2021-10-23 16:54:02.000000000 +0000 @@ -3,26 +3,41 @@ # Because Windows Python ships only with optimized libs, # we must build this project the same way. +if meson.backend() != 'ninja' + error('MESON_SKIP_TEST: Ninja backend required') +endif + + py_mod = import('python') py = py_mod.find_installation() -py_dep = py.dependency() +py_dep = py.dependency(required: false) -if py_dep.found() - subdir('ext') +if not py_dep.found() + error('MESON_SKIP_TEST: Python libraries not found.') +endif - test('extmod', - py, - args : files('blaster.py'), - env : ['PYTHONPATH=' + pypathdir]) +subdir('ext') - # Check we can apply a version constraint - dependency('python3', version: '>=@0@'.format(py_dep.version())) +blaster = configure_file( + input: 'blaster.py.in', + output: 'blaster.py', + configuration: {'tachyon_module': 'tachyon'} +) + +test('extmod', + py, + args : blaster, + env : ['PYTHONPATH=' + pypathdir]) -else - error('MESON_SKIP_TEST: Python3 libraries not found, skipping test.') -endif +py.install_sources(blaster, pure: false) +py.install_sources(blaster, subdir: 'pure') py3_pkg_dep = dependency('python3', method: 'pkg-config', required : false) if py3_pkg_dep.found() python_lib_dir = py3_pkg_dep.get_pkgconfig_variable('libdir') + + # Check we can apply a version constraint + dependency('python3', version: '>=@0@'.format(py_dep.version())) +else + message('Skipped python3 pkg-config test') endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/2 extmodule/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/2 extmodule/test.json" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,13 @@ +{ + "installed": [ + { "type": "python_file", "file": "usr/@PYTHON_PLATLIB@/blaster.py" }, + { "type": "python_lib", "file": "usr/@PYTHON_PLATLIB@/tachyon" }, + { "type": "py_implib", "file": "usr/@PYTHON_PLATLIB@/tachyon" }, + { "type": "python_file", "file": "usr/@PYTHON_PURELIB@/pure/blaster.py" }, + { "type": "python_file", "file": "usr/@PYTHON_PLATLIB@/nested/blaster.py" }, + { "type": "python_lib", "file": "usr/@PYTHON_PLATLIB@/nested/tachyon" }, + { "type": "py_implib", "file": "usr/@PYTHON_PLATLIB@/nested/tachyon" }, + { "type": "python_lib", "file": "usr/lib/tachyon" }, + { "type": "py_implib", "file": "usr/lib/tachyon" } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/3 cython/cytest.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/3 cython/cytest.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/3 cython/cytest.py" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/3 cython/cytest.py" 2021-04-01 21:12:21.000000000 +0000 @@ -1,23 +1,19 @@ #!/usr/bin/env python3 from storer import Storer -import sys s = Storer() if s.get_value() != 0: - print('Initial value incorrect.') - sys.exit(1) + raise SystemExit('Initial value incorrect.') s.set_value(42) if s.get_value() != 42: - print('Setting value failed.') - sys.exit(1) + raise SystemExit('Setting value failed.') try: s.set_value('not a number') - print('Using wrong argument type did not fail.') - sys.exit(1) + raise SystemExit('Using wrong argument type did not fail.') except TypeError: pass diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/3 cython/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/3 cython/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/3 cython/meson.build" 2020-01-07 21:13:21.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/3 cython/meson.build" 2021-04-01 21:12:21.000000000 +0000 @@ -1,20 +1,26 @@ project('cython', 'c', default_options : ['warning_level=3']) -cython = find_program('cython3', required : false) -py3_dep = dependency('python3', required : false) +if meson.backend() != 'ninja' + error('MESON_SKIP_TEST: Ninja backend required') +endif -if cython.found() and py3_dep.found() - py_mod = import('python') - py3 = py_mod.find_installation() - py3_dep = py3.dependency() - subdir('libdir') +cython = find_program('cython', required : false) +if not cython.found() + error('MESON_SKIP_TEST: Cython3 not found.') +endif - test('cython tester', - py3, - args : files('cytest.py'), - env : ['PYTHONPATH=' + pydir] - ) -else - error('MESON_SKIP_TEST: Cython3 or Python3 libraries not found, skipping test.') +py_mod = import('python') +py3 = py_mod.find_installation() +py3_dep = py3.dependency(required: false) +if not py3_dep.found() + error('MESON_SKIP_TEST: Python library not found.') endif + +subdir('libdir') + +test('cython tester', + py3, + args : files('cytest.py'), + env : ['PYTHONPATH=' + pydir] +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/4 custom target depends extmodule/blaster.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/4 custom target depends extmodule/blaster.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/4 custom target depends extmodule/blaster.py" 2019-02-07 09:08:55.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/4 custom target depends extmodule/blaster.py" 2021-04-27 06:49:45.000000000 +0000 @@ -24,9 +24,7 @@ f.write('success') if not isinstance(result, int): - print('Returned result not an integer.') - sys.exit(1) + raise SystemExit('Returned result not an integer.') if result != 1: - print('Returned result {} is not 1.'.format(result)) - sys.exit(1) + raise SystemExit(f'Returned result {result} is not 1.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/4 custom target depends extmodule/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/4 custom target depends extmodule/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/4 custom target depends extmodule/meson.build" 2020-01-07 21:13:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/4 custom target depends extmodule/meson.build" 2021-10-23 16:54:04.000000000 +0000 @@ -3,11 +3,19 @@ # Because Windows Python ships only with optimized libs, # we must build this project the same way. +if meson.backend() != 'ninja' + error('MESON_SKIP_TEST: Ninja backend required') +endif + py_mod = import('python') py3 = py_mod.find_installation() py3_dep = py3.dependency(required : false) cc = meson.get_compiler('c') +if not py3_dep.found() + error('MESON_SKIP_TEST: Python3 libraries not found, skipping test.') +endif + # Copy to the builddir so that blaster.py can find the built tachyon module # FIXME: We should automatically detect this case and append the correct paths # to PYTHONLIBDIR @@ -20,21 +28,18 @@ with open(sys.argv[1], 'rb') as f: assert(f.read() == b'success') ''' -if py3_dep.found() - message('Detected Python version: ' + py3_dep.version()) - if py3_dep.version().version_compare('>=3.8') and cc.get_id() == 'msvc' and cc.version().version_compare('<=19.00.24215.1') - error('MESON_SKIP_TEST: Python modules do not work with Python 3.8 and VS2015 or earlier.') - endif - subdir('ext') - - out_txt = custom_target('tachyon flux', - input : blaster_py, - output : 'out.txt', - command : [py3, '@INPUT@', '-o', '@OUTPUT@'], - depends : pylib, - build_by_default: true) - test('flux', py3, args : ['-c', check_exists, out_txt]) -else - error('MESON_SKIP_TEST: Python3 libraries not found, skipping test.') +message('Detected Python version: ' + py3_dep.version()) +if py3_dep.version().version_compare('>=3.8') and cc.get_id() == 'msvc' and cc.version().version_compare('<=19.00.24215.1') + error('MESON_SKIP_TEST: Python modules do not work with Python 3.8 and VS2015 or earlier.') endif +subdir('ext') + +out_txt = custom_target('tachyon flux', + input : blaster_py, + output : 'out.txt', + command : [py3, '@INPUT@', '-o', '@OUTPUT@'], + depends : pylib, + build_by_default: true) + +test('flux', py3, args : ['-c', check_exists, out_txt]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/5 modules kwarg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/5 modules kwarg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/5 modules kwarg/meson.build" 2020-01-07 21:13:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/5 modules kwarg/meson.build" 2021-10-23 16:54:02.000000000 +0000 @@ -1,7 +1,7 @@ project('python kwarg') py = import('python') -prog_python = py.find_installation('python3', modules : ['setuptools']) +prog_python = py.find_installation('python3', modules : ['distutils']) assert(prog_python.found() == true, 'python not found when should be') prog_python = py.find_installation('python3', modules : ['thisbetternotexistmod'], required : false) assert(prog_python.found() == false, 'python not found but reported as found') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/6 failing subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/6 failing subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/6 failing subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/6 failing subproject/meson.build" 2021-10-23 16:54:07.000000000 +0000 @@ -0,0 +1,5 @@ +project('foo', 'cpp') + +# Regression test for https://github.com/mesonbuild/meson/issues/9038 +dependency('bar', required: false, allow_fallback: true) +python = import('python').find_installation('python3').dependency() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/6 failing subproject/subprojects/bar/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/6 failing subproject/subprojects/bar/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/6 failing subproject/subprojects/bar/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/6 failing subproject/subprojects/bar/meson.build" 2021-08-18 11:22:25.000000000 +0000 @@ -0,0 +1,4 @@ +project('bar', 'cpp') + +python = import('python').find_installation('python3') +dependency('nonexistant-dependency') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/7 install path/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/7 install path/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/7 install path/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/7 install path/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,10 @@ +project('install path', + default_options: [ + 'python.purelibdir=/pure', + 'python.platlibdir=/plat' + ] +) + +py = import('python').find_installation() +py.install_sources('test.py') +py.install_sources('test.py', pure: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/7 install path/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/7 install path/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python/7 install path/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python/7 install path/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "file", "file": "plat/test.py"}, + {"type": "file", "file": "pure/test.py"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python3/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python3/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python3/1 basic/meson.build" 2020-01-07 21:13:14.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python3/1 basic/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -9,13 +9,13 @@ endif py3_purelib = py3_mod.sysconfig_path('purelib') -if not py3_purelib.to_lower().startswith('lib') or not py3_purelib.endswith('site-packages') +if not py3_purelib.to_lower().startswith('lib') or not (py3_purelib.endswith('site-packages') or py3_purelib.endswith('dist-packages')) error('Python3 purelib path seems invalid?') endif # could be 'lib64' or 'Lib' on some systems py3_platlib = py3_mod.sysconfig_path('platlib') -if not py3_platlib.to_lower().startswith('lib') or not py3_platlib.endswith('site-packages') +if not py3_platlib.to_lower().startswith('lib') or not (py3_platlib.endswith('site-packages') or py3_platlib.endswith('dist-packages')) error('Python3 platlib path seems invalid?') endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python3/2 extmodule/blaster.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python3/2 extmodule/blaster.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python3/2 extmodule/blaster.py" 2016-02-27 09:33:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python3/2 extmodule/blaster.py" 2021-04-27 06:49:45.000000000 +0000 @@ -10,5 +10,5 @@ sys.exit(1) if result != 1: - print('Returned result {} is not 1.'.format(result)) + print(f'Returned result {result} is not 1.') sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python3/3 cython/libdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python3/3 cython/libdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python3/3 cython/libdir/meson.build" 2017-01-12 20:52:44.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python3/3 cython/libdir/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -1,6 +1,7 @@ pyx_c = custom_target('storer_pyx', output : 'storer_pyx.c', input : 'storer.pyx', + depend_files : 'cstorer.pxd', command : [cython, '@INPUT@', '-o', '@OUTPUT@'], ) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python3/4 custom target depends extmodule/blaster.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python3/4 custom target depends extmodule/blaster.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/python3/4 custom target depends extmodule/blaster.py" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/python3/4 custom target depends extmodule/blaster.py" 2021-04-27 06:49:45.000000000 +0000 @@ -28,5 +28,5 @@ sys.exit(1) if result != 1: - print('Returned result {} is not 1.'.format(result)) + print(f'Returned result {result} is not 1.') sys.exit(1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/3 kwargs/add.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/3 kwargs/add.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/3 kwargs/add.json" 2019-03-06 20:48:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/3 kwargs/add.json" 2021-04-01 21:13:00.000000000 +0000 @@ -25,5 +25,14 @@ "kwargs": { "license": "BSD" } + }, + { + "type": "kwargs", + "function": "project", + "id": "//", + "operation": "add", + "kwargs": { + "license": "Boost" + } } ] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/3 kwargs/remove.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/3 kwargs/remove.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/3 kwargs/remove.json" 2019-03-06 20:48:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/3 kwargs/remove.json" 2021-04-01 21:13:00.000000000 +0000 @@ -5,7 +5,7 @@ "id": "/", "operation": "set", "kwargs": { - "license": ["GPL", "MIT", "BSD"] + "license": ["GPL", "MIT", "BSD", "Boost"] } }, { @@ -25,5 +25,14 @@ "kwargs": { "license": "BSD" } + }, + { + "type": "kwargs", + "function": "project", + "id": "//", + "operation": "remove", + "kwargs": { + "license": "Boost" + } } ] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/3 kwargs/remove_regex.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/3 kwargs/remove_regex.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/3 kwargs/remove_regex.json" 2019-03-06 20:48:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/3 kwargs/remove_regex.json" 2021-04-01 21:13:00.000000000 +0000 @@ -16,5 +16,14 @@ "kwargs": { "default_options": ["cpp_std=.*"] } + }, + { + "type": "kwargs", + "function": "project", + "id": "//", + "operation": "remove_regex", + "kwargs": { + "default_options": ["buildtype=.*"] + } } ] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/3 kwargs/set.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/3 kwargs/set.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/3 kwargs/set.json" 2019-03-06 20:48:10.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/3 kwargs/set.json" 2021-04-01 21:13:00.000000000 +0000 @@ -2,7 +2,7 @@ { "type": "kwargs", "function": "project", - "id": "/", + "id": "//", "operation": "set", "kwargs": { "version": "0.0.2", diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/6 extra_files/addExtraFiles.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/6 extra_files/addExtraFiles.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/6 extra_files/addExtraFiles.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/6 extra_files/addExtraFiles.json" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,111 @@ +[ + { + "type": "target", + "target": "trivialprog1", + "operation": "extra_files_add", + "sources": ["a2.hpp", "a1.hpp", "a2.hpp"] + }, + { + "type": "target", + "target": "trivialprog2", + "operation": "extra_files_add", + "sources": ["a7.hpp"] + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "extra_files_add", + "sources": ["a5.hpp"] + }, + { + "type": "target", + "target": "trivialprog4", + "operation": "extra_files_add", + "sources": ["a5.hpp"] + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "extra_files_add", + "sources": ["a3.hpp"] + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "extra_files_add", + "sources": ["a6.hpp", "a1.hpp"] + }, + { + "type": "target", + "target": "trivialprog8", + "operation": "extra_files_add", + "sources": ["a2.hpp", "a7.hpp"] + }, + { + "type": "target", + "target": "trivialprog9", + "operation": "extra_files_add", + "sources": ["a9.hpp", "a8.hpp"] + }, + { + "type": "target", + "target": "trivialprog10", + "operation": "extra_files_add", + "sources": ["a4.hpp", "a1.hpp"] + }, + { + "type": "target", + "target": "trivialprog0", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog1", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog2", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog4", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog6", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog8", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog9", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog10", + "operation": "info" + } +] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/6 extra_files/info.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/6 extra_files/info.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/6 extra_files/info.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/6 extra_files/info.json" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,57 @@ +[ + { + "type": "target", + "target": "trivialprog0", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog1", + "operation": "info" + }, + { + "type": "target", + "target": "exe2", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "info" + }, + { + "type": "target", + "target": "exe4", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "info" + }, + { + "type": "target", + "target": "exe6", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "info" + }, + { + "type": "target", + "target": "exe8", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog9", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog10", + "operation": "info" + } +] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/6 extra_files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/6 extra_files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/6 extra_files/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/6 extra_files/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,21 @@ +project('rewritetest', 'cpp') + +ef1 = ['main.hpp', 'fileA.hpp'] +ef2 = files(['fileB.hpp', 'fileC.hpp']) +ef3 = ef1 +ef4 = [ef3] +ef5 = [] + +# Magic comment + +exe0 = executable('trivialprog0', 'main.cpp', extra_files : ef1 + ef2) +exe1 = executable('trivialprog1', 'main.cpp', extra_files : ef1) +exe2 = executable('trivialprog2', 'main.cpp', extra_files : [ef2]) +exe3 = executable('trivialprog3', 'main.cpp', extra_files : ['main.hpp', 'fileA.hpp']) +exe4 = executable('trivialprog4', 'main.cpp', extra_files : ['main.hpp', ['fileA.hpp']]) +exe5 = executable('trivialprog5', 'main.cpp', extra_files : [ef2, 'main.hpp']) +exe6 = executable('trivialprog6', 'main.cpp', extra_files : ef3) +executable('trivialprog7', 'main.cpp', extra_files : ef4) +exe8 = executable('trivialprog8', 'main.cpp', extra_files : []) +exe9 = executable('trivialprog9', 'main.cpp') +exe10 = executable('trivialprog10', 'main.cpp', extra_files : ef5) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/6 extra_files/rmExtraFiles.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/6 extra_files/rmExtraFiles.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rewrite/6 extra_files/rmExtraFiles.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rewrite/6 extra_files/rmExtraFiles.json" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,93 @@ +[ + { + "type": "target", + "target": "trivialprog1", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog4", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "extra_files_rm", + "sources": ["fileB.hpp"] + }, + { + "type": "target", + "target": "trivialprog6", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "extra_files_rm", + "sources": ["fileA.hpp"] + }, + { + "type": "target", + "target": "trivialprog0", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog1", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog2", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog3", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog4", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog5", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog6", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog7", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog8", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog9", + "operation": "info" + }, + { + "type": "target", + "target": "trivialprog10", + "operation": "info" + } +] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/10 language stds/2015.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/10 language stds/2015.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/10 language stds/2015.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/10 language stds/2015.rs" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,3 @@ +trait Foo { + fn foo(&self, Box); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/10 language stds/2018.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/10 language stds/2018.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/10 language stds/2018.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/10 language stds/2018.rs" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,9 @@ +const fn foo(x: i32) -> i32 { + return x + 1; +} + +const VALUE: i32 = foo(-1); + +pub fn main() { + std::process::exit(VALUE); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/10 language stds/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/10 language stds/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/10 language stds/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/10 language stds/meson.build" 2021-10-23 16:52:53.000000000 +0000 @@ -0,0 +1,18 @@ +project('rust std options', 'rust') + +# this only works in 2018 +new = executable( + 'new', + '2018.rs', + override_options : ['rust_std=2018'], +) + +# this only works in 2015 +old = static_library( + 'old', + '2015.rs', + override_options : ['rust_std=2015'], +) + + +test('2018 std', new) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/11 generated main/generated_lib_main.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/11 generated main/generated_lib_main.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/11 generated main/generated_lib_main.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/11 generated main/generated_lib_main.rs" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,5 @@ +extern crate static_lib_generated as lib; + +fn main() { + lib::libfun(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/11 generated main/gen.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/11 generated main/gen.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/11 generated main/gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/11 generated main/gen.py" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +import argparse + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('out') + parser.add_argument('--mode', choices=['main', 'lib'], default='main') + args = parser.parse_args() + + with open(args.out, 'w') as f: + if args.mode == 'main': + f.write('fn main() { println!("I prefer tarnish, actually.") }') + elif args.mode == 'lib': + f.write('pub fn libfun() { println!("I prefer tarnish, actually.") }') + + +if __name__ == "__main__": + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/11 generated main/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/11 generated main/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/11 generated main/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/11 generated main/meson.build" 2021-10-23 16:52:55.000000000 +0000 @@ -0,0 +1,21 @@ +project('generated rust main', 'rust') + +gen = find_program('gen.py') + +c = custom_target( + 'custom_target', + command : [gen, '@OUTPUT@'], + output : ['main.rs'], +) + +executable('custom_target_main', c) +executable('custom_target_index_main', c[0]) + +gener = generator(gen, arguments : ['@OUTPUT@'], output : '@BASENAME@.rs') +# Doesn't actually use gen.py as input, just a limitation of generators +executable('generator_main', gener.process(['gen.py'])) + +subdir('sub') +executable('custom_target_subdir_main', s) + +executable('link_with_generated_lib', 'generated_lib_main.rs', link_with : lib) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/11 generated main/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/11 generated main/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/11 generated main/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/11 generated main/sub/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,13 @@ +s = custom_target( + 'subdir_target', + command : [gen, '@OUTPUT@'], + output : ['main.rs'], +) + +l = custom_target( + 'lib_target', + command : [gen, '@OUTPUT@', '--mode', 'lib'], + output : ['lib.rs'], +) + +lib = static_library('static_lib_generated', l) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/include/other.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/include/other.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/include/other.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/include/other.h" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,6 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2021 Intel Corporation + +# pragma once + +#include diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,82 @@ +# SPDX-license-identifer: Apache-2.0 +# Copyright © 2021 Intel Corporation + +project('rustmod bindgen', ['c', 'rust']) + +prog_bindgen = find_program('bindgen', required : false) +if not prog_bindgen.found() + error('MESON_SKIP_TEST bindgen not found') +endif + +# This seems to happen on windows when libclang.dll is not in path or is not +# valid. We must try to process a header file for this to work. +# +# See https://github.com/rust-lang/rust-bindgen/issues/1797 +result = run_command(prog_bindgen, 'include/other.h', check: false) +if result.returncode() != 0 + error('MESON_SKIP_TEST bindgen does not seem to work') +endif + +# This is to test the include_directories argument to bindgen +inc = include_directories('include') + +c_lib = static_library('clib', 'src/source.c', include_directories : inc) + +rust = import('unstable-rust') + +gen = rust.bindgen( + input : 'src/header.h', + output : 'header.rs', + include_directories : inc, +) + +# see: https://github.com/mesonbuild/meson/issues/8160 +f = configure_file( + input : 'src/main.rs', + output : 'main.rs', + copy : true, +) + +rust_bin = executable( + 'rust_bin', + [f, gen], + link_with : c_lib, +) + +test('main', rust_bin) + +# Test a generated header +gen_h = custom_target( + 'gen.h', + command : [find_program('src/gen_header.py'), '@INPUT@', '@OUTPUT@'], + output : 'gen.h', + input : 'src/header.h' +) + +gen2_h = custom_target( + 'other.h', + command : [find_program('src/gen_header.py'), '@INPUT@', '@OUTPUT@'], + output : 'other.h', + input : 'include/other.h' +) + +gen_rs = rust.bindgen( + input : [gen_h, gen2_h], + output : 'gen.rs', +) + +f = configure_file( + input : 'src/main2.rs', + output : 'main2.rs', + copy : true, +) + +rust_bin2 = executable( + 'rust_bin2', + [f, gen_rs], + link_with : c_lib, +) + +test('generated header', rust_bin2) + +subdir('sub') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/gen_header.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/gen_header.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/gen_header.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/gen_header.py" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# SPDX-license-identifer: Apache-2.0 +# Copyright © 2021 Intel Corporation + +import argparse +import shutil + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('input') + parser.add_argument('output') + args = parser.parse_args() + + shutil.copy2(args.input, args.output) + + +if __name__ == "__main__": + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/header.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/header.h" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,8 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2021 Intel Corporation + +#pragma once + +#include "other.h" + +int32_t add(const int32_t, const int32_t); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/main2.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/main2.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/main2.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/main2.rs" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,15 @@ + +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2021 Intel Corporation + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!("gen.rs"); + +fn main() { + unsafe { + std::process::exit(add(0, 0)); + }; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/main.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/main.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/main.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/main.rs" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,14 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2021 Intel Corporation + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!("header.rs"); + +fn main() { + unsafe { + std::process::exit(add(0, 0)); + }; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/src/source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/src/source.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,8 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2021 Intel Corporation + +#include "header.h" + +int32_t add(const int32_t first, const int32_t second) { + return first + second; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/12 bindgen/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/12 bindgen/sub/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,39 @@ +gen_rs3 = rust.bindgen( + input : [gen_h, gen2_h], + output : 'gen.rs', +) + +f3 = configure_file( + input : '../src/main2.rs', + output : 'main3.rs', + copy : true, +) + +rust_bin3 = executable( + 'rust_bin3', + [f3, gen_rs3], + link_with : c_lib, +) + +test('generated header (subdir)', rust_bin3) + +gen4 = rust.bindgen( + input : '../src/header.h', + output : 'header.rs', + include_directories : inc, +) + +# see: https://github.com/mesonbuild/meson/issues/8160 +f4 = configure_file( + input : '../src/main.rs', + output : 'main.rs', + copy : true, +) + +rust_bin4 = executable( + 'rust_bin_subdir', + [f4, gen4], + link_with : c_lib, +) + +test('static header (subdir)', rust_bin4) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/c_accessing_zlib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/c_accessing_zlib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/c_accessing_zlib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/c_accessing_zlib.c" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include +#include + +void c_accessing_zlib(void) { + struct z_stream_s zstream; + printf("Hello from C!\n"); + memset(&zstream, 0, sizeof(zstream)); + inflateInit(&zstream); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,23 @@ +project('rust linking to c using dependency', 'c', 'rust') + +if host_machine.system() == 'darwin' + error('MESON_SKIP_TEST: does not work right on macos, please fix!') +endif + +dep_zlib = dependency('zlib', static : get_option('static'), method : get_option('method'), required : false) +if not dep_zlib.found() + error('MESON_SKIP_TEST: Could not find a @0@ zlib'.format(get_option('static') ? 'static' : 'shared')) +endif + +l = static_library( + 'c_accessing_zlib', + 'c_accessing_zlib.c', + dependencies: [dep_zlib], +) + +e = executable( + 'prog', 'prog.rs', + link_with : l, +) + +test('cdepstest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/meson_options.txt" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,2 @@ +option('static', type : 'boolean') +option('method', type : 'string') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/prog.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/prog.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/prog.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/prog.rs" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,9 @@ +extern "C" { + fn c_accessing_zlib(); +} + +fn main() { + unsafe { + c_accessing_zlib(); + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/13 external c dependencies/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/13 external c dependencies/test.json" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,18 @@ +{ + "matrix": { + "options": { + "static": [ + { "val": true }, + { "val": false } + ], + "method": [ + { "val": "pkg-config" }, + { "val": "cmake" }, + { "val": "system" } + ] + }, + "exclude": [ + { "static": true, "method": "pkg-config" } + ] + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,24 @@ +project('rust linking to libm', 'c', 'rust') + +if host_machine.system() == 'darwin' + error('MESON_SKIP_TEST: does not work right on macos, please fix!') +endif + +cc = meson.get_compiler('c') +dep_m = cc.find_library('m', required : false, static : get_option('static')) +if not dep_m.found() + error('MESON_SKIP_TEST: Could not find a @0@ libm'.format(get_option('static') ? 'static' : 'shared')) +endif + +librs_math = static_library( + 'rs_math', + 'rs_math.rs', + dependencies : [dep_m], +) + +e = executable( + 'prog', 'prog.rs', + link_with : [librs_math], +) + +test('cdepstest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/meson_options.txt" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,2 @@ +option('static', type : 'boolean') +option('method', type : 'string') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/prog.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/prog.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/prog.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/prog.rs" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,5 @@ +extern crate rs_math; + +fn main() { + assert_eq!(rs_math::rs_log2(8.0), 3.0); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/rs_math.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/rs_math.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/rs_math.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/rs_math.rs" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,12 @@ +#![crate_name = "rs_math"] + +use std::os::raw::c_double; + +extern "C" { + fn log2(n: c_double) -> c_double; +} + +#[no_mangle] +pub extern fn rs_log2(n: c_double) -> c_double { + unsafe { log2(n) } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/14 external libm/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/14 external libm/test.json" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "matrix": { + "options": { + "static": [ + { "val": true }, + { "val": false } + ] + } + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/adder.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/adder.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/adder.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/adder.c" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,18 @@ +#include +#include + +struct _Adder { + int number; +}; + +adder* adder_create(int number) { + adder *a = malloc(sizeof(struct _Adder)); + a->number = number; + return a; +} + +// adder_add is implemented in the Rust file. + +void adder_destroy(adder *a) { + free(a); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/adder.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/adder.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/adder.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/adder.h" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,34 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined _WIN32 || defined __CYGWIN__ + #if defined BUILDING_ADDER + #define DLL_PUBLIC __declspec(dllexport) + #else + #define DLL_PUBLIC __declspec(dllimport) + #endif +#else + #if defined __GNUC__ + #if defined BUILDING_ADDER + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #define DLL_PUBLIC + #endif + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +typedef struct _Adder adder; + +DLL_PUBLIC extern adder* adder_create(int number); +DLL_PUBLIC extern int adder_add(adder *a, int number); +DLL_PUBLIC extern void adder_destroy(adder*); + +#ifdef __cplusplus +} +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/adder.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/adder.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/adder.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/adder.rs" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,9 @@ +#[repr(C)] +pub struct Adder { + pub number: i32 +} + +#[no_mangle] +pub extern fn adder_add(a: &Adder, number: i32) -> i32 { + return a.number + number; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/addertest.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/addertest.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/addertest.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/addertest.c" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,12 @@ +#include +#include + +int main(int argc, char **argv) { + adder *a = adder_create(3); + int result = adder_add(a, 4); + if(result != 7) { + return 1; + } + adder_destroy(a); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/15 polyglot sharedlib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/15 polyglot sharedlib/meson.build" 2021-10-23 16:53:08.000000000 +0000 @@ -0,0 +1,20 @@ +project('adder', 'c', 'rust', version: '1.0.0') + +if build_machine.system() != 'linux' + error('MESON_SKIP_TEST, this test only works on Linux. Patches welcome.') +endif + +thread_dep = dependency('threads') +dl_dep = meson.get_compiler('c').find_library('dl', required: false) +m_dep = meson.get_compiler('c').find_library('m', required: false) + +rl = static_library('radder', 'adder.rs', rust_crate_type: 'staticlib') + +l = shared_library('adder', 'adder.c', + c_args: '-DBUILDING_ADDER', + link_with: rl, + version: '1.0.0', + soversion: '1', + link_args: '-Wl,-u,adder_add', # Ensure that Rust code is not removed as unused. + dependencies: [thread_dep, dl_dep, m_dep]) +test('adder', executable('addertest', 'addertest.c', link_with: l)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/lib.c" 2021-06-07 17:35:22.000000000 +0000 @@ -0,0 +1,6 @@ +#include +#include "lib.h" + +void c_func(void) { + printf("This is a " MODE " C library\n"); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/lib.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/lib.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/lib.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/lib.h" 2021-06-07 17:35:22.000000000 +0000 @@ -0,0 +1,22 @@ +#pragma once + +#if defined _WIN32 || defined __CYGWIN__ + #if defined BUILDING_ADDER + #define DLL_PUBLIC __declspec(dllexport) + #else + #define DLL_PUBLIC __declspec(dllimport) + #endif +#else + #if defined __GNUC__ + #if defined BUILDING_ADDER + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #define DLL_PUBLIC + #endif + #else + #pragma message("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +DLL_PUBLIC void c_func(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/main.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/main.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/main.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/main.rs" 2021-06-07 17:35:22.000000000 +0000 @@ -0,0 +1,9 @@ +extern "C" { + fn c_func(); +} + +fn main() { + unsafe { + c_func(); + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/meson.build" 2021-10-23 16:53:05.000000000 +0000 @@ -0,0 +1,14 @@ +project('internal dependencies', 'c', 'rust') + +test_prog = find_program('test.py') + +static = static_library('static', 'lib.c', c_args : '-DMODE="static"') +exe = executable('static', 'main.rs', link_with : static) +test('static linkage', test_prog, args : [exe, 'This is a static C library']) + +# Shared linkage with rust doesn't work on macOS with meson, yet +if host_machine.system() != 'darwin' + shared = shared_library('shared', 'lib.c', c_args : '-DMODE="shared"') + exe = executable('shared', 'main.rs', link_with : shared) + test('shared linkage', test_prog, args : [exe, 'This is a shared C library']) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/test.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/test.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/16 internal c dependencies/test.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/16 internal c dependencies/test.py" 2021-06-07 17:35:22.000000000 +0000 @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import argparse +import subprocess +import sys + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('command') + parser.add_argument('expected') + args = parser.parse_args() + + out = subprocess.run(args.command, stdout=subprocess.PIPE) + actual = out.stdout.decode().strip() + + if args.expected != actual: + print('expected:', args.expected, file=sys.stderr) + print('actual: ', actual, file=sys.stderr) + sys.exit(1) + sys.exit(0) + + +if __name__ == "__main__": + main() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/branch.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/branch.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/branch.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/branch.rs" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,4 @@ +#[no_mangle] +pub extern "C" fn what_have_we_here() -> i32 { + leaf::HOW_MANY * leaf::HOW_MANY +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/leaf.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/leaf.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/leaf.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/leaf.rs" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1 @@ +pub const HOW_MANY: i32 = 5; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/meson.build" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,8 @@ +project('staticlib link staticlib', 'c', 'rust') + +leaf = static_library('leaf', 'leaf.rs', rust_crate_type : 'rlib') +# Even though leaf is linked using link_with, this gets implicitly promoted to link_whole because +# it is an internal Rust project. +branch = static_library('branch', 'branch.rs', link_with: leaf, rust_crate_type : 'staticlib', install : true) +e = executable('prog', 'prog.c', link_with : branch, install : true) +test('linktest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/prog.c" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +int what_have_we_here(); + +int main(void) { + printf("printing %d\n", what_have_we_here()); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/17 staticlib link staticlib/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/17 staticlib link staticlib/test.json" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/lib/libbranch.a"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/clippy.toml" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/clippy.toml" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/clippy.toml" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/clippy.toml" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +blacklisted-names = ["foo"] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/installed_files.txt" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -usr/bin/program?exe -?msvc:usr/bin/program.pdb -usr/bin/program2?exe -?msvc:usr/bin/program2.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/meson.build" 2020-01-07 21:12:15.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/meson.build" 2022-02-14 19:03:13.000000000 +0000 @@ -1,6 +1,6 @@ project('rustprog', 'rust') -e = executable('program', 'prog.rs', +e = executable('rust-program', 'prog.rs', rust_args : ['-C', 'lto'], # Just a test install : true ) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/prog.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/prog.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/prog.rs" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/prog.rs" 2021-11-02 19:58:07.000000000 +0000 @@ -1,3 +1,4 @@ fn main() { - println!("rust compiler is working"); + let foo = "rust compiler is working"; + println!("{}", foo); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/subdir/meson.build" 2017-04-04 16:41:09.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/subdir/meson.build" 2022-02-14 19:03:13.000000000 +0000 @@ -1,2 +1,2 @@ -e = executable('program2', 'prog.rs', install : true) +e = executable('rust-program2', 'prog.rs', install : true) test('rusttest2', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/1 basic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/1 basic/test.json" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/rust-program"}, + {"type": "pdb", "file": "usr/bin/rust-program"}, + {"type": "exe", "file": "usr/bin/rust-program2"}, + {"type": "pdb", "file": "usr/bin/rust-program2"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/2 sharedlib/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/2 sharedlib/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/2 sharedlib/installed_files.txt" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/2 sharedlib/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb -?gcc:usr/lib/libstuff.so -?msvc:usr/bin/stuff.dll -?msvc:usr/bin/stuff.pdb -?msvc:usr/lib/stuff.dll.lib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/2 sharedlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/2 sharedlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/2 sharedlib/meson.build" 2020-01-07 21:12:11.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/2 sharedlib/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,5 +1,9 @@ project('rust shared library', 'rust') +if host_machine.system() == 'darwin' + error('MESON_SKIP_TEST: does not work right on macos, please fix!') +endif + l = shared_library('stuff', 'stuff.rs', install : true) e = executable('prog', 'prog.rs', link_with : l, install : true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/2 sharedlib/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/2 sharedlib/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/2 sharedlib/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/2 sharedlib/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff.dll"}, + {"type": "pdb", "file": "usr/bin/stuff"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff.dll.lib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/3 staticlib/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/3 staticlib/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/3 staticlib/installed_files.txt" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/3 staticlib/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb -usr/lib/libstuff.rlib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/3 staticlib/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/3 staticlib/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/3 staticlib/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/3 staticlib/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/lib/libstuff.rlib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/4 polyglot/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/4 polyglot/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/4 polyglot/installed_files.txt" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/4 polyglot/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb -?gcc:usr/lib/libstuff.so -?msvc:usr/bin/stuff.dll -?msvc:usr/lib/stuff.dll.lib -?msvc:usr/bin/stuff.pdb - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/4 polyglot/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/4 polyglot/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/4 polyglot/meson.build" 2020-01-07 21:12:12.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/4 polyglot/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,5 +1,9 @@ project('rust and c polyglot executable', 'c', 'rust') -l = library('stuff', 'stuff.rs', rust_crate_type: 'cdylib', install : true) +if host_machine.system() == 'darwin' + error('MESON_SKIP_TEST: does not work right on macos, please fix!') +endif + +l = shared_library('stuff', 'stuff.rs', rust_crate_type: 'cdylib', install : true) e = executable('prog', 'prog.c', link_with : l, install : true) test('polyglottest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/4 polyglot/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/4 polyglot/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/4 polyglot/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/4 polyglot/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff.dll.lib"}, + {"type": "pdb", "file": "usr/bin/stuff"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/5 polyglot static/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/5 polyglot static/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/5 polyglot static/installed_files.txt" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/5 polyglot static/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb -usr/lib/libstuff.a diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/5 polyglot static/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/5 polyglot static/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/5 polyglot static/meson.build" 2020-01-07 21:12:17.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/5 polyglot static/meson.build" 2021-12-22 17:54:40.000000000 +0000 @@ -2,10 +2,11 @@ deps = [ meson.get_compiler('c').find_library('dl', required: false), + meson.get_compiler('c').find_library('m', required: false), dependency('threads'), ] -extra_winlibs = meson.get_compiler('c').get_id() == 'msvc' ? ['userenv.lib', 'ws2_32.lib'] : [] +extra_winlibs = meson.get_compiler('c').get_id() in ['msvc', 'clang-cl'] ? ['userenv.lib', 'ws2_32.lib', 'bcrypt.lib'] : [] l = static_library('stuff', 'stuff.rs', rust_crate_type : 'staticlib', install : true) e = executable('prog', 'prog.c', diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/5 polyglot static/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/5 polyglot static/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/5 polyglot static/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/5 polyglot static/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/lib/libstuff.a"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/6 named staticlib/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/6 named staticlib/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/6 named staticlib/installed_files.txt" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/6 named staticlib/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb -usr/lib/libnamed_stuff.rlib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/6 named staticlib/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/6 named staticlib/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/6 named staticlib/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/6 named staticlib/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/lib/libnamed_stuff.rlib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/7 private crate collision/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/7 private crate collision/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/7 private crate collision/installed_files.txt" 2019-06-27 16:43:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/7 private crate collision/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/bin/prog?exe -?msvc:usr/bin/prog.pdb -usr/lib/librand.rlib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/7 private crate collision/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/7 private crate collision/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/7 private crate collision/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/7 private crate collision/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/prog"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/lib/librand.rlib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/9 unit tests/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/9 unit tests/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/9 unit tests/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/9 unit tests/meson.build" 2021-10-23 16:52:53.000000000 +0000 @@ -0,0 +1,43 @@ +project('rust unit tests', 'rust') + +t = executable( + 'rust_test', + ['test.rs'], + rust_args : ['--test'], +) + +test( + 'rust test (should fail)', + t, + protocol : 'rust', + suite : ['foo'], + should_fail : true, +) + +test( + 'rust test (should pass)', + t, + args : ['--skip', 'test_add_intentional_fail'], + protocol : 'rust', + suite : ['foo'], +) + + +test( + 'rust test (should skip)', + t, + args : ['--skip', 'test_add'], + protocol : 'rust', + suite : ['foo'], +) + +exe = executable('rust_exe', ['test2.rs', 'test.rs']) + +rust = import('unstable-rust') +rust.test('rust_test_from_exe', exe, should_fail : true) + +lib = static_library('rust_static', ['test.rs']) +rust.test('rust_test_from_static', lib, args: ['--skip', 'test_add_intentional_fail']) + +lib = shared_library('rust_shared', ['test.rs']) +rust.test('rust_test_from_shared', lib, args: ['--skip', 'test_add_intentional_fail']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/9 unit tests/test2.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/9 unit tests/test2.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/9 unit tests/test2.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/9 unit tests/test2.rs" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,11 @@ +mod test; +use std::env; + +fn main() { + let args: Vec = env::args().collect(); + let first = args[1].parse::().expect("Invliad value for first argument."); + let second = args[2].parse::().expect("Invliad value for second argument."); + + let new = test::add(first, second); + println!("New value: {}", new); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/9 unit tests/test.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/9 unit tests/test.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/rust/9 unit tests/test.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/rust/9 unit tests/test.rs" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,24 @@ +pub fn add(a: i32, b: i32) -> i32 { + return a + b; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_add() { + assert_eq!(add(1, 2), 3); + } + + #[test] + fn test_add_intentional_fail() { + assert_eq!(add(1, 2), 5); + } + + #[test] + #[ignore] + fn test_add_intentional_fail2() { + assert_eq!(add(1, 7), 5); + } +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/swift/1 exe/main.swift" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/swift/1 exe/main.swift" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/swift/1 exe/main.swift" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/swift/1 exe/main.swift" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +print("Swift executable is working.") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/swift/1 exe/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/swift/1 exe/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/swift/1 exe/meson.build" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/swift/1 exe/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -1,3 +1,3 @@ project('swift exe', 'swift') -test('swifttest', executable('swifttest', 'prog.swift')) +test('swifttest', executable('swifttest', 'main.swift')) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/swift/1 exe/prog.swift" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/swift/1 exe/prog.swift" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/swift/1 exe/prog.swift" 2016-01-23 18:52:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/swift/1 exe/prog.swift" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -print("Swift executable is working.") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/100 custom target name/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/100 custom target name/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/100 custom target name/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/100 custom target name/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,14 @@ +project('custom target name', 'c') + +python = import('python').find_installation() + +# Name argument is optional and should default to 'file.txt' +custom_target( + input: 'file.txt.in', + output: '@BASENAME@', + command: [python, '--version'], + build_by_default: true, + capture: true, +) + +subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/100 custom target name/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/100 custom target name/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/100 custom target name/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/100 custom target name/subdir/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,9 @@ +# Name argument is optional and should default to 'file.txt', but should be +# displayed as 'subdir/file.txt' by ninja. +custom_target( + input: '../file.txt.in', + output: ['@BASENAME@'], + command: [python, '--version'], + build_by_default: true, + capture: true, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/101 relative find program/foo.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/101 relative find program/foo.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/101 relative find program/foo.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/101 relative find program/foo.py" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +exit(0) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/101 relative find program/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/101 relative find program/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/101 relative find program/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/101 relative find program/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +project('relative find program') + +subdir('subdir') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/101 relative find program/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/101 relative find program/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/101 relative find program/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/101 relative find program/subdir/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,2 @@ +prog = find_program('./foo.py', required: false) +assert(not prog.found()) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/102 rlib linkage/lib2.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/102 rlib linkage/lib2.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/102 rlib linkage/lib2.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/102 rlib linkage/lib2.rs" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,5 @@ +use lib; + +pub fn fun() { + lib::fun(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/102 rlib linkage/main.rs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/102 rlib linkage/main.rs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/102 rlib linkage/main.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/102 rlib linkage/main.rs" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,5 @@ +use lib2::fun; + +fn main() { + fun(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/102 rlib linkage/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/102 rlib linkage/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/102 rlib linkage/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/102 rlib linkage/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,22 @@ +project('rlib linkage', 'rust', default_options : ['rust_std=2018']) + +lib = static_library( + 'lib', + 'lib.rs', + rust_crate_type : 'rlib', +) + +lib2 = static_library( + 'lib2', + 'lib2.rs', + rust_crate_type : 'rlib', + link_with : lib, +) + +exe = executable( + 'exe', + 'main.rs', + link_with : lib2, +) + +test('main', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/103 python without pkgconfig/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/103 python without pkgconfig/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/103 python without pkgconfig/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/103 python without pkgconfig/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,4 @@ +project('python wihtout pkgconfig', 'c') + +# This unit test is ran with PKG_CONFIG=notfound +import('python').find_installation().dependency() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/11 cross prog/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/11 cross prog/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/11 cross prog/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/11 cross prog/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -4,9 +4,9 @@ cross_exe = find_program('sometool.py') cross_other_exe = find_program('someothertool.py') -native_out = run_command(native_exe).stdout().strip() -cross_out = run_command(cross_exe).stdout().strip() -cross_other_out = run_command(cross_other_exe).stdout().strip() +native_out = run_command(native_exe, check: true).stdout().strip() +cross_out = run_command(cross_exe, check: true).stdout().strip() +cross_other_out = run_command(cross_other_exe, check: true).stdout().strip() assert(native_out == 'native', 'Native output incorrect:' + native_out) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/11 cross prog/some_cross_tool.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/11 cross prog/some_cross_tool.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/11 cross prog/some_cross_tool.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/11 cross prog/some_cross_tool.py" 2021-04-27 06:49:45.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -from __future__ import print_function print('cross') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/11 cross prog/sometool.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/11 cross prog/sometool.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/11 cross prog/sometool.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/11 cross prog/sometool.py" 2021-04-27 06:49:45.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -from __future__ import print_function print('native') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -2,4 +2,3 @@ subproject('s1') subproject('s2') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s1/subprojects/s3/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s1/subprojects/s3/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s1/subprojects/s3/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s1/subprojects/s3/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,3 @@ project('s3', 'c') l = static_library('s3', 's3.c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s1/subprojects/scommon/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s1/subprojects/scommon/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s1/subprojects/scommon/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s1/subprojects/scommon/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,3 @@ project('scommon', 'c') clib = static_library('scommon', 'scommon_broken.c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s2/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s2/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -3,4 +3,3 @@ sc = subproject('scommon') executable('s2', 's2.c', link_with : sc.get_variable('clib')) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s2/subprojects/athing.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s2/subprojects/athing.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s2/subprojects/athing.wrap" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s2/subprojects/athing.wrap" 2020-08-15 16:27:05.000000000 +0000 @@ -1,2 +1 @@ -The contents of this wrap file are never evaluated so they -can be anything. +[wrap-file] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s2/subprojects/scommon/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s2/subprojects/scommon/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/12 promote/subprojects/s2/subprojects/scommon/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/12 promote/subprojects/s2/subprojects/scommon/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,3 @@ project('scommon', 'c') clib = static_library('scommon', 'scommon_ok.c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/meson.build" 2021-11-25 22:00:46.000000000 +0000 @@ -1,7 +1,12 @@ project('prebuilt shared library', 'c') +search_dir = get_option('search_dir') +if search_dir == 'auto' + search_dir = meson.current_source_dir() +endif + cc = meson.get_compiler('c') -shlib = cc.find_library('alexandria', dirs : meson.current_source_dir()) +shlib = cc.find_library('alexandria', dirs : search_dir) exe = executable('patron', 'patron.c', dependencies : shlib) test('visitation', exe) @@ -12,3 +17,22 @@ dependencies : d) test('another', exe2) +stlib = static_library( + 'rejected', + 'rejected.c', + dependencies : shlib, +) + +rejected = executable( + 'rejected', + 'rejected_main.c', + link_with : stlib, +) +test('rejected', rejected) + +rejected_whole = executable( + 'rejected_whole', + 'rejected_main.c', + link_whole : stlib, +) +test('rejected (whole archive)', rejected_whole) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/meson_options.txt" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1 @@ +option('search_dir', type : 'string', value : 'auto') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/rejected.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/rejected.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/rejected.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/rejected.c" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,8 @@ +#include "rejected.h" + +void say(void) { + printf("You are standing outside the Great Library of Alexandria.\n"); + printf("You decide to go inside.\n\n"); + alexandria_visit(); + printf("The librarian tells you it's time to leave\n"); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/rejected.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/rejected.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/rejected.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/rejected.h" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,6 @@ +#include +#include + +#pragma once + +void say(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/rejected_main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/rejected_main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/17 prebuilt shared/rejected_main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/17 prebuilt shared/rejected_main.c" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,6 @@ +#include "rejected.h" + +int main(void) { + say(); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/1 soname/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/1 soname/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/1 soname/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/1 soname/main.c" 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,5 @@ +int versioned_func (void); + +int main (void) { + return versioned_func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/1 soname/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/1 soname/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/1 soname/meson.build" 2016-12-29 21:18:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/1 soname/meson.build" 2021-11-25 22:00:46.000000000 +0000 @@ -20,3 +20,16 @@ install : true, soversion : '7.8.9', version : '7.8.9') + +shared_module('some_module', 'versioned.c', + install: true) + +module1 = shared_module('linked_module1', 'versioned.c', + install: true) + +module2 = shared_module('linked_module2', 'versioned.c', + install: true) +module2_dep = declare_dependency(link_with: module2) + +executable('main1', 'main.c', link_with: module1) +executable('main2', 'main.c', dependencies: module2_dep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/22 warning location/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/22 warning location/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/22 warning location/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/22 warning location/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,4 @@ -project('warning location', 'c', invalid: 'cheese') +project('warning location', 'c') a = library('liba', 'a.c') b = library('libb', 'b.c') executable('main', 'main.c', link_with: a, link_with: b) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/24 compiler run_command/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/24 compiler run_command/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/24 compiler run_command/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/24 compiler run_command/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -4,7 +4,7 @@ # This test only checks that the compiler object can be passed to # run_command(). If the compiler has been launched, it is expected # to output something either to stdout or to stderr. -result = run_command(cc, '--version') +result = run_command(cc, '--version', check: false) if result.stdout() == '' and result.stderr() == '' error('No output in stdout and stderr. Did the compiler run at all?') endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/27 pkgconfig usage/dependee/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/27 pkgconfig usage/dependee/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/27 pkgconfig usage/dependee/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/27 pkgconfig usage/dependee/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -4,4 +4,3 @@ executable('pkguser', 'pkguser.c', dependencies : pkgdep) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/27 pkgconfig usage/dependency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/27 pkgconfig usage/dependency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/27 pkgconfig usage/dependency/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/27 pkgconfig usage/dependency/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,10 +1,10 @@ -project('pkgconfig dep', 'c', +project('pkgconfig dep', 'c', version : '1.0.0') # This is not used in the code, only to check that it does not # leak out to --libs. glib_dep = dependency('glib-2.0') - + pkgconfig = import('pkgconfig') intlib = static_library('libpkgdep-int', 'privatelib.c') @@ -15,7 +15,7 @@ install : true) install_headers('pkgdep.h') - + pkgconfig.generate( filebase : 'libpkgdep', name : 'Libpkgdep', diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/2 testsetups/envcheck.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/2 testsetups/envcheck.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/2 testsetups/envcheck.py" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/2 testsetups/envcheck.py" 2021-11-02 19:58:07.000000000 +0000 @@ -2,4 +2,4 @@ import os -assert('PATH' in os.environ) +assert 'PATH' in os.environ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/2 testsetups/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/2 testsetups/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/2 testsetups/meson.build" 2018-08-25 08:05:43.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/2 testsetups/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -12,7 +12,7 @@ env : env) buggy = executable('buggy', 'buggy.c', 'impl.c') -test('Test buggy', buggy) +test('Test buggy', buggy, suite: ['buggy']) envcheck = find_program('envcheck.py') test('test-env', envcheck) @@ -23,3 +23,4 @@ add_test_setup('onlyenv3', env : ['TEST_ENV=1']) add_test_setup('wrapper', exe_wrapper : [vg, '--error-exitcode=1']) add_test_setup('timeout', timeout_multiplier : 20) +add_test_setup('good', exclude_suites : 'buggy') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/32 pkgconfig use libraries/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/32 pkgconfig use libraries/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/32 pkgconfig use libraries/lib/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/32 pkgconfig use libraries/lib/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -12,5 +12,3 @@ libraries: [b], subdirs: ['.'] ) - - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/meson.build" 2018-12-09 14:27:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/meson.build" 2021-04-27 06:49:45.000000000 +0000 @@ -5,3 +5,6 @@ test('compare', exe) meson.add_dist_script('replacer.py', '"incorrect"', '"correct"') +meson.add_dist_script(find_program('replacer.py'), '"incorrect"', '"correct"') + +subproject('sub') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/subprojects/sub/dist-script.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/subprojects/sub/dist-script.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/subprojects/sub/dist-script.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/subprojects/sub/dist-script.py" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import os +import pathlib +import sys + +assert sys.argv[1] == 'success' + +source_root = pathlib.Path(os.environ['MESON_PROJECT_DIST_ROOT']) +modfile = source_root / 'prog.c' +with modfile.open('w') as f: + f.write('int main(){return 0;}') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/subprojects/sub/meson.build" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,11 @@ +project('sub') + +if get_option('broken_dist_script') + # Make sure we can add a dist script in a subproject, but it won't be run + # if not using --include-subprojects. + meson.add_dist_script('dist-script.py', 'broken') +else + # The dist script replace prog.c with something that actually build. + meson.add_dist_script('dist-script.py', 'success') + executable('prog', 'prog.c') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/subprojects/sub/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/subprojects/sub/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/subprojects/sub/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/subprojects/sub/meson_options.txt" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1 @@ +option('broken_dist_script', type: 'boolean', value: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/subprojects/sub/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/subprojects/sub/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/35 dist script/subprojects/sub/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/35 dist script/subprojects/sub/prog.c" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1 @@ +#error This should be replaced by a program during dist diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/36 exe_wrapper behaviour/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/36 exe_wrapper behaviour/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/36 exe_wrapper behaviour/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/36 exe_wrapper behaviour/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -1,7 +1,7 @@ project('exe wrapper behaviour', 'c') assert(meson.is_cross_build(), 'not setup as cross build') -assert(meson.has_exe_wrapper(), 'exe wrapper not defined?') +assert(meson.has_exe_wrapper(), 'exe wrapper not defined?') # intentionally not changed to can_run_host_binaries, exe = executable('prog', 'prog.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/39 python extmodule/blaster.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/39 python extmodule/blaster.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/39 python extmodule/blaster.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/39 python extmodule/blaster.py" 2021-04-27 06:49:45.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python import sys import tachyon diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/39 python extmodule/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/39 python extmodule/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/39 python extmodule/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/39 python extmodule/meson.build" 2021-04-01 21:12:21.000000000 +0000 @@ -6,7 +6,7 @@ py = py_mod.find_installation(get_option('python'), required : false) if py.found() - py_dep = py.dependency() + py_dep = py.dependency(required : false) if py_dep.found() subdir('ext') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/3 subproject defaults/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/3 subproject defaults/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/3 subproject defaults/meson.build" 2017-01-04 21:36:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/3 subproject defaults/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -8,4 +8,3 @@ assert(get_option('fromcmdline') == 'cmdline', 'Default option defined in cmd line is incorrect: ' + get_option('fromcmdline')) assert(get_option('defopoverride') == 'defopt', 'Default option without cmd line override is incorrect: ' + get_option('defopoverride')) assert(get_option('fromoptfile') == 'optfile', 'Default value from option file is incorrect: ' + get_option('fromoptfile')) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/3 subproject defaults/subprojects/foob/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/3 subproject defaults/subprojects/foob/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/3 subproject defaults/subprojects/foob/meson.build" 2017-01-04 21:36:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/3 subproject defaults/subprojects/foob/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -9,4 +9,3 @@ assert(get_option('fromspfunconly') == 'spfunc', 'Default option set with subproject() incorrect: ' + get_option('fromspfunc')) assert(get_option('defopoverride') == 's_defopt', 'Default option without cmd line override is incorrect: ' + get_option('defopoverride')) assert(get_option('fromoptfile') == 's_optfile', 'Default value from option file is incorrect: ' + get_option('fromoptfile')) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/40 external, internal library rpath/built library/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/40 external, internal library rpath/built library/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/40 external, internal library rpath/built library/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/40 external, internal library rpath/built library/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -18,4 +18,9 @@ if host_machine.system() == 'darwin' e = executable('prog', 'prog.c', link_with: l, install: true) test('testprog', e) +elif host_machine.system() == 'linux' + e = executable('prog', 'prog.c', link_with: l, install: true, + install_rpath: '$ORIGIN/..' / get_option('libdir'), + ) + test('testprog', e) endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/40 external, internal library rpath/external library/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/40 external, internal library rpath/external library/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/40 external, internal library rpath/external library/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/40 external, internal library rpath/external library/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -4,16 +4,16 @@ l = shared_library('faa_pkg', 'faa.c', install: true) if host_machine.system() == 'darwin' - frameworks = ['-framework', 'CoreFoundation', '-framework', 'CoreMedia'] + ldflags = ['-framework', 'CoreFoundation', '-framework', 'CoreMedia'] allow_undef_args = ['-Wl,-undefined,dynamic_lookup'] else - frameworks = [] + ldflags = ['-Wl,-rpath,${libdir}'] allow_undef_args = [] endif pkg = import('pkgconfig') pkg.generate(name: 'faa_pkg', - libraries: [l] + frameworks, + libraries: [l] + ldflags, description: 'FAA, a pkg-config test library') # cygwin DLLs can't have undefined symbols diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/44 promote wrap/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/44 promote wrap/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/44 promote wrap/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/44 promote wrap/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -2,4 +2,3 @@ subproject('s1') subproject('s2') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/44 promote wrap/subprojects/s1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/44 promote wrap/subprojects/s1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/44 promote wrap/subprojects/s1/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/44 promote wrap/subprojects/s1/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,2 +1 @@ project('s1', 'c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/44 promote wrap/subprojects/s1/subprojects/ambiguous/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/44 promote wrap/subprojects/s1/subprojects/ambiguous/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/44 promote wrap/subprojects/s1/subprojects/ambiguous/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/44 promote wrap/subprojects/s1/subprojects/ambiguous/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,2 +1 @@ project('ambiguous', 'c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/44 promote wrap/subprojects/s2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/44 promote wrap/subprojects/s2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/44 promote wrap/subprojects/s2/meson.build" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/44 promote wrap/subprojects/s2/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,2 +1 @@ project('s2', 'c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/45 vscpp17/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/45 vscpp17/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/45 vscpp17/main.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/45 vscpp17/main.cpp" 2021-04-01 21:13:00.000000000 +0000 @@ -1,7 +1,29 @@ -[[nodiscard]] int foo(void) { - return 0; -} +#include + +#if __cpp_lib_filesystem || (defined(__cplusplus) && __cplusplus >= 201703L) +#include +#endif + +int main(){ + +#if __cpp_lib_filesystem || (defined(__cplusplus) && __cplusplus >= 201703L) +char fs = std::filesystem::path::preferred_separator; +std::cout << "OK: C++17 filesystem enabled" << std::endl; +#endif -int main(void) { - return foo(); +#if defined(_MSC_VER) +#if _HAS_CXX17 +std::cout << "OK: MSVC has C++17 enabled" << std::endl; +return EXIT_SUCCESS; +#else +std::cerr << "ERROR: MSVC does not have C++17 enabled" << std::endl; +return EXIT_FAILURE; +#endif +#elif defined(__cplusplus) && __cplusplus >= 201703L +std::cout << "OK: C++17 enabled" << std::endl; +return EXIT_SUCCESS; +#else +std::cerr << "ERROR: C++17 not enabled" << std::endl; +return EXIT_FAILURE; +#endif } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/47 native file binary/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/47 native file binary/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/47 native file binary/meson.build" 2019-05-05 19:11:16.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/47 native file binary/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -4,7 +4,7 @@ if case == 'find_program' prog = find_program('bash') - result = run_command(prog, ['--version']) + result = run_command(prog, ['--version'], check: true) assert(result.stdout().strip().endswith('12345'), 'Didn\'t load bash from config file') elif case == 'config_dep' add_languages('cpp') @@ -12,10 +12,10 @@ assert(dep.get_configtool_variable('version').endswith('12345'), 'Didn\'t load llvm from config file') elif case == 'python3' prog = import('python3').find_python() - result = run_command(prog, ['--version']) + result = run_command(prog, ['--version'], check: true) assert(result.stdout().strip().endswith('12345'), 'Didn\'t load python3 from config file') elif case == 'python' prog = import('python').find_installation() - result = run_command(prog, ['--version']) + result = run_command(prog, ['--version'], check: true) assert(result.stdout().strip().endswith('12345'), 'Didn\'t load python from config file') endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/48 reconfigure/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/48 reconfigure/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/48 reconfigure/meson.build" 2019-03-10 17:10:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/48 reconfigure/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -7,3 +7,5 @@ exe = executable('test1', 'main.c') test('test1', exe) + +sub1 = subproject('sub1') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/48 reconfigure/subprojects/sub1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/48 reconfigure/subprojects/sub1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/48 reconfigure/subprojects/sub1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/48 reconfigure/subprojects/sub1/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,3 @@ +project('sub1') + +message('sub1:werror @0@'.format(get_option('werror'))) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/49 testsetup default/envcheck.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/49 testsetup default/envcheck.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/49 testsetup default/envcheck.py" 2019-03-10 17:10:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/49 testsetup default/envcheck.py" 2021-11-02 19:58:07.000000000 +0000 @@ -2,9 +2,9 @@ import os -assert('ENV_A' in os.environ) -assert('ENV_B' in os.environ) -assert('ENV_C' in os.environ) +assert 'ENV_A' in os.environ +assert 'ENV_B' in os.environ +assert 'ENV_C' in os.environ print('ENV_A is', os.environ['ENV_A']) print('ENV_B is', os.environ['ENV_B']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/51 noncross options/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/51 noncross options/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/51 noncross options/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/51 noncross options/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -7,7 +7,7 @@ if not meson.is_cross_build() executable('prog2', 'prog.c', native: true) - + # Check that even deps marked as native are found # by default when not cross compiling. dependency('ylib', method: 'pkg-config') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/54 clang-format/dummydir.h/dummy.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/54 clang-format/dummydir.h/dummy.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/54 clang-format/dummydir.h/dummy.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/54 clang-format/dummydir.h/dummy.dat" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1 @@ +Placeholder to track enclosing directory in git. Not to be analyzed. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/54 clang-format/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/54 clang-format/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/54 clang-format/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/54 clang-format/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,4 +1,3 @@ project('clangformat', 'c') executable('prog', 'prog.c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/54 clang-format/prog_orig_c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/54 clang-format/prog_orig_c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/54 clang-format/prog_orig_c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/54 clang-format/prog_orig_c" 2021-11-02 19:58:07.000000000 +0000 @@ -18,4 +18,3 @@ 0 ; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/cp.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/cp.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/cp.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/cp.py" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,5 @@ +#! /usr/bin/env python3 + +import sys +from shutil import copyfile +copyfile(*sys.argv[1:]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/meson.build" 2019-12-29 22:47:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/meson.build" 2021-08-18 11:22:25.000000000 +0000 @@ -8,11 +8,13 @@ b2 = get_option('test_opt2') test_bool = b1 or b2 test_bool = b1 and b2 +test_bool = not test_bool set_variable('list_test_plusassign', []) list_test_plusassign += ['bugs everywhere'] +dict_test = {list_test_plusassign[0]: 'even more bugs'} -if false +if not true vers_str = '<=99.9.9' dependency('somethingthatdoesnotexist', required: true, version: '>=1.2.3') dependency('look_i_have_a_fallback', version: ['>=1.0.0', vers_str], fallback: ['oh_no', 'the_subproject_does_not_exist']) @@ -25,10 +27,20 @@ var2 = 2.to_string() var3 = 'test3' -t1 = executable('test' + var1, ['t1.cpp'], link_with: [sharedlib], install: true, build_by_default: get_option('test_opt2')) +var4 = f'test @var1@ string' # TODO: Actually implement fstrings + +cus1 = custom_target('custom target test 1', output: 'file2', input: 'cp.py', + command: [find_program('cp.py'), '@INPUT@', '@OUTPUT@']) +cus2 = custom_target('custom target test 2', output: 'file3', input: cus1, + command: [find_program('cp.py'), '@INPUT@', '@OUTPUT@']) + +t1 = executable('test' + var1, ['t1.cpp'], link_with: [sharedlib], install: not false, build_by_default: get_option('test_opt2')) t2 = executable('test@0@'.format('@0@'.format(var2)), sources: ['t2.cpp'], link_with: [staticlib]) t3 = executable(var3, 't3.cpp', link_with: [sharedlib, staticlib], dependencies: [dep1]) +cus3 = custom_target('custom target test 3', output: 'file4', input: t3, + command: [find_program('cp.py'), '@INPUT@', '@OUTPUT@']) + ### BEGIN: Test inspired by taisei: https://github.com/taisei-project/taisei/blob/master/meson.build#L293 systype = '@0@'.format(host_machine.system()) systype = '@0@, @1@, @2@'.format(systype, host_machine.cpu_family(), host_machine.cpu()) @@ -43,5 +55,18 @@ message(osmesa_lib_name) # Infinite recursion gets triggered here when the parameter osmesa_lib_name is resolved test('test case 1', t1) -test('test case 2', t2) -benchmark('benchmark 1', t3) +test('test case 2', t2, depends: t3) +benchmark('benchmark 1', t3, args: [cus1, cus2, cus3]) + +### Stuff to test the AST JSON printer +foreach x : ['a', 'b', 'c'] + if x == 'a' + message('a') + elif x == 'b' + message('a') + else + continue + endif + break + continue +endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/sharedlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/sharedlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/sharedlib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/sharedlib/meson.build" 2021-04-01 21:12:21.000000000 +0000 @@ -1,2 +1,2 @@ SRC_shared = ['shared.cpp'] -sharedlib = shared_library('sharedTestLib', SRC_shared) +sharedlib = shared_library('sharedTestLib', SRC_shared, extra_files: ['shared.hpp']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/staticlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/staticlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/staticlib/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/staticlib/meson.build" 2021-04-01 21:12:21.000000000 +0000 @@ -1,2 +1,3 @@ SRC_static = ['static.c'] -staticlib = static_library('staticTestLib', SRC_static) +extra_static = files(['static.h']) +staticlib = static_library('staticTestLib', SRC_static, extra_files: extra_static) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/staticlib/static.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/staticlib/static.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/57 introspection/staticlib/static.h" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/57 introspection/staticlib/static.h" 2021-04-01 21:12:21.000000000 +0000 @@ -1,3 +1,11 @@ #pragma once -int add_numbers(int a, int b); \ No newline at end of file +#ifdef __cplusplus +extern "C" { +#endif + +int add_numbers(int a, int b); + +#ifdef __cplusplus +} +#endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/59 introspect buildoptions/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/59 introspect buildoptions/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/59 introspect buildoptions/meson.build" 2019-09-16 21:20:45.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/59 introspect buildoptions/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -1,4 +1,4 @@ -project('introspect buildargs', ['c'], default_options: ['c_std=c11', 'cpp_std=c++14', 'buildtype=release']) +project('introspect buildargs', ['c'], default_options: ['c_std=c99', 'cpp_std=c++14', 'buildtype=release']) subA = subproject('projectA') @@ -9,7 +9,7 @@ executable(target_name, target_src, build_by_default : foo) -r = run_command(find_program('c_compiler.py')) +r = run_command(find_program('c_compiler.py'), check: false) if r.returncode() != 0 error('FAILED') endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/5 compiler detection/trivial.mm" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/5 compiler detection/trivial.mm" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/5 compiler detection/trivial.mm" 2017-02-28 22:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/5 compiler detection/trivial.mm" 2021-11-02 19:58:07.000000000 +0000 @@ -6,4 +6,3 @@ int main(int argc, char **argv) { return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/60 native file override/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/60 native file override/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/60 native file override/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/60 native file override/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -4,7 +4,7 @@ 'libexecdir', 'localedir', 'localstatedir', 'mandir', 'prefix', 'sbindir', 'sharedstatedir', 'sysconfdir'] expected = get_option('def_' + o) - actual = get_option(o) + actual = get_option(o) assert(expected == actual, '@0@ should have been @1@, but was @2@!'.format(o, expected, actual)) endforeach diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/61 identity cross/build_wrapper.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/61 identity cross/build_wrapper.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/61 identity cross/build_wrapper.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/61 identity cross/build_wrapper.py" 2020-08-15 16:27:05.000000000 +0000 @@ -1,5 +1,11 @@ #!/usr/bin/env python3 -import subprocess, sys +import subprocess, sys, platform -subprocess.call(["cc", "-DEXTERNAL_BUILD"] + sys.argv[1:]) +# Meson does not yet support Studio cc on Solaris, only gcc or clang +if platform.system() == 'SunOS': + cc = 'gcc' +else: + cc = 'cc' + +subprocess.call([cc, "-DEXTERNAL_BUILD"] + sys.argv[1:]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/61 identity cross/host_wrapper.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/61 identity cross/host_wrapper.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/61 identity cross/host_wrapper.py" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/61 identity cross/host_wrapper.py" 2020-08-15 16:27:05.000000000 +0000 @@ -1,5 +1,11 @@ #!/usr/bin/env python3 -import subprocess, sys +import subprocess, sys, platform -subprocess.call(["cc", "-DEXTERNAL_HOST"] + sys.argv[1:]) +# Meson does not yet support Studio cc on Solaris, only gcc or clang +if platform.system() == 'SunOS': + cc = 'gcc' +else: + cc = 'cc' + +subprocess.call([cc, "-DEXTERNAL_HOST"] + sys.argv[1:]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/63 cmake_prefix_path/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/63 cmake_prefix_path/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/63 cmake_prefix_path/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/63 cmake_prefix_path/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('cmake prefix path test') + +d = dependency('mesontest', method : 'cmake') +assert(d.version() == '1.2.3', 'Got the wrong version!') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/63 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/63 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/63 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/63 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +set(MESONTEST_VERSION "1.2.3") +set(MESONTEST_LIBRARIES "foo.so") +set(MESONTEST_INCLUDE_DIR "") +set(MESONTEST_FOUND "TRUE") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/63 test env does not stack/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/63 test env does not stack/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/63 test env does not stack/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/63 test env does not stack/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -project('test env var stacking') - -testenv = environment() -testenv.set('TEST_VAR_SET', 'some-value') -testenv.set('TEST_VAR_APPEND', 'some-value') -testenv.set('TEST_VAR_PREPEND', 'some-value') - -testenv.append('TEST_VAR_APPEND', 'another-value-append', separator: ':') -testenv.prepend('TEST_VAR_PREPEND', 'another-value-prepend', separator: ':') -testenv.set('TEST_VAR_SET', 'another-value-set') - -test('check env', find_program('script.py'), env: testenv) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/63 test env does not stack/script.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/63 test env does not stack/script.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/63 test env does not stack/script.py" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/63 test env does not stack/script.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#!/usr/bin/env python3 - -import os - -for name in ('append', 'prepend', 'set'): - envname = 'TEST_VAR_' + name.upper() - value = 'another-value-' + name - envvalue = os.environ[envname] - assert (envvalue == value), (name, envvalue) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/64 cmake parser/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/64 cmake parser/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/64 cmake parser/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/64 cmake parser/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +project('61 cmake parser') + +dep = dependency('mesontest') + +# Test a bunch of variations of the set() command +assert(dep.get_variable(cmake : 'VAR_WITHOUT_SPACES') == 'NoSpaces', 'set() without spaces incorrect') +assert(dep.get_variable(cmake : 'VAR_WITH_SPACES') == 'With Spaces', 'set() with spaces incorrect') + +assert(dep.get_variable(cmake : 'VAR_WITHOUT_SPACES_PS') == 'NoSpaces', 'set(PARENT_SCOPE) without spaces incorrect') +assert(dep.get_variable(cmake : 'VAR_WITH_SPACES_PS') == 'With Spaces', 'set(PARENT_SCOPE) with spaces incorrect') + +assert(dep.get_variable(cmake : 'VAR_THAT_IS_UNSET', default_value : 'sentinal') == 'sentinal', 'set() to unset is incorrect') +assert(dep.get_variable(cmake : 'CACHED_STRING_NS') == 'foo', 'set(CACHED) without spaces is incorrect') +assert(dep.get_variable(cmake : 'CACHED_STRING_WS') == 'foo bar', 'set(CACHED STRING) with spaces is incorrect') +assert(dep.get_variable(cmake : 'CACHED_STRING_ARRAY_NS') == ['foo', 'bar'], 'set(CACHED STRING) without spaces is incorrect') +assert(dep.get_variable(cmake : 'CACHED_STRING_ARRAY_WS') == ['foo', 'foo bar', 'bar'], 'set(CACHED STRING[]) with spaces is incorrect') + +# We don't support this, so it should be unset. +assert(dep.get_variable(cmake : 'ENV{var}', default_value : 'sentinal') == 'sentinal', 'set(ENV) should be ignored') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/64 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/64 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/64 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/64 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,63 @@ +# This should be enough to satisfy the basic parser +set(MESONTEST_VERSION "1.2.3") +set(MESONTEST_LIBRARIES "foo.so") +set(MESONTEST_INCLUDE_DIR "") +set(MESONTEST_FOUND "TRUE") + +## Tests for set() in its various forms + +# Basic usage +set(VAR_WITHOUT_SPACES "NoSpaces") +set(VAR_WITH_SPACES "With Spaces") + +# test of PARENT_SCOPE, requires a function to have a parent scope obviously... +function(foo) + set(VAR_WITHOUT_SPACES_PS "NoSpaces" PARENT_SCOPE) + set(VAR_WITH_SPACES_PS "With Spaces" PARENT_SCOPE) +endfunction(foo) +foo() + +# Using set() to unset values +set(VAR_THAT_IS_UNSET "foo") +set(VAR_THAT_IS_UNSET) + +# The more advanced form that uses CACHE +# XXX: Why don't we read the type and use that instead of always treat things as strings? +set(CACHED_STRING_NS "foo" CACHE STRING "docstring") +set(CACHED_STRING_WS "foo bar" CACHE STRING "docstring") +set(CACHED_STRING_ARRAY_NS "foo;bar" CACHE STRING "doc string") +set(CACHED_STRING_ARRAY_WS "foo;foo bar;bar" CACHE STRING "stuff" FORCE) + +set(CACHED_BOOL ON CACHE BOOL "docstring") + +set(CACHED_PATH_NS "foo/bar" CACHE PATH "docstring") +set(CACHED_PATH_WS "foo bar/fin" CACHE PATH "docstring") + +set(CACHED_FILEPATH_NS "foo/bar.txt" CACHE FILEPATH "docstring") +set(CACHED_FILEPATH_WS "foo bar/fin.txt" CACHE FILEPATH "docstring") + +# Set ENV, we don't support this so it shouldn't be showing up +set(ENV{var}, "foo") + + +## Tests for set_properties() +# We need something to attach properties too +add_custom_target(MESONTEST_FOO ALL) + +set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value") +set_property(TARGET MESONTEST_FOO APPEND PROPERTY FOLDER "name") +set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value") +set_property(TARGET MESONTEST_FOO APPEND_STRING PROPERTY FOLDER "name") + +set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value space") +set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value space") +set_property(TARGET MESONTEST_FOO APPEND PROPERTY FOLDER "name space") +set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value space") +set_property(TARGET MESONTEST_FOO APPEND_STRING PROPERTY FOLDER "name space") + +## Tests for set_target_properties() +set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value") +set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value space") +set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value" OUTPUT_NAME "another value") +set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value space" OUTPUT_NAME "another value") +set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value space" OUTPUT_NAME "value") \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/64 cmake_prefix_path/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/64 cmake_prefix_path/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/64 cmake_prefix_path/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/64 cmake_prefix_path/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('cmake prefix path test') - -d = dependency('mesontest', method : 'cmake') -assert(d.version() == '1.2.3', 'Got the wrong version!') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/64 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/64 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/64 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/64 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -set(MESONTEST_VERSION "1.2.3") -set(MESONTEST_LIBRARIES "foo.so") -set(MESONTEST_INCLUDE_DIR "") -set(MESONTEST_FOUND "TRUE") diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 alias target/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 alias target/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 alias target/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 alias target/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(int argc, char *argv[]) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 alias target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 alias target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 alias target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 alias target/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,17 @@ +project('alias target', 'c') + +python3 = import('python').find_installation() + +exe_target = executable('prog', 'main.c', + build_by_default : false) + +custom_target = custom_target('custom-target', + output : 'hello.txt', + command : [python3, '-c', 'print("hello")'], + capture : true, + build_by_default : false +) + +alias_target('build-all', [exe_target, custom_target]) + +subdir('subdir') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 alias target/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 alias target/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 alias target/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 alias target/subdir/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +r = run_target('run-target', + command: [python3, '-c', 'print("a run target was here")'] +) + +alias_target('aliased-run', r) + diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 cmake parser/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 cmake parser/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 cmake parser/meson.build" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 cmake parser/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -project('61 cmake parser') - -dep = dependency('mesontest') - -# Test a bunch of variations of the set() command -assert(dep.get_variable(cmake : 'VAR_WITHOUT_SPACES') == 'NoSpaces', 'set() without spaces incorrect') -assert(dep.get_variable(cmake : 'VAR_WITH_SPACES') == 'With Spaces', 'set() with spaces incorrect') - -assert(dep.get_variable(cmake : 'VAR_WITHOUT_SPACES_PS') == 'NoSpaces', 'set(PARENT_SCOPE) without spaces incorrect') -assert(dep.get_variable(cmake : 'VAR_WITH_SPACES_PS') == 'With Spaces', 'set(PARENT_SCOPE) with spaces incorrect') - -assert(dep.get_variable(cmake : 'VAR_THAT_IS_UNSET', default_value : 'sentinal') == 'sentinal', 'set() to unset is incorrect') -assert(dep.get_variable(cmake : 'CACHED_STRING_NS') == 'foo', 'set(CACHED) without spaces is incorrect') -assert(dep.get_variable(cmake : 'CACHED_STRING_WS') == 'foo bar', 'set(CACHED STRING) with spaces is incorrect') -assert(dep.get_variable(cmake : 'CACHED_STRING_ARRAY_NS') == ['foo', 'bar'], 'set(CACHED STRING) without spaces is incorrect') -assert(dep.get_variable(cmake : 'CACHED_STRING_ARRAY_WS') == ['foo', 'foo bar', 'bar'], 'set(CACHED STRING[]) with spaces is incorrect') - -# We don't support this, so it should be unset. -assert(dep.get_variable(cmake : 'ENV{var}', default_value : 'sentinal') == 'sentinal', 'set(ENV) should be ignored') \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/65 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/65 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake" 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -# This should be enough to satisfy the basic parser -set(MESONTEST_VERSION "1.2.3") -set(MESONTEST_LIBRARIES "foo.so") -set(MESONTEST_INCLUDE_DIR "") -set(MESONTEST_FOUND "TRUE") - -## Tests for set() in its various forms - -# Basic usage -set(VAR_WITHOUT_SPACES "NoSpaces") -set(VAR_WITH_SPACES "With Spaces") - -# test of PARENT_SCOPE, requires a function to have a parent scope obviously... -function(foo) - set(VAR_WITHOUT_SPACES_PS "NoSpaces" PARENT_SCOPE) - set(VAR_WITH_SPACES_PS "With Spaces" PARENT_SCOPE) -endfunction(foo) -foo() - -# Using set() to unset values -set(VAR_THAT_IS_UNSET "foo") -set(VAR_THAT_IS_UNSET) - -# The more advanced form that uses CACHE -# XXX: Why don't we read the type and use that instead of always treat things as strings? -set(CACHED_STRING_NS "foo" CACHE STRING "docstring") -set(CACHED_STRING_WS "foo bar" CACHE STRING "docstring") -set(CACHED_STRING_ARRAY_NS "foo;bar" CACHE STRING "doc string") -set(CACHED_STRING_ARRAY_WS "foo;foo bar;bar" CACHE STRING "stuff" FORCE) - -set(CACHED_BOOL ON CACHE BOOL "docstring") - -set(CACHED_PATH_NS "foo/bar" CACHE PATH "docstring") -set(CACHED_PATH_WS "foo bar/fin" CACHE PATH "docstring") - -set(CACHED_FILEPATH_NS "foo/bar.txt" CACHE FILEPATH "docstring") -set(CACHED_FILEPATH_WS "foo bar/fin.txt" CACHE FILEPATH "docstring") - -# Set ENV, we don't support this so it shouldn't be showing up -set(ENV{var}, "foo") - - -## Tests for set_properties() -# We need something to attach properties too -add_custom_target(MESONTEST_FOO ALL) - -set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value") -set_property(TARGET MESONTEST_FOO APPEND PROPERTY FOLDER "name") -set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value") -set_property(TARGET MESONTEST_FOO APPEND_STRING PROPERTY FOLDER "name") - -set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value space") -set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value space") -set_property(TARGET MESONTEST_FOO APPEND PROPERTY FOLDER "name space") -set_property(TARGET MESONTEST_FOO PROPERTY FOLDER "value space") -set_property(TARGET MESONTEST_FOO APPEND_STRING PROPERTY FOLDER "name space") - -## Tests for set_target_properties() -set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value") -set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value space") -set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value" OUTPUT_NAME "another value") -set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value space" OUTPUT_NAME "another value") -set_target_properties(MESONTEST_FOO PROPERTIES FOLDER "value space" OUTPUT_NAME "value") \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 alias target/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 alias target/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 alias target/main.c" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 alias target/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(int argc, char *argv[]) { - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 alias target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 alias target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 alias target/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 alias target/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -project('alias target', 'c') - -python3 = import('python').find_installation() - -exe_target = executable('prog', 'main.c', - build_by_default : false) - -custom_target = custom_target('custom-target', - output : 'hello.txt', - command : [python3, '-c', 'print("hello")'], - capture : true, - build_by_default : false -) - -alias_target('build-all', [exe_target, custom_target]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/app/appA.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/app/appA.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/app/appA.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/app/appA.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +#include +#include + +int main(void) { printf("The answer is: %d\n", libA_func()); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/app/appB.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/app/appB.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/app/appB.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/app/appB.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +#include +#include + +int main(void) { printf("The answer is: %d\n", libB_func()); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/app/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/app/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/app/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/app/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +project('app', ['c']) + +a = dependency('test-a') +b = dependency('test-b') + +executable('appA', files('appA.c'), dependencies : a) +executable('appB', files('appB.c'), dependencies : b) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/libA.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/libA.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/libA.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/libA.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +static int libA_func_impl(void) { return 0; } + +int libA_func(void) { return libA_func_impl(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/libA.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/libA.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/libA.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/libA.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int libA_func(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/libB.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/libB.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/libB.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/libB.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +static int libB_func_impl(void) { return 0; } + +int libB_func(void) { return libB_func_impl(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/libB.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/libB.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/libB.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/libB.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int libB_func(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/66 static archive stripping/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/66 static archive stripping/lib/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,23 @@ +project('lib', ['c']) + +pkg = import('pkgconfig') + +a = library('test-a', files('libA.c'), install: true) +install_headers(files('libA.h'), subdir: 'libA') +pkg.generate( + a, + version: '0.0', + description: 'test library libA', + filebase: 'test-a', + name: 'test library libA', + subdirs: 'libA') + +b = static_library('test-b', files('libB.c'), install: true) +install_headers(files('libB.h'), subdir: 'libB') +pkg.generate( + b, + version: '0.0', + description: 'test library libB', + filebase: 'test-b', + name: 'test library libB', + subdirs: 'libB') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func10.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func10.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func10.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func10.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int func10() +{ + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func11.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func11.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func11.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func11.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func10(); + +int func11() +{ + return func10() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func12.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func12.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func12.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func12.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +int func10(); +int func11(); + +int func12() +{ + return func10() + func11(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func14.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func14.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func14.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func14.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int func14() +{ + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func15.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func15.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func15.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func15.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func14(); + +int func15() +{ + return func14() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func16.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func16.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func16.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func16.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func15(); + +int func16() +{ + return func15() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func17.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func17.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func17.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func17.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int func17() +{ + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func18.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func18.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func18.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func18.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func17(); + +int func18() +{ + return func17() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func19.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func19.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func19.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func19.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +int func17(); +int func18(); + +int func19() +{ + return func17() + func18(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +int func1() +{ + return 1; +} + +int func1b() +{ + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func1(); + +int func2() +{ + return func1() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int func3() +{ + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func4.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func4.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func4.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func4.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func3(); + +int func4() +{ + return func3() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func5.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func5.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func5.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func5.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int func5() +{ + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func6.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func6.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func6.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func6.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func5(); + +int func6() +{ + return func5() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func7.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func7.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func7.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func7.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int func7() +{ + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func8.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func8.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func8.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func8.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func7(); + +int func8() +{ + return func7() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func9.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func9.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/func9.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/func9.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func8(); + +int func9() +{ + return func8() + 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/lib/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,80 @@ +project('test static link libs', 'c') + +pkg = import('pkgconfig') + +# libfunc2 should contain both func1() and func2() symbols +libfunc1 = static_library('func1', 'func1.c', + install : false) +libfunc2 = static_library('func2', 'func2.c', + link_whole : libfunc1, + install : true) + +# Same as above, but with link_with instead of link_whole, +# libfunc4 should contain both func3() and func4() symbols +libfunc3 = static_library('func3', 'func3.c', + install : false) +libfunc4 = static_library('func4', 'func4.c', + link_with : libfunc3, + install : true) + +# Same as above, but also generate an pkg-config file. Use both_libraries() to +# make sure a complete .pc file gets generated. libfunc5 should not be mentioned +# into the .pc file because it's not installed. +libfunc5 = static_library('func5', 'func5.c', + install : false) +libfunc6 = both_libraries('func6', 'func6.c', + link_with : libfunc5, + install : true) +pkg.generate(libfunc6) + +# libfunc9 should contain both func8() and func9() but not func7() because that +# one gets installed. Also test that link_with and link_whole works the same way +# because libfunc8 is uninstalled. +libfunc7 = static_library('func7', 'func7.c', + install : true) +libfunc8 = static_library('func8', 'func8.c', + link_with : libfunc7, + install : false) +libfunc9_linkwith = static_library('func9_linkwith', 'func9.c', + link_with : libfunc8, + install : true) +libfunc9_linkwhole = static_library('func9_linkwhole', 'func9.c', + link_whole : libfunc8, + install : true) + +# Pattern found in mesa: +# - libfunc11 uses func10() +# - libfunc12 uses both func10() and func11() +# When a shared library link_whole on libfunc12, we ensure we don't include +# func10.c.o twice which would fail to link. +libfunc10 = static_library('func10', 'func10.c', + install : false) +libfunc11 = static_library('func11', 'func11.c', + link_with : libfunc10, + install : false) +libfunc12 = static_library('func12', 'func12.c', + link_with : [libfunc10, libfunc11], + install : false) +libfunc13 = shared_library('func13', link_whole : libfunc12) + +# libfunc16 should contain func14(), func15() and func16() +libfunc14 = static_library('func14', 'func14.c', + install : false) +libfunc15 = static_library('func15', 'func15.c', + link_with : libfunc14, + install : false) +libfunc16 = static_library('func16', 'func16.c', + link_with : libfunc15, + install : true) + +# Verify func17.c.o gets included only once into libfunc19, otherwise +# func19-shared would failed with duplicated symbol. +libfunc17 = static_library('func17', 'func17.c', + install : false) +libfunc18 = static_library('func18', 'func18.c', + link_with : libfunc17, + install : false) +libfunc19 = static_library('func19', 'func19.c', + link_whole : [libfunc17, libfunc18], + install : false) +shared_library('func19-shared', link_whole : [libfunc19]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,32 @@ +project('test static link', 'c') + +cc = meson.get_compiler('c') + +# Verify that installed libfunc2.a is usable +func2_dep = cc.find_library('func2') +test('test1', executable('test1', 'test1.c', dependencies : func2_dep)) + +# Verify that installed libfunc4.a is usable +func4_dep = cc.find_library('func4') +test('test2', executable('test2', 'test2.c', dependencies : func4_dep)) + +# Verify that installed pkg-config file is usable for both shared and static link +func6_static_dep = dependency('func6', static : true) +test('test3-static', executable('test3-static', 'test3.c', + dependencies : func6_static_dep)) +func6_shared_dep = dependency('func6', static : false) +test('test3-shared', executable('test3-shared', 'test3.c', + dependencies : func6_shared_dep)) + +# Verify that installed libfunc9.a contains func8() and func8() but not func7() +func7_dep = cc.find_library('func7') +func9_linkwhole_dep = cc.find_library('func9_linkwhole') +test('test4-linkwhole', executable('test4-linkwhole', 'test4.c', + dependencies : [func7_dep, func9_linkwhole_dep])) +func9_linkwith_dep = cc.find_library('func9_linkwith') +test('test4-linkwith', executable('test4-linkwith', 'test4.c', + dependencies : [func7_dep, func9_linkwith_dep])) + +# Verify that installed libfunc16.a is usable +libfunc16_dep = cc.find_library('func16') +test('test5', executable('test5', 'test5.c', dependencies: libfunc16_dep)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +int func1b(); +int func2(); + +int main(int argc, char *argv[]) +{ + return func2() + func1b() == 3 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func4(); + +int main(int argc, char *argv[]) +{ + return func4() == 2 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func6(); + +int main(int argc, char *argv[]) +{ + return func6() == 2 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test4.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test4.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test4.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test4.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func9(); + +int main(int argc, char *argv[]) +{ + return func9() == 3 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test5.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test5.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/67 static link/test5.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/67 static link/test5.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int func16(); + +int main(int argc, char *argv[]) +{ + return func16() == 3 ? 0 : 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/app/appA.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/app/appA.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/app/appA.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/app/appA.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -#include -#include - -int main(void) { printf("The answer is: %d\n", libA_func()); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/app/appB.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/app/appB.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/app/appB.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/app/appB.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -#include -#include - -int main(void) { printf("The answer is: %d\n", libB_func()); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/app/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/app/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/app/meson.build" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/app/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -project('app', ['c']) - -a = dependency('test-a') -b = dependency('test-b') - -executable('appA', files('appA.c'), dependencies : a) -executable('appB', files('appB.c'), dependencies : b) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/libA.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/libA.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/libA.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/libA.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -static int libA_func_impl(void) { return 0; } - -int libA_func(void) { return libA_func_impl(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/libA.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/libA.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/libA.h" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/libA.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int libA_func(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/libB.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/libB.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/libB.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/libB.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -static int libB_func_impl(void) { return 0; } - -int libB_func(void) { return libB_func_impl(); } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/libB.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/libB.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/libB.h" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/libB.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int libB_func(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 static archive stripping/lib/meson.build" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 static archive stripping/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -project('lib', ['c']) - -pkg = import('pkgconfig') - -a = library('test-a', files('libA.c'), install: true) -install_headers(files('libA.h'), subdir: 'libA') -pkg.generate( - a, - version: '0.0', - description: 'test library libA', - filebase: 'test-a', - name: 'test library libA', - subdirs: 'libA') - -b = static_library('test-b', files('libB.c'), install: true) -install_headers(files('libB.h'), subdir: 'libB') -pkg.generate( - b, - version: '0.0', - description: 'test library libB', - filebase: 'test-b', - name: 'test library libB', - subdirs: 'libB') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 test env value/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 test env value/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 test env value/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 test env value/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +project('test env value') + +testpy = find_program('test.py') + +val = ['1', '2', '3'] +foreach v: val + test('check env', testpy, args: [v], env: {'TEST_VAR': v}) +endforeach +test('check env', testpy, args: ['4'], env: environment({'TEST_VAR': '4'})) +test('check env', testpy, args: ['5'], env: environment(['TEST_VAR=5'])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 test env value/test.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 test env value/test.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/68 test env value/test.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/68 test env value/test.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import os +import sys + +assert os.environ['TEST_VAR'] == sys.argv[1] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 clang-tidy/.clang-tidy" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 clang-tidy/.clang-tidy" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 clang-tidy/.clang-tidy" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 clang-tidy/.clang-tidy" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Checks: '-*,modernize-use-bool-literals' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 clang-tidy/cttest.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 clang-tidy/cttest.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 clang-tidy/cttest.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 clang-tidy/cttest.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +int main(int, char**) { + bool intbool = 1; + printf("Intbool is %d\n", (int)intbool); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 clang-tidy/dummydir.h/dummy.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 clang-tidy/dummydir.h/dummy.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 clang-tidy/dummydir.h/dummy.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 clang-tidy/dummydir.h/dummy.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +Placeholder to track enclosing directory in git. Not to be analyzed. diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 clang-tidy/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 clang-tidy/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 clang-tidy/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 clang-tidy/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('clangtidytest', 'cpp', default_options: 'cpp_std=c++14') + +executable('cttest', 'cttest.cpp') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func10.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func10.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func10.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func10.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int func10() -{ - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func11.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func11.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func11.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func11.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func10(); - -int func11() -{ - return func10() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func12.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func12.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func12.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func12.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -int func10(); -int func11(); - -int func12() -{ - return func10() + func11(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func14.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func14.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func14.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func14.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int func14() -{ - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func15.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func15.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func15.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func15.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func14(); - -int func15() -{ - return func14() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func16.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func16.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func16.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func16.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func15(); - -int func16() -{ - return func15() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func17.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func17.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func17.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func17.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int func17() -{ - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func18.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func18.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func18.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func18.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func17(); - -int func18() -{ - return func17() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func19.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func19.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func19.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func19.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -int func17(); -int func18(); - -int func19() -{ - return func17() + func18(); -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func1.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -int func1() -{ - return 1; -} - -int func1b() -{ - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func2.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func1(); - -int func2() -{ - return func1() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func3.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int func3() -{ - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func4.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func4.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func4.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func4.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func3(); - -int func4() -{ - return func3() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func5.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func5.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func5.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func5.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int func5() -{ - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func6.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func6.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func6.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func6.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func5(); - -int func6() -{ - return func5() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func7.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func7.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func7.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func7.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int func7() -{ - return 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func8.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func8.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func8.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func8.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func7(); - -int func8() -{ - return func7() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func9.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func9.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/func9.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/func9.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func8(); - -int func9() -{ - return func8() + 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/lib/meson.build" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/lib/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -project('test static link libs', 'c') - -pkg = import('pkgconfig') - -# libfunc2 should contain both func1() and func2() symbols -libfunc1 = static_library('func1', 'func1.c', - install : false) -libfunc2 = static_library('func2', 'func2.c', - link_whole : libfunc1, - install : true) - -# Same as above, but with link_with instead of link_whole, -# libfunc4 should contain both func3() and func4() symbols -libfunc3 = static_library('func3', 'func3.c', - install : false) -libfunc4 = static_library('func4', 'func4.c', - link_with : libfunc3, - install : true) - -# Same as above, but also generate an pkg-config file. Use both_libraries() to -# make sure a complete .pc file gets generated. libfunc5 should not be mentioned -# into the .pc file because it's not installed. -libfunc5 = static_library('func5', 'func5.c', - install : false) -libfunc6 = both_libraries('func6', 'func6.c', - link_with : libfunc5, - install : true) -pkg.generate(libfunc6) - -# libfunc9 should contain both func8() and func9() but not func7() because that -# one gets installed. Also test that link_with and link_whole works the same way -# because libfunc8 is uninstalled. -libfunc7 = static_library('func7', 'func7.c', - install : true) -libfunc8 = static_library('func8', 'func8.c', - link_with : libfunc7, - install : false) -libfunc9_linkwith = static_library('func9_linkwith', 'func9.c', - link_with : libfunc8, - install : true) -libfunc9_linkwhole = static_library('func9_linkwhole', 'func9.c', - link_whole : libfunc8, - install : true) - -# Pattern found in mesa: -# - libfunc11 uses func10() -# - libfunc12 uses both func10() and func11() -# When a shared library link_whole on libfunc12, we ensure we don't include -# func10.c.o twice which would fail to link. -libfunc10 = static_library('func10', 'func10.c', - install : false) -libfunc11 = static_library('func11', 'func11.c', - link_with : libfunc10, - install : false) -libfunc12 = static_library('func12', 'func12.c', - link_with : [libfunc10, libfunc11], - install : false) -libfunc13 = shared_library('func13', link_whole : libfunc12) - -# libfunc16 should contain func14(), func15() and func16() -libfunc14 = static_library('func14', 'func14.c', - install : false) -libfunc15 = static_library('func15', 'func15.c', - link_with : libfunc14, - install : false) -libfunc16 = static_library('func16', 'func16.c', - link_with : libfunc15, - install : true) - -# Verify func17.c.o gets included only once into libfunc19, otherwise -# func19-shared would failed with duplicated symbol. -libfunc17 = static_library('func17', 'func17.c', - install : false) -libfunc18 = static_library('func18', 'func18.c', - link_with : libfunc17, - install : false) -libfunc19 = static_library('func19', 'func19.c', - link_whole : [libfunc17, libfunc18], - install : false) -shared_library('func19-shared', link_whole : [libfunc19]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/meson.build" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -project('test static link', 'c') - -cc = meson.get_compiler('c') - -# Verify that installed libfunc2.a is usable -func2_dep = cc.find_library('func2') -test('test1', executable('test1', 'test1.c', dependencies : func2_dep)) - -# Verify that installed libfunc4.a is usable -func4_dep = cc.find_library('func4') -test('test2', executable('test2', 'test2.c', dependencies : func4_dep)) - -# Verify that installed pkg-config file is usable for both shared and static link -func6_static_dep = dependency('func6', static : true) -test('test3-static', executable('test3-static', 'test3.c', - dependencies : func6_static_dep)) -func6_shared_dep = dependency('func6', static : false) -test('test3-shared', executable('test3-shared', 'test3.c', - dependencies : func6_shared_dep)) - -# Verify that installed libfunc9.a contains func8() and func8() but not func7() -func7_dep = cc.find_library('func7') -func9_linkwhole_dep = cc.find_library('func9_linkwhole') -test('test4-linkwhole', executable('test4-linkwhole', 'test4.c', - dependencies : [func7_dep, func9_linkwhole_dep])) -func9_linkwith_dep = cc.find_library('func9_linkwith') -test('test4-linkwith', executable('test4-linkwith', 'test4.c', - dependencies : [func7_dep, func9_linkwith_dep])) - -# Verify that installed libfunc16.a is usable -libfunc16_dep = cc.find_library('func16') -test('test5', executable('test5', 'test5.c', dependencies: libfunc16_dep)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test1.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test1.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -int func1b(); -int func2(); - -int main(int argc, char *argv[]) -{ - return func2() + func1b() == 3 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test2.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func4(); - -int main(int argc, char *argv[]) -{ - return func4() == 2 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test3.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test3.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func6(); - -int main(int argc, char *argv[]) -{ - return func6() == 2 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test4.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test4.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test4.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test4.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func9(); - -int main(int argc, char *argv[]) -{ - return func9() == 3 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test5.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test5.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 static link/test5.c" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 static link/test5.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int func16(); - -int main(int argc, char *argv[]) -{ - return func16() == 3 ? 0 : 1; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 test env value/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 test env value/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 test env value/meson.build" 2019-10-06 17:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 test env value/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('test env value') - -testpy = find_program('test.py') - -val = ['1', '2', '3'] -foreach v: val - test('check env', testpy, args: [v], env: {'TEST_VAR': v}) -endforeach -test('check env', testpy, args: ['4'], env: environment({'TEST_VAR': '4'})) -test('check env', testpy, args: ['5'], env: environment(['TEST_VAR=5'])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 test env value/test.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 test env value/test.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/69 test env value/test.py" 2019-10-06 17:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/69 test env value/test.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -assert(os.environ['TEST_VAR'] == sys.argv[1]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 clang-tidy/.clang-tidy" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 clang-tidy/.clang-tidy" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 clang-tidy/.clang-tidy" 2019-10-06 17:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 clang-tidy/.clang-tidy" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Checks: '-*,modernize-use-bool-literals' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 clang-tidy/cttest.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 clang-tidy/cttest.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 clang-tidy/cttest.cpp" 2019-10-06 17:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 clang-tidy/cttest.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include - -int main(int, char**) { - bool intbool = 1; - printf("Intbool is %d\n", (int)intbool); - return 0; -} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 clang-tidy/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 clang-tidy/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 clang-tidy/meson.build" 2019-10-06 17:01:35.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 clang-tidy/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('clangtidytest', 'cpp', default_options: 'cpp_std=c++14') - -executable('cttest', 'cttest.cpp') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 cross/crossfile.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 cross/crossfile.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 cross/crossfile.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 cross/crossfile.in" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +[host_machine] +system = '@system@' +cpu_family = '@cpu_family@' +cpu = '@cpu@' +endian = '@endian@' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 cross/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 cross/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 cross/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 cross/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,16 @@ +project('crosstest') + +if get_option('generate') + conf_data = configuration_data() + conf_data.set('system', build_machine.system()) + conf_data.set('cpu', build_machine.cpu()) + conf_data.set('cpu_family', build_machine.cpu_family()) + conf_data.set('endian', build_machine.endian()) + + configure_file(input: 'crossfile.in', + output: 'crossfile', + configuration: conf_data) + message('Written cross file') +else + assert(meson.is_cross_build(), 'not setup as cross build') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 cross/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 cross/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/70 cross/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/70 cross/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +option('generate', type : 'boolean', value : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross/crossfile.in" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross/crossfile.in" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross/crossfile.in" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross/crossfile.in" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -[host_machine] -system = '@system@' -cpu_family = '@cpu_family@' -cpu = '@cpu@' -endian = '@endian@' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross/meson.build" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -project('crosstest') - -if get_option('generate') - conf_data = configuration_data() - conf_data.set('system', build_machine.system()) - conf_data.set('cpu', build_machine.cpu()) - conf_data.set('cpu_family', build_machine.cpu_family()) - conf_data.set('endian', build_machine.endian()) - - configure_file(input: 'crossfile.in', - output: 'crossfile', - configuration: conf_data) - message('Written cross file') -else - assert(meson.is_cross_build(), 'not setup as cross build') -endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross/meson_options.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -option('generate', type : 'boolean', value : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/exewrapper.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/exewrapper.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/exewrapper.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/exewrapper.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# Test that the MESON_EXE_WRAPPER environment variable is set + +import argparse +import os +import sys + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('binary') # unused, but needed for test behavior + parser.add_argument('--expected', action='store_true') + args = parser.parse_args() + + defined = 'MESON_EXE_WRAPPER' in os.environ + + if args.expected != defined: + print(os.environ, file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,19 @@ +project( + 'cross test passed', + 'c', + version : '>= 0.51' +) + +e = executable('exec', 'src/main.c') + +py = import('python').find_installation() + +test('root', e) +test('main', py, args : [meson.current_source_dir() / 'script.py', e]) + +wrapper_args = [] +if get_option('expect') + wrapper_args += '--expected' +endif + +test('exe_wrapper in env', py, args : [meson.current_source_dir() / 'exewrapper.py', e, wrapper_args]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +option( + 'expect', + type : 'boolean', + value : false, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/script.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/script.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/script.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/script.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import subprocess +import sys + +if __name__ == "__main__": + sys.exit(subprocess.run(sys.argv[1:]).returncode) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/src/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/src/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/71 cross test passed/src/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/71 cross test passed/src/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main(int argc, char const *argv[]) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/meson.build" 2021-10-11 16:26:46.000000000 +0000 @@ -0,0 +1,23 @@ +project('My Project', version : '1.0') + +subproject('sub') +subproject('sub2', required : false) + +summary({'Some boolean': false, + 'Another boolean': true, + 'Some string': 'Hello World', + 'A list': ['string', 1, true], + 'empty list': [], + 'enabled_opt': get_option('enabled_opt'), + }, section: 'Configuration') +summary({'missing prog': find_program('xyzzy', required: false), + 'existing prog': import('python').find_installation(), + 'missing dep': dependency('', required: false), + 'external dep': dependency('zlib', required: false), + 'internal dep': declare_dependency(), + }, section: 'Stuff') +summary('A number', 1, section: 'Configuration') +summary('yes', true, bool_yn : true, section: 'Configuration') +summary('no', false, bool_yn : true, section: 'Configuration') +summary('coma list', ['a', 'b', 'c'], list_sep: ', ', section: 'Configuration') +summary('long coma list', ['alpha', 'alphacolor', 'apetag', 'audiofx', 'audioparsers', 'auparse', 'autodetect', 'avi'], list_sep: ', ', section: 'Plugins') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/meson_options.txt" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +option('enabled_opt', type: 'feature', value: 'auto') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('Some Subproject', version : '2.0') + +summary('string', 'bar') +summary({'integer': 1, 'boolean': true}) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/subprojects/sub2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/subprojects/sub2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/subprojects/sub2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/subprojects/sub2/meson.build" 2021-08-18 11:22:25.000000000 +0000 @@ -0,0 +1,6 @@ +project('sub2') + +subproject('subsub') + +summary('Section', 'Should not be seen') +error('This subproject failed') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/subprojects/sub2/subprojects/subsub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/subprojects/sub2/subprojects/subsub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/72 summary/subprojects/sub2/subprojects/subsub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/72 summary/subprojects/sub2/subprojects/subsub/meson.build" 2021-08-18 11:22:25.000000000 +0000 @@ -0,0 +1,3 @@ +project('subsub') + +summary('Something', 'Some value') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/74 dep files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/74 dep files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/74 dep files/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/74 dep files/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,16 @@ +project('test', 'c') + +python = import('python').find_installation() + +lib = library('foo', 'foo.c') + +# The library does not yet exist but we can already use its path during +# configuration. This should not trigger a reconfigure when the library is +# rebuilt. +configure_file( + output: 'out.txt', + capture: true, + command: [python, '-c', 'import sys; print(sys.argv[1])', lib.full_path()], +) + +message('Project configured') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/74 summary/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/74 summary/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/74 summary/meson.build" 2020-02-25 18:00:47.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/74 summary/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('My Project', version : '1.0') - -subproject('sub') -subproject('sub2', required : false) - -summary({'Some boolean': false, - 'Another boolean': true, - 'Some string': 'Hello World', - 'A list': ['string', 1, true], - 'empty list': [], - }, section: 'Configuration') -summary('A number', 1, section: 'Configuration') -summary('yes', true, bool_yn : true, section: 'Configuration') -summary('no', false, bool_yn : true, section: 'Configuration') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/74 summary/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/74 summary/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/74 summary/subprojects/sub/meson.build" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/74 summary/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('Some Subproject', version : '2.0') - -summary('string', 'bar') -summary({'integer': 1, 'boolean': true}) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/74 summary/subprojects/sub2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/74 summary/subprojects/sub2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/74 summary/subprojects/sub2/meson.build" 2020-01-23 22:29:05.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/74 summary/subprojects/sub2/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -project('sub2') - -error('This subproject failed') - -summary('Section', 'Should not be seen') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/client/client.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/client/client.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/client/client.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/client/client.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char **argv) +{ + printf("%d\n", val2()); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/client/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/client/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/client/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/client/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('client', 'c') +val2_dep = dependency('val2') +executable('client', 'client.c', dependencies : [val2_dep], install: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +project('val1', 'c') +val1 = shared_library('val1', 'val1.c', install: true) +install_headers('val1.h') +pkgconfig = import('pkgconfig') +pkgconfig.generate(val1, libraries : ['-Wl,-rpath,${libdir}']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val1/val1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val1/val1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val1/val1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val1/val1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#include "val1.h" + +int val1(void) { return 1; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val1/val1.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val1/val1.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val1/val1.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val1/val1.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int val1(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val2/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val2/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val2/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val2/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +project('val2', 'c') +val1_dep = dependency('val1') +val2 = shared_library('val2', 'val2.c', + dependencies : [val1_dep], + install: true) +install_headers('val2.h') +pkgconfig = import('pkgconfig') +pkgconfig.generate(val2, libraries : ['-Wl,-rpath,${libdir}']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val2/val2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val2/val2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val2/val2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val2/val2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +#include "val1.h" +#include "val2.h" + +int val2(void) { return val1() + 2; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val2/val2.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val2/val2.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/75 pkgconfig prefixes/val2/val2.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/75 pkgconfig prefixes/val2/val2.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +int val2(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/76 subdir libdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/76 subdir libdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/76 subdir libdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/76 subdir libdir/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +project('toplevel', 'c') +subproject('flub') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/76 subdir libdir/subprojects/flub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/76 subdir libdir/subprojects/flub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/76 subdir libdir/subprojects/flub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/76 subdir libdir/subprojects/flub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +project('subflub', 'c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/77 as link whole/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/77 as link whole/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/77 as link whole/bar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/77 as link whole/bar.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int bar(void); + +int bar(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/77 as link whole/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/77 as link whole/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/77 as link whole/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/77 as link whole/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +int foo(void); + +int foo(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/77 as link whole/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/77 as link whole/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/77 as link whole/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/77 as link whole/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +project('as-link-whole', 'c') + +foo = static_library('foo', 'foo.c', install: true) +dep = declare_dependency(link_with: foo) +bar1 = library('bar1', 'bar.c', dependencies: dep) +bar2 = library('bar2', 'bar.c', dependencies: dep.as_link_whole()) + +# bar1.pc should have -lfoo but not bar2.pc +pkg = import('pkgconfig') +pkg.generate(bar1) +pkg.generate(bar2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +project('own libc', 'c') + +# Not related to this test, but could not find a better place for this test. +assert(meson.get_cross_property('nonexisting', 'defaultvalue') == 'defaultvalue', + 'Cross prop getting is broken.') + +# A simple project that uses its own libc. + +# Note that we don't need to specify anything, the flags to use +# stdlib come from the cross file. + +exe = executable('selfcontained', 'prog.c') + +test('standalone test', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ + +#include + +int main(void) { + const char *message = "Hello without stdlib.\n"; + return simple_print(message, simple_strlen(message)); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/subprojects/mylibc/libc.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/subprojects/mylibc/libc.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/subprojects/mylibc/libc.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/subprojects/mylibc/libc.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,35 @@ +/* Do not use this as the basis of your own libc. + * The code is probably unoptimal or wonky, as I + * had no prior experience with this, but instead + * just fiddled with the code until it worked. + */ + +#include + +#define STDOUT 1 +#define SYS_WRITE 4 + +int simple_print(const char *msg, const long bufsize) { + int count; + long total_written = 0; + while(total_written < bufsize) { + asm( + "int $0x80\n\t" + : "=a"(count) + : "0"(SYS_WRITE), "b"(STDOUT), "c"(msg+total_written), "d"(bufsize-total_written) + :); + if(count == 0) { + return 1; + } + total_written += count; + } + return 0; +} + +int simple_strlen(const char *str) { + int len = 0; + while(str[len] != '\0') { + len++; + } + return len; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/subprojects/mylibc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/subprojects/mylibc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/subprojects/mylibc/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/subprojects/mylibc/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +project('own libc', 'c') + +# A very simple libc implementation + +# Do not specify -nostdlib & co. They come from cross specifications. + +libc = static_library('c', 'libc.c', 'stubstart.s') + +mylibc_dep = declare_dependency(link_with : libc, + include_directories : include_directories('.') +) + +meson.override_dependency('c_stdlib', mylibc_dep) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/subprojects/mylibc/stdio.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/subprojects/mylibc/stdio.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/subprojects/mylibc/stdio.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/subprojects/mylibc/stdio.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#pragma once + +int simple_print(const char *msg, const long bufsize); + +int simple_strlen(const char *str); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/subprojects/mylibc/stubstart.s" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/subprojects/mylibc/stubstart.s" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/78 nostdlib/subprojects/mylibc/stubstart.s" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/78 nostdlib/subprojects/mylibc/stubstart.s" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +.globl _start + +_start: + + call main + movl %eax, %ebx + movl $1, %eax + int $0x80 diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/75 user options for subproject/.gitignore" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/75 user options for subproject/.gitignore" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/75 user options for subproject/.gitignore" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/75 user options for subproject/.gitignore" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +subprojects/* diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/75 user options for subproject/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/75 user options for subproject/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/75 user options for subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/75 user options for subproject/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('user option for subproject') + +p = subproject('sub') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/.gitignore" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/.gitignore" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/.gitignore" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/.gitignore" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +/subprojects diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,45 @@ +project('options', 'c') + +if get_option('testoption') != 'optval' + error('Incorrect value to test option') +endif + +if get_option('other_one') != false + error('Incorrect value to boolean option.') +endif + +if get_option('combo_opt') != 'combo' + error('Incorrect value to combo option.') +endif + +if get_option('array_opt') != ['one', 'two'] + message(get_option('array_opt')) + error('Incorrect value for array option') +endif + +# If the default changes, update test cases/unit/13 reconfigure +if get_option('b_lto') != false + error('Incorrect value in base option.') +endif + +if get_option('includedir') != 'include' + error('Incorrect value in builtin option.') +endif + +if get_option('integer_opt') != 3 + error('Incorrect value in integer option.') +endif + +if get_option('neg_int_opt') != -3 + error('Incorrect value in negative integer option.') +endif + +if get_option('CaseSenSiTivE') != 'Some CAPS' + error('Incorrect value in mixed caps option.') +endif + +if get_option('CASESENSITIVE') != 'ALL CAPS' + error('Incorrect value in all caps option.') +endif + +assert(get_option('wrap_mode') == 'default', 'Wrap mode option is broken.') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/subprojects/sub/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/subprojects/sub/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/79 user options for subproject/subprojects/sub/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/79 user options for subproject/subprojects/sub/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +option('testoption', type : 'string', value : 'optval', description : 'An option ' + 'to do something') +option('other_one', type : 'boolean', value : not (not (not (not false)))) +option('combo_opt', type : 'co' + 'mbo', choices : ['one', 'two', 'combo'], value : 'combo') +option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two']) +option('free_array_opt', type : 'array') +option('integer_opt', type : 'integer', min : 0, max : -(-5), value : 3) +option('neg' + '_' + 'int' + '_' + 'opt', type : 'integer', min : -5, max : 5, value : -3) +option('CaseSenSiTivE', type : 'string', value: 'Some CAPS', description : 'An option with mixed capitaliziation') +option('CASESENSITIVE', type : 'string', value: 'ALL CAPS', description : 'An option with all caps') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/7 run installed/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/7 run installed/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/7 run installed/foo/meson.build" 2017-04-20 16:57:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/7 run installed/foo/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -4,4 +4,3 @@ foolib = shared_library('foo', 'foo.c', install_dir : 'foo', install : true) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/7 run installed/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/7 run installed/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/7 run installed/meson.build" 2017-04-20 16:57:27.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/7 run installed/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -6,4 +6,3 @@ executable('prog', 'prog.c', link_with : foolib, install : true) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('global-rpath', 'cpp') +yonder_dep = dependency('yonder') +executable('rpathified', 'rpathified.cpp', dependencies: [yonder_dep], install: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/rpathified.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/rpathified.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/rpathified.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/rpathified.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +#include +#include +int main(int argc, char **argv) +{ + return strcmp(yonder(), "AB54 6BR"); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/yonder/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/yonder/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/yonder/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/yonder/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +project('yonder', 'cpp') +yonder = shared_library('yonder', 'yonder.cpp', install: true) +install_headers('yonder.h') +pkgconfig = import('pkgconfig') +pkgconfig.generate(yonder) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/yonder/yonder.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/yonder/yonder.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/yonder/yonder.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/yonder/yonder.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#include "yonder.h" + +char *yonder(void) { return "AB54 6BR"; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/yonder/yonder.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/yonder/yonder.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/80 global-rpath/yonder/yonder.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/80 global-rpath/yonder/yonder.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +char *yonder(void); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/81 wrap-git/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/81 wrap-git/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/81 wrap-git/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/81 wrap-git/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('test-wrap-git') + +exe = subproject('wrap_git').get_variable('exe') +test('test1', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/81 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/81 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/81 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/81 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('foo', 'c') + +exe = executable('app', 'main.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/81 wrap-git/subprojects/wrap_git_upstream/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/81 wrap-git/subprojects/wrap_git_upstream/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/81 wrap-git/subprojects/wrap_git_upstream/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/81 wrap-git/subprojects/wrap_git_upstream/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/82 meson version compare/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/82 meson version compare/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/82 meson version compare/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/82 meson version compare/meson.build" 2021-08-18 11:22:25.000000000 +0000 @@ -0,0 +1,19 @@ +project('version compare', meson_version: '>= 0.1') + +if meson.version().version_compare('>= 9999') + error('This should not be executed') +elif meson.version().version_compare('>= 0.55') and false + error('This should not be executed') +elif not meson.version().version_compare('>= 0.55') + error('This should not be executed') +elif meson.version().version_compare('>= 0.55') + # This Should not produce warning even when using function not available in + # meson 0.1. + foo_dep = declare_dependency() + meson.override_dependency('foo', foo_dep) +endif + +# This will error out if elif cause did not enter +assert(foo_dep.found(), 'meson.version_compare did not work') + +subproject('foo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/82 meson version compare/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/82 meson version compare/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/82 meson version compare/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/82 meson version compare/subprojects/foo/meson.build" 2021-08-18 11:22:25.000000000 +0000 @@ -0,0 +1,8 @@ +project('foo', meson_version: '>= 0.1') + +if meson.version().version_compare('>= 0.55') + # This Should not produce warning even when using function not available in + # meson 0.1. + foo_dep = declare_dependency() + meson.override_dependency('foo2', foo_dep) +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/83 cross only introspect/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/83 cross only introspect/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/83 cross only introspect/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/83 cross only introspect/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +project('cross only introspect') +add_languages('c', native: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/84 change option choices/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/84 change option choices/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/84 change option choices/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/84 change option choices/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +project('change option choices') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/84 change option choices/meson_options.1.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/84 change option choices/meson_options.1.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/84 change option choices/meson_options.1.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/84 change option choices/meson_options.1.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +option( + 'combo', + type : 'combo', + choices : ['a', 'b', 'c'], + value : 'a', +) + +option( + 'array', + type : 'array', + choices : ['a', 'b', 'c'], + value : ['a'], +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/84 change option choices/meson_options.2.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/84 change option choices/meson_options.2.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/84 change option choices/meson_options.2.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/84 change option choices/meson_options.2.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,13 @@ +option( + 'combo', + type : 'combo', + choices : ['b', 'c', 'd'], + value : 'b', +) + +option( + 'array', + type : 'array', + choices : ['b', 'c', 'd'], + value : ['b'], +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/85 nested subproject regenerate depends/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/85 nested subproject regenerate depends/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/85 nested subproject regenerate depends/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/85 nested subproject regenerate depends/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/85 nested subproject regenerate depends/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/85 nested subproject regenerate depends/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/85 nested subproject regenerate depends/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/85 nested subproject regenerate depends/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +project('nested subproject regenerate depends', 'c') + +s = subproject('sub1') + +# This is needed to make msbuild noop check work correctly +executable('exe', 'main.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/85 nested subproject regenerate depends/subprojects/sub1/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/85 nested subproject regenerate depends/subprojects/sub1/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/85 nested subproject regenerate depends/subprojects/sub1/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/85 nested subproject regenerate depends/subprojects/sub1/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('sub1') + +cmake = import('cmake') +cmake.subproject('sub2') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/85 nested subproject regenerate depends/subprojects/sub2/CMakeLists.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/85 nested subproject regenerate depends/subprojects/sub2/CMakeLists.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/85 nested subproject regenerate depends/subprojects/sub2/CMakeLists.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/85 nested subproject regenerate depends/subprojects/sub2/CMakeLists.txt" 2021-10-23 16:42:59.000000000 +0000 @@ -0,0 +1 @@ +project(sub2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/main.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +import M0; +#include + +int main() { + printf("The value is %d", func0()); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +project('cppmodules', 'cpp', default_options: ['cpp_std=c++latest']) + +e = executable('modtest', + 'main.cpp', + 'src0.ixx', + 'src1.ixx', + 'src2.ixx', + 'src3.ixx', + 'src4.ixx', + 'src5.ixx', + 'src6.ixx', + 'src7.ixx', + 'src8.ixx', + 'src9.ixx', + ) + +test('modtest', e) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src0.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src0.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src0.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src0.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M0; + +import M1; + +export int func0() { + return func1(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src1.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src1.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src1.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src1.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M1; + +import M2; + +export int func1() { + return func2(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src2.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src2.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src2.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src2.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M2; + +import M3; + +export int func2() { + return func3(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src3.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src3.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src3.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src3.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M3; + +import M4; + +export int func3() { + return func4(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src4.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src4.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src4.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src4.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M4; + +import M5; + +export int func4() { + return func5(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src5.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src5.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src5.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src5.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M5; + +import M6; + +export int func5() { + return func6(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src6.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src6.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src6.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src6.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M6; + +import M7; + +export int func6() { + return func7(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src7.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src7.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src7.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src7.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M7; + +import M8; + +export int func7() { + return func8(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src8.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src8.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src8.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src8.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +export module M8; + +import M9; + +export int func8() { + return func9(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src9.ixx" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src9.ixx" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/86 cpp modules/src9.ixx" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/86 cpp modules/src9.ixx" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +export module M9; + +export int func9() { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/file1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/file1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/file1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/file1.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,14 @@ +#include +#include + +int public_func() { + return round1_a(); +} + +int round1_a() { + return round1_b(); +} + +int round2_a() { + return round2_b(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/file2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/file2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/file2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/file2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#include + +int round1_b() { + return round1_c(); +} + +int round2_b() { + return round2_c(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/file3.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/file3.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/file3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/file3.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#include + +int round1_c() { + return round1_d(); +} + +int round2_c() { + return round2_d(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/file4.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/file4.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/file4.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/file4.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#include + +int round1_d() { + return round2_a(); +} + +int round2_d() { + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include + +int main(int argc, char **argv) { + if(public_func() != 42) { + printf("Something failed.\n"); + return 1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +project('prelinking', 'c') + +liba = static_library('prelinked', 'file1.c', 'file2.c', 'file3.c', 'file4.c', + prelink: true) +exe = executable('testprog', 'main.c', + link_with: liba) +test('prelinked', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/private_header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/private_header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/private_header.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/private_header.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,11 @@ +#pragma once + +int round1_a(); +int round1_b(); +int round1_c(); +int round1_d(); + +int round2_a(); +int round2_b(); +int round2_c(); +int round2_d(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/public_header.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/public_header.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/87 prelinking/public_header.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/87 prelinking/public_header.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +#pragma once + +int public_func(); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/88 run native test/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/88 run native test/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/88 run native test/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/88 run native test/main.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,17 @@ +#include + +int main (int argc, char * argv[]) +{ + const char *out = "SUCCESS!"; + + if (argc != 2) { + printf ("%s\n", out); + } else { + int ret; + FILE *f = fopen (argv[1], "w"); + ret = fwrite (out, sizeof (out), 1, f); + if (ret != 1) + return -1; + } + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/88 run native test/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/88 run native test/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/88 run native test/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/88 run native test/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +project('run native test', ['c']) + +executable('terget_exe', 'main.c') + +native_exe = executable('native_exe', 'main.c', native: true) +test('native_exe', native_exe, args: ['native_test_has_run.stamp']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/89 multiple envvars/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/89 multiple envvars/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/89 multiple envvars/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/89 multiple envvars/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +project('multienv', 'c', 'cpp') + +executable('cexe', 'prog.c') +executable('cppexe', 'prog.cpp') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/89 multiple envvars/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/89 multiple envvars/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/89 multiple envvars/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/89 multiple envvars/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#include + +#ifndef CPPFLAG +#error CPPFLAG not set +#endif + +#ifndef CFLAG +#error CFLAGS not set +#endif + +#ifdef CXXFLAG +#error CXXFLAG is set +#endif + +int main(int argc, char **argv) { + printf("%d %s\n", argc, argv[0]); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/89 multiple envvars/prog.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/89 multiple envvars/prog.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/89 multiple envvars/prog.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/89 multiple envvars/prog.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,18 @@ +#include + +#ifndef CPPFLAG +#error CPPFLAG not set +#endif + +#ifdef CFLAG +#error CFLAG is set +#endif + +#ifndef CXXFLAG +#error CXXFLAG not set +#endif + +int main(int argc, char **argv) { + printf("%d %s\n", argc, argv[0]); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/dummy.pc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/dummy.pc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/dummy.pc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/dummy.pc" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,7 @@ +prefix=/foo +libdir=${prefix}/dummy + +Name: dummy +Description: Nonexisting lib but add an rpath +Version: 1.0.0 +Libs: -Wl,-rpath,${libdir} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,20 @@ +project('build rpath', 'c', 'cpp') + +subdir('sub') +pkgconf_dep = dependency('dummy') + +executable('prog', 'prog.c', + dependencies : pkgconf_dep, + link_with : l, + build_rpath : '/foo/bar', + install_rpath : '/baz', + install : true, + ) + +executable('progcxx', 'prog.cc', + dependencies : pkgconf_dep, + link_with : l, + build_rpath : '/foo/bar', + install_rpath : 'baz', + install : true, + ) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/prog.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,5 @@ +int get_stuff(); + +int main(int argc, char **argv) { + return get_stuff(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/prog.cc" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/prog.cc" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/prog.cc" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/prog.cc" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char **argv) { + std::string* s = new std::string("Hello"); + delete s; + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/sub/meson.build" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1 @@ +l = shared_library('stuff', 'stuff.c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/sub/stuff.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/sub/stuff.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/90 pkgconfig build rpath order/sub/stuff.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/90 pkgconfig build rpath order/sub/stuff.c" 2021-04-01 21:13:00.000000000 +0000 @@ -0,0 +1,3 @@ +int get_stuff() { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/main.c" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,14 @@ +#include + +#ifdef _WIN32 + #define DO_IMPORT __declspec(dllimport) +#else + #define DO_IMPORT +#endif + +DO_IMPORT int foo(void); + +int main(void) { + printf("This is text.\n"); + return foo(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/meson.build" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,12 @@ +project('devenv', 'c') + +meson.add_devenv('TEST_A=1') +foo_dep = dependency('foo', fallback: 'sub') + +env = environment() +env.append('TEST_B', ['2', '3'], separator: '+') +meson.add_devenv(env) + +# This exe links on a library built in another directory. On Windows this means +# PATH must contain builddir/subprojects/sub to be able to run it. +executable('app', 'main.c', dependencies: foo_dep, install: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/subprojects/sub/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/subprojects/sub/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/subprojects/sub/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/subprojects/sub/foo.c" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,10 @@ +#ifdef _WIN32 + #define DO_EXPORT __declspec(dllexport) +#else + #define DO_EXPORT +#endif + +DO_EXPORT int foo(void) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/subprojects/sub/meson.build" 2021-04-27 06:49:45.000000000 +0000 @@ -0,0 +1,6 @@ +project('sub', 'c') + +meson.add_devenv({'TEST_B': '1'}) + +libfoo = shared_library('foo', 'foo.c') +meson.override_dependency('foo', declare_dependency(link_with: libfoo)) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/test-devenv.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/test-devenv.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/91 devenv/test-devenv.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/91 devenv/test-devenv.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,8 @@ +#! /usr/bin/python + +import os + +assert os.environ['MESON_DEVENV'] == '1' +assert os.environ['MESON_PROJECT_NAME'] == 'devenv' +assert os.environ['TEST_A'] == '1' +assert os.environ['TEST_B'] == '1+2+3' diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int main(int argc, char *argv[]) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/foo.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/foo.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/foo.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/foo.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +dummy diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/foo.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/foo.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/foo.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/foo.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#define FOO diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,8 @@ +project('foo', 'c') + +install_data('foo.dat') +install_headers('foo.h') +install_subdir('foo', install_dir: '') +executable('foo', 'foo.c', install: true) + +subproject('bar') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +dummy diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +int main(int argc, char *argv[]) +{ + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +dummy diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +#define FOO diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +project('bar', 'c') + +install_data('bar.dat') +install_headers('bar.h') +install_subdir('bar', install_dir: '') +executable('bar', 'bar.c', install: true) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/93 new subproject in configured project/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/93 new subproject in configured project/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/93 new subproject in configured project/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/93 new subproject in configured project/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +# SPDX-license-identifier: Apache-2.0 +# Copyright © 2021 Intel Corporation +project('existing project with new subproject', 'c') + +if get_option('use-sub') + dep = subproject('sub') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/93 new subproject in configured project/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/93 new subproject in configured project/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/93 new subproject in configured project/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/93 new subproject in configured project/meson_options.txt" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +# SPDX-license-identifier: Apache-2.0 +# Copyright © 2021 Intel Corporation +option('use-sub', type : 'boolean', value : false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,6 @@ +/* SPDX-license-identifier: Apache-2.0 */ +/* Copyright © 2021 Intel Corporation */ + +int func(void) { + return 1; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +# SPDX-license-identifier: Apache-2.0 +# Copyright © 2021 Intel Corporation +project('new subproject', 'c') + +l = library('foo', 'foo.c') + +dep = declare_dependency(link_with : l) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/.clang-format" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/.clang-format" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/.clang-format" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/.clang-format" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,4 @@ +--- +BasedOnStyle: Google + +... diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/.clang-format-ignore" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/.clang-format-ignore" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/.clang-format-ignore" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/.clang-format-ignore" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ + +# Ignore C files +*.c diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/.clang-format-include" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/.clang-format-include" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/.clang-format-include" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/.clang-format-include" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ + +# Only reformat in src/ +src/**/* diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1 @@ +project('dummy', 'c', 'cpp') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/not-included/badformat.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/not-included/badformat.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/not-included/badformat.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/not-included/badformat.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +class { +}; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/src/badformat.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/src/badformat.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/src/badformat.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/src/badformat.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +struct { +}; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/src/badformat.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/src/badformat.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/94 clangformat/src/badformat.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/94 clangformat/src/badformat.cpp" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,2 @@ +class { +}; diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/easytogrepfor/genh.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/easytogrepfor/genh.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/easytogrepfor/genh.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/easytogrepfor/genh.py" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys + +f = open(sys.argv[1], 'w') +f.write('#define RETURN_VALUE 0') +f.close() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/easytogrepfor/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/easytogrepfor/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/easytogrepfor/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/easytogrepfor/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,3 @@ +genh = custom_target('header', + output: 'generated.h', + command: [find_program('genh.py'), '@OUTPUT@']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/helper.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/helper.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/helper.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/helper.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int func(void) { + return RETURN_VALUE; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/meson.build" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +project('implicit custom dirs', 'c') + +subdir('easytogrepfor') + +l = static_library('helper', 'helper.c', genh) +d = declare_dependency(link_with: l, sources: genh) +executable('prog', 'prog.c', dependencies: d, implicit_include_directories: false) + +executable('prog2', 'prog2.c', dependencies: d) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/prog2.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/prog2.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/prog2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/prog2.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include + +int func(void); + +int main(int argc, char **argv) { + (void)argc; + (void)(argv); + return func() + RETURN_VALUE; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/95 custominc/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/95 custominc/prog.c" 2021-04-27 06:50:21.000000000 +0000 @@ -0,0 +1,9 @@ +#include + +int func(void); + +int main(int argc, char **argv) { + (void)argc; + (void)(argv); + return func(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/96 implicit force fallback/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/96 implicit force fallback/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/96 implicit force fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/96 implicit force fallback/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,8 @@ +project('implicit force fallback') + +# The dependency 'something' is provided by a subproject. Normally this won't +# use the fallback subproject because required is false. However this unit test +# is configured with wrap_mode=forcefallback and force_fallback_for=something +# in which case we are expecting the fallback to be done. +d = dependency('something', required: false) +assert(d.found()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/96 implicit force fallback/subprojects/something/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/96 implicit force fallback/subprojects/something/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/96 implicit force fallback/subprojects/something/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/96 implicit force fallback/subprojects/something/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,3 @@ +project('something') + +meson.override_dependency('something', declare_dependency()) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/97 compiler.links file arg/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/97 compiler.links file arg/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/97 compiler.links file arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/97 compiler.links file arg/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,11 @@ +project('test', ['c', 'cpp']) + +cc = meson.get_compiler('c') +cxx = meson.get_compiler('cpp') + +# used by run_unittests.py to grab the path to the C and C++ compilers +assert(cc.compiles(files('test.c'))) +assert(cxx.compiles(files('test.c'))) + +assert(cc.links(files('test.c'))) +assert(cxx.links(files('test.c'))) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/97 compiler.links file arg/test.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/97 compiler.links file arg/test.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/97 compiler.links file arg/test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/97 compiler.links file arg/test.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +int main(void) { return 0; } diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/.gitignore" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/.gitignore" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/.gitignore" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/.gitignore" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,5 @@ +*.a +*.o +a.out +libtestprovider.a +build diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/libtestprovider/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/libtestprovider/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/libtestprovider/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/libtestprovider/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,20 @@ +project('libtestprovider','c') + +libtestprovider=static_library('testprovider', + files('./provider.c'), + install:true, + c_args:['-Wall','-Werror'], +) + +pkg = import('pkgconfig') + + +pkg.generate( + name:'testprovider', + filebase:'libtestprovider', + description: 'fortest', + requires: [], + libraries_private: ['-Wl,--whole-archive'] + + ['-L${libdir}','-l:libtestprovider.a']+ + ['-Wl,--no-whole-archive'] +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/libtestprovider/provider.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/libtestprovider/provider.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/libtestprovider/provider.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/libtestprovider/provider.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,12 @@ +#include +static int g_checked = 0; + +static void __attribute__((constructor(101), used)) init_checked(void) { + g_checked=100; + fprintf(stdout, "inited\n"); +} + + +int get_checked(void) { + return g_checked; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/proguser/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/proguser/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/proguser/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/proguser/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,11 @@ +project('testprovider','c') + +deplib = dependency('libtestprovider', static:true) + +dprovidertest = executable('dprovidertest', + files('./receiver.c'), + dependencies:[deplib], + c_args:['-Wall','-Werror'], +) + +test('testprovider',dprovidertest) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/proguser/receiver.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/proguser/receiver.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/98 link full name/proguser/receiver.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/98 link full name/proguser/receiver.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,18 @@ +#include +int __attribute__((weak)) get_checked(void) { + return -1; +} + + +#define CHECK_VALUE (100) +#define TEST_SUCCESS (0) +#define TEST_FAILTURE (-1) + +int main(void) { + if (get_checked() == CHECK_VALUE) { + fprintf(stdout,"good\n"); + return TEST_SUCCESS; + } + fprintf(stdout,"bad\n"); + return TEST_FAILTURE; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/custom_files/data.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/custom_files/data.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/custom_files/data.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/custom_files/data.txt" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1 @@ +Hello World diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/lib.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,9 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else +#define DLL_PUBLIC +#endif + +int DLL_PUBLIC foo(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/main.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +int main(int argc, char *argv[]) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,82 @@ +project('install tag', 'c') + +subdir('subdir') + +# Those files should not be tagged +configure_file(input: 'foo.in', output: 'foo-notag.h', + configuration: {'foo': 'bar'}, + install_dir: get_option('datadir'), + install: true, +) +install_data('bar-notag.txt', + install_dir: get_option('datadir') +) +custom_target('ct1', + output: ['out1-notag.txt', 'out2-notag.txt'], + command: ['script.py', '@OUTPUT@'], + install_dir: get_option('datadir'), + install: true, +) + +# Those files should be tagged as devel +install_headers('foo1-devel.h') +install_data('bar-devel.h', + install_dir: get_option('includedir'), +) +configure_file(input: 'foo.in', output: 'foo2-devel.h', + configuration: {'foo': 'bar'}, + install_dir: get_option('includedir'), + install: true, +) +static_library('static', 'lib.c', + install: true, +) + +# Those files should have 'runtime' tag +executable('app', 'main.c', + install: true, +) +shared_library('shared', 'lib.c', + install: true, +) +both_libraries('both', 'lib.c', + install: true, +) + +# Those files should have custom tag +install_data('bar-custom.txt', + install_dir: get_option('datadir'), + install_tag: 'custom') +configure_file(input: 'foo.in', output: 'foo-custom.h', + configuration: {'foo': 'bar'}, + install_dir: get_option('datadir'), + install_tag: 'custom', + install: true, +) +both_libraries('bothcustom', 'lib.c', + install_tag: 'custom', + install: true, +) +custom_target('ct2', + output: ['out1-custom.txt', 'out2-custom.txt'], + command: ['script.py', '@OUTPUT@'], + install_dir: get_option('datadir'), + install_tag: 'custom', + install: true, +) +install_subdir('custom_files', + install_dir: get_option('datadir'), + install_tag: 'custom', +) + +# First is custom, 2nd is devel, 3rd has no tag +custom_target('ct3', + output: ['out3-custom.txt', 'out-devel.h', 'out3-notag.txt'], + command: ['script.py', '@OUTPUT@'], + install_dir: [get_option('datadir'), get_option('includedir'), get_option('datadir')], + install_tag: ['custom', 'devel', false], + install: true, +) + +meson.add_install_script('script.py', install_tag: 'custom') +meson.add_install_script('script.py') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/script.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/script.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/script.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/script.py" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys + +for f in sys.argv[1:]: + with open(f, 'w') as f: + pass diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/subdir/lib.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/subdir/lib.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/subdir/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/subdir/lib.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,9 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else +#define DLL_PUBLIC +#endif + +int DLL_PUBLIC foo(void) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/subdir/main.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/subdir/main.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/subdir/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/subdir/main.c" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,3 @@ +int main(int argc, char *argv[]) { + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/subdir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/subdir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/subdir/meson.build" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,21 @@ +configure_file(input: 'foo2.in', output: 'foo2.h', + configuration: {'foo': 'bar'}, + install_dir: get_option('datadir'), + install: true, +) +custom_target('ct4', + output: ['out1.txt', 'out2.txt'], + command: ['script.py', '@OUTPUT@'], + install_dir: get_option('datadir'), + install: true, +) +install_headers('foo3-devel.h') +install_data('bar2-devel.h', + install_dir: get_option('includedir'), +) +executable('app2', 'main.c', + install: true, +) +both_libraries('both2', 'lib.c', + install: true, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/subdir/script.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/subdir/script.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/99 install all targets/subdir/script.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/99 install all targets/subdir/script.py" 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys + +for f in sys.argv[1:]: + with open(f, 'w') as f: + pass diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/9 d dedup/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/9 d dedup/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/unit/9 d dedup/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/unit/9 d dedup/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -3,4 +3,3 @@ add_project_arguments('-D', 'FOO', '-D', 'BAR', language : 'c') executable('prog', 'prog.c') - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -usr/bin/vapigen-test?exe -usr/lib/?libfoo.so -?cygwin:usr/lib/libfoo.dll.a -usr/lib/?libbar.so -?cygwin:usr/lib/libbar.dll.a -usr/share/vala/vapi/foo-1.0.vapi -usr/share/vala/vapi/foo-1.0.deps -usr/share/vala/vapi/bar-1.0.vapi -usr/share/vala/vapi/bar-1.0.deps diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/libbar/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/libbar/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/libbar/meson.build" 2016-12-13 21:40:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/libbar/meson.build" 2021-12-26 16:24:25.000000000 +0000 @@ -19,7 +19,6 @@ sources: libbar_sources, namespace: 'Bar', nsversion: libbar_api_ver, - packages: 'gobject-2.0', symbol_prefix: 'bar', extra_args: [ '--c-include=bar.h', diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/libfoo/foo.metadata" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/libfoo/foo.metadata" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/libfoo/foo.metadata" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/libfoo/foo.metadata" 2022-01-17 10:50:38.000000000 +0000 @@ -0,0 +1 @@ +Foo.bar nullable diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/libfoo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/libfoo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/libfoo/meson.build" 2016-12-13 21:40:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/libfoo/meson.build" 2022-01-17 10:50:38.000000000 +0000 @@ -18,14 +18,20 @@ sources: libfoo_sources, namespace: 'Foo', nsversion: libfoo_api_ver, - packages: 'gobject-2.0', symbol_prefix: 'foo', extra_args: [ '--c-include=foo.h', ], ) +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 -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/11 generated vapi/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/11 generated vapi/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,13 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/vapigen-test"}, + {"type": "expr", "file": "usr/lib/?libfoo.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libfoo.dll.a"}, + {"type": "expr", "file": "usr/lib/?libbar.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libbar.dll.a"}, + {"type": "file", "file": "usr/share/vala/vapi/foo-1.0.vapi"}, + {"type": "file", "file": "usr/share/vala/vapi/foo-1.0.deps"}, + {"type": "file", "file": "usr/share/vala/vapi/bar-1.0.vapi"}, + {"type": "file", "file": "usr/share/vala/vapi/bar-1.0.deps"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/1 basic/meson.build" 2020-01-07 21:11:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/1 basic/meson.build" 2021-10-23 16:52:11.000000000 +0000 @@ -1,4 +1,5 @@ -project('valatest', 'vala', 'c') +# Language are case unsensitive, check here that capital C works too. +project('valatest', 'vala', 'C') valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')] diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/20 genie multiple mixed sources/init.gs" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/20 genie multiple mixed sources/init.gs" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/20 genie multiple mixed sources/init.gs" 2017-07-21 20:07:34.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/20 genie multiple mixed sources/init.gs" 2021-11-02 19:58:07.000000000 +0000 @@ -8,4 +8,3 @@ assert( new Vala.TestTwo().is_true() ) assert( c_test_one_is_true() ) assert( c_test_two_is_true() ) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/2 multiple files/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/2 multiple files/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/2 multiple files/meson.build" 2020-01-07 21:11:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/2 multiple files/meson.build" 2021-10-23 16:52:12.000000000 +0000 @@ -1,4 +1,5 @@ -project('multiple files', 'c') +# adding 'c' shouldn't be required +project('multiple files') add_languages('vala') glib = dependency('glib-2.0') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/6 static library/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/6 static library/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/6 static library/installed_files.txt" 2016-11-13 21:03:31.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/6 static library/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/lib/libextractedlib.a diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/6 static library/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/6 static library/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/6 static library/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/6 static library/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/libextractedlib.a"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/7 shared library/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/7 shared library/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/7 shared library/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/7 shared library/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -usr/lib/?libinstalled_vala_lib.so -?cygwin:usr/lib/libinstalled_vala_lib.dll.a -usr/lib/?libinstalled_vala_all.so -?cygwin:usr/lib/libinstalled_vala_all.dll.a -usr/include/installed_vala_all.h -usr/include/valah/installed_vala_all_nolib.h -usr/include/installed_vala_onlyh.h -usr/share/vala/vapi/installed_vala_all.vapi -usr/share/vala-1.0/vapi/installed_vala_all_nolib.vapi -usr/share/vala/vapi/installed_vala_onlyvapi.vapi diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/7 shared library/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/7 shared library/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/7 shared library/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/7 shared library/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,14 @@ +{ + "installed": [ + {"type": "expr", "file": "usr/lib/?libinstalled_vala_lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libinstalled_vala_lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libinstalled_vala_all.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libinstalled_vala_all.dll.a"}, + {"type": "file", "file": "usr/include/installed_vala_all.h"}, + {"type": "file", "file": "usr/include/valah/installed_vala_all_nolib.h"}, + {"type": "file", "file": "usr/include/installed_vala_onlyh.h"}, + {"type": "file", "file": "usr/share/vala/vapi/installed_vala_all.vapi"}, + {"type": "file", "file": "usr/share/vala-1.0/vapi/installed_vala_all_nolib.vapi"}, + {"type": "file", "file": "usr/share/vala/vapi/installed_vala_onlyvapi.vapi"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/8 generated sources/dependency-generated/enum-types.c.template" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/8 generated sources/dependency-generated/enum-types.c.template" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/8 generated sources/dependency-generated/enum-types.c.template" 2016-12-18 18:47:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/8 generated sources/dependency-generated/enum-types.c.template" 2021-11-02 19:58:07.000000000 +0000 @@ -14,9 +14,9 @@ GType @enum_name@_get_type (void) { - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) { + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) { static const G@Type@Value values[] = { /*** END value-header ***/ @@ -27,13 +27,13 @@ /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; - GType g_define_type_id = + GType g_define_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + + g_once_init_leave (&static_g_define_type_id, g_define_type_id); } - - return g_define_type_id__volatile; + + return static_g_define_type_id; } /*** END value-tail ***/ diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/8 generated sources/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/8 generated sources/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/8 generated sources/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/8 generated sources/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/bin/generatedtestparent?exe -usr/bin/generatedtest?exe -usr/bin/onlygentest?exe diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/8 generated sources/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/8 generated sources/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/8 generated sources/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/8 generated sources/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/generatedtestparent"}, + {"type": "exe", "file": "usr/bin/generatedtest"}, + {"type": "exe", "file": "usr/bin/onlygentest"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/9 gir/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/9 gir/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/9 gir/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/9 gir/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -?gcc:usr/lib/?libfoo.so -?cygwin:usr/lib/libfoo.dll.a -usr/share/gir-1.0/Foo-1.0.gir diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/9 gir/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/9 gir/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/9 gir/meson.build" 2020-01-07 21:11:41.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/9 gir/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -15,4 +15,3 @@ input: meson.current_build_dir() + '/Foo-1.0.gir', output: 'Foo-1.0.typelib', depends: foo) - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/9 gir/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/9 gir/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/vala/9 gir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/vala/9 gir/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "installed": [ + {"type": "expr", "platform": "gcc", "file": "usr/lib/?libfoo.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libfoo.dll.a"}, + {"type": "file", "file": "usr/share/gir-1.0/Foo-1.0.gir"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/1 version for string div/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/1 version for string div/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/1 version for string div/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/1 version for string div/test.json" 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "comment": "literal '/' appears in output, irrespective of os.path.sep, as that's the operator", + "line": "test cases/warning/1 version for string div/meson.build:3: WARNING: Project targeting '>=0.48.0' but tried to use feature introduced in '0.49.0': / with string arguments." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/2 languages missing native/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/2 languages missing native/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/2 languages missing native/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/2 languages missing native/meson.build" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,3 @@ +project('languages missing native', + meson_version : '>= 0.54') +add_languages('c') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/2 languages missing native/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/2 languages missing native/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/2 languages missing native/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/2 languages missing native/test.json" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/warning/2 languages missing native/meson.build:3: WARNING: add_languages is missing native:, assuming languages are wanted for both host and build." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/3 fallback consistency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/3 fallback consistency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/3 fallback consistency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/3 fallback consistency/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +project('proj', 'c') + +# The first call succeed and cache the value of 'sub' dependency. The 2nd call +# should return the cached value, but still verify the fallback variable is +# consistent. +dependency('sub', fallback : ['sub', 'dep1']) +dependency('sub', fallback : ['sub', 'dep2']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/3 fallback consistency/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/3 fallback consistency/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/3 fallback consistency/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/3 fallback consistency/subprojects/sub/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +project('proj', 'c') + +dep1 = declare_dependency() +dep2 = declare_dependency() +meson.override_dependency('sub', dep1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/3 fallback consistency/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/3 fallback consistency/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/3 fallback consistency/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/3 fallback consistency/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "WARNING: Inconsistency: Subproject has overridden the dependency with another variable than 'dep2'" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/4 fallback consistency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/4 fallback consistency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/4 fallback consistency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/4 fallback consistency/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('proj', 'c') + +# Subproject overrides 'sub' with another variable than dep2. This should warn. +dependency('sub', fallback : ['sub', 'dep2']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/4 fallback consistency/subprojects/sub/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/4 fallback consistency/subprojects/sub/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/4 fallback consistency/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/4 fallback consistency/subprojects/sub/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,5 @@ +project('proj', 'c') + +dep1 = declare_dependency() +dep2 = declare_dependency() +meson.override_dependency('sub', dep1) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/4 fallback consistency/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/4 fallback consistency/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/4 fallback consistency/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/4 fallback consistency/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "WARNING: Inconsistency: Subproject has overridden the dependency with another variable than 'dep2'" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/5 fallback consistency/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/5 fallback consistency/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/5 fallback consistency/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/5 fallback consistency/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,4 @@ +project('fallback consistency') + +# Subproject overrides foo with foo_dep but wrap file says it's bar_dep. This should warn. +dependency('foo') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/5 fallback consistency/subprojects/foo/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/5 fallback consistency/subprojects/foo/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/5 fallback consistency/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/5 fallback consistency/subprojects/foo/meson.build" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +project('sub') + +foo_dep = declare_dependency() +meson.override_dependency('foo', foo_dep) + +bar_dep = declare_dependency() diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/5 fallback consistency/subprojects/foo.wrap" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/5 fallback consistency/subprojects/foo.wrap" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/5 fallback consistency/subprojects/foo.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/5 fallback consistency/subprojects/foo.wrap" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,6 @@ +[wrap-file] +source_url = http://host.invalid/foo.tar.gz +source_filename = foo.tar.gz + +[provide] +foo = bar_dep diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/5 fallback consistency/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/5 fallback consistency/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/5 fallback consistency/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/5 fallback consistency/test.json" 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "WARNING: Inconsistency: Subproject has overridden the dependency with another variable than 'bar_dep'" + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/6 list add/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/6 list add/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/6 list add/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/6 list add/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +project('test list add', meson_version: '>=0.59.0') + +l1 = [1, 2, 3] +l2 = l1 + 4 +l2 += 5 + +message(l2) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/6 list add/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/6 list add/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/warning/6 list add/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/warning/6 list add/test.json" 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/warning/6 list add/meson.build:4: WARNING: Project targeting '>=0.59.0' but tried to use feature introduced in '0.60.0': list.. The right hand operand was not a list." + } + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/1 basic/hello.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/1 basic/hello.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/1 basic/hello.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/1 basic/hello.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +#include + +int main() { + printf("Hello World\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/1 basic/hello.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/1 basic/hello.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/1 basic/hello.cpp" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/1 basic/hello.cpp" 2021-11-02 19:58:07.000000000 +0000 @@ -4,4 +4,3 @@ std::cout << "Hello World" << std::endl; return 0; } - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/1 basic/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/1 basic/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/1 basic/meson.build" 2019-08-28 17:15:39.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/1 basic/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -1,3 +1,4 @@ -project('emcctest', 'cpp') +project('emcctest', 'c', 'cpp') +executable('hello-c', 'hello.c') executable('hello', 'hello.cpp') diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/2 threads/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/2 threads/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/2 threads/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/2 threads/meson.build" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,10 @@ +project( + 'threads', + 'c', 'cpp', + default_options : ['cpp_std=c++11'], +) + +dep_threads = dependency('threads') + +executable('threads-c', 'threads.c', dependencies : dep_threads) +executable('threads-c++', 'threads.cpp', dependencies : dep_threads) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/2 threads/threads.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/2 threads/threads.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/2 threads/threads.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/2 threads/threads.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,21 @@ +#include +#include +#include + +void inthread(void * args) { + sleep(1); + printf("In thread\n"); +} + +int main() { +#ifdef __EMSCRIPTEN_PTHREADS__ + pthread_t thread_id; + printf("Before Thread\n"); + pthread_create(&thread_id, NULL, (void *)*inthread, NULL); + pthread_join(thread_id, NULL); + printf("After Thread\n"); + return 0; +#else +# error "threads not enabled\n" +#endif +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/2 threads/threads.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/2 threads/threads.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/2 threads/threads.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/2 threads/threads.cpp" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,13 @@ +#include +#include +#include + +int main(void) { + std::cout << "Before thread" << std::endl; + std::thread t([]() { + sleep(1); + std::cout << "In a thread." << std::endl; + }); + t.join(); + std::cout << "After thread" << std::endl; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/3 jslib/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/3 jslib/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/3 jslib/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/3 jslib/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,8 @@ +project('jslib', 'c') + +cc = meson.get_compiler('c') + +sf_dep = cc.find_library('somefuncs.js', dirs: meson.current_source_dir()) + +executable('libcallc', 'prog.c', + dependencies: sf_dep) \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/3 jslib/prog.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/3 jslib/prog.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/3 jslib/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/3 jslib/prog.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,10 @@ +#include +#include + +extern void sample_function(); + +int main() { + printf("Hello World\n"); + // sampleFunction(); ???? + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/3 jslib/somefuncs.js" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/3 jslib/somefuncs.js" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/wasm/3 jslib/somefuncs.js" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/wasm/3 jslib/somefuncs.js" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +mergeInto(LibraryManager.library, { + sample_function__sig: 'v', + sample_function: function() { + alert("Something happened!"); + }, +}); diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/10 vs module defs generated custom target/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/10 vs module defs generated custom target/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/10 vs module defs generated custom target/meson.build" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/10 vs module defs generated custom target/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -1,10 +1,5 @@ project('generated_dll_module_defs', 'c') -if meson.backend().startswith('vs') - # FIXME: Broken on the VS backends - error('MESON_SKIP_TEST see https://github.com/mesonbuild/meson/issues/1799') -endif - subdir('subdir') exe = executable('prog', 'prog.c', link_with : shlib) test('runtest', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/11 exe implib/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/11 exe implib/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/11 exe implib/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/11 exe implib/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -usr/bin/prog.exe -?msvc:usr/bin/prog.pdb -usr/bin/prog2.exe -?msvc:usr/bin/prog2.pdb -?gcc:usr/lib/libprog.exe.a -?gcc:usr/lib/libburble.a -?msvc:usr/lib/prog.exe.lib -?msvc:usr/lib/burble.lib diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/11 exe implib/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/11 exe implib/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/11 exe implib/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/11 exe implib/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,12 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/prog.exe"}, + {"type": "pdb", "file": "usr/bin/prog"}, + {"type": "file", "file": "usr/bin/prog2.exe"}, + {"type": "pdb", "file": "usr/bin/prog2"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libprog.exe.a"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libburble.a"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/prog.exe.lib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/burble.lib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/12 resources with custom targets/res/gen-res.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/12 resources with custom targets/res/gen-res.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/12 resources with custom targets/res/gen-res.py" 2018-10-31 09:31:20.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/12 resources with custom targets/res/gen-res.py" 2021-04-27 06:49:45.000000000 +0000 @@ -2,5 +2,5 @@ import sys -with open(sys.argv[1], 'r') as infile, open(sys.argv[2], 'w') as outfile: +with open(sys.argv[1]) as infile, open(sys.argv[2], 'w') as outfile: outfile.write(infile.read().format(icon=sys.argv[3])) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/16 gui app/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/16 gui app/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/16 gui app/meson.build" 2020-01-23 12:51:19.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/16 gui app/meson.build" 2021-04-01 21:12:21.000000000 +0000 @@ -6,16 +6,21 @@ # console_lib = static_library('main', 'console_prog.c') -executable('console', 'dummy.c', link_with: console_lib, gui_app: false) +executable('console', 'dummy.c', link_with: console_lib, win_subsystem: 'console') +executable('console2', 'dummy.c', link_with: console_lib, gui_app: false) # # also verify that the correct subsystem is set by executable(gui_app:) # -gui_prog = executable('gui_prog', 'gui_prog.c', gui_app: true) -console_prog = executable('console_prog', 'console_prog.c', gui_app: false) +gui_prog = executable('gui_prog', 'gui_prog.c', win_subsystem: 'windows,6.0') +gui_prog2 = executable('gui_prog2', 'gui_prog.c', gui_app: true) +console_prog = executable('console_prog', 'console_prog.c', win_subsystem: 'console') +console_prog2 = executable('console_prog2', 'console_prog.c', gui_app: false) tester = find_program('gui_app_tester.py') test('is_gui', tester, args: [gui_prog, '2']) +test('is_gui2', tester, args: [gui_prog2, '2']) test('not_gui', tester, args: [console_prog, '3']) +test('not_gui2', tester, args: [console_prog2, '3']) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/17 msvc ndebug/main.cpp" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/17 msvc ndebug/main.cpp" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/17 msvc ndebug/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/17 msvc ndebug/main.cpp" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,9 @@ +int main() { +#ifdef NDEBUG + // NDEBUG is defined + return 0; +#else + // NDEBUG is not defined + return 1; +#endif +} \ No newline at end of file diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/17 msvc ndebug/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/17 msvc ndebug/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/17 msvc ndebug/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/17 msvc ndebug/meson.build" 2021-04-01 21:12:21.000000000 +0000 @@ -0,0 +1,7 @@ +project('msvc_ndebug', 'cpp', + default_options : [ 'b_ndebug=true' ] +) + +exe = executable('exe', 'main.cpp') + +test('ndebug', exe) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/18 msvc charset/iso-8859-1.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/18 msvc charset/iso-8859-1.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/18 msvc charset/iso-8859-1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/18 msvc charset/iso-8859-1.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +int main(int argc, char *argcv[]) +{ + printf("This is ISO-8859-1 encoded é\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/18 msvc charset/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/18 msvc charset/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/18 msvc charset/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/18 msvc charset/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,15 @@ +project('charset', 'c') + +cc = meson.get_compiler('c') + +if cc.get_id() != 'msvc' + error('MESON_SKIP_TEST requires MSVC.') +endif + +executable('utf8', 'utf8.c') + +if get_option('test-failure') + executable('iso-8859-1', 'iso-8859-1.c') +else + executable('iso-8859-1', 'iso-8859-1.c', c_args: '/source-charset:.850') +endif diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/18 msvc charset/meson_options.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/18 msvc charset/meson_options.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/18 msvc charset/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/18 msvc charset/meson_options.txt" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1 @@ +option('test-failure', type: 'boolean', value: false) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/18 msvc charset/utf8.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/18 msvc charset/utf8.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/18 msvc charset/utf8.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/18 msvc charset/utf8.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +int main(int argc, char *argcv[]) +{ + printf("This is UTF-8 encoded é\n"); + return 0; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/both_lib_source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/both_lib_source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/both_lib_source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/both_lib_source.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,7 @@ +extern int static_lib_function(void); +extern __declspec(dllexport) int both_lib_function(void); + +int both_lib_function(void) +{ + return static_lib_function(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/copyfile.py" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/copyfile.py" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/copyfile.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/copyfile.py" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,4 @@ +from shutil import copyfile +import sys + +copyfile(sys.argv[1], sys.argv[2]) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/generated_source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/generated_source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/generated_source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/generated_source.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,4 @@ +int generated_function(void) +{ + return 42; +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/meson.build" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/meson.build" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/meson.build" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,20 @@ +project('test', 'c') + +generated_c = custom_target( + 'generated.c', + input : files('generated_source.c', 'copyfile.py'), + output : 'generated.c', + command : ['python', '@INPUT1@', '@INPUT0@', '@OUTPUT@'], +) + +static_lib = static_library( + 'static_lib', + [files('static_lib_source.c'), generated_c], +) + +both_lib = both_libraries( + 'both_lib', + [files('both_lib_source.c')], + link_with : [static_lib], + install : true, +) diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/static_lib_source.c" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/static_lib_source.c" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/static_lib_source.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/static_lib_source.c" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,6 @@ +extern int generated_function(void); + +int static_lib_function(void) +{ + return generated_function(); +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/19 vs install static lib with generated obj deps/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/19 vs install static lib with generated obj deps/test.json" 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,13 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/libboth_lib.a"}, + + {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/both_lib"}, + {"type": "implib", "platform": "msvc", "file": "usr/lib/both_lib"}, + {"type": "pdb", "platform": "msvc", "file": "usr/bin/both_lib"}, + + {"type": "expr", "platform": "gcc", "file": "usr/lib/?libboth_lib.dll"}, + {"type": "implib", "platform": "gcc", "file": "usr/lib/libboth_lib"}, + {"type": "pdb", "platform": "gcc", "file": "usr/bin/libboth_lib"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/1 basic/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/1 basic/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/1 basic/installed_files.txt" 2018-10-31 09:31:57.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/1 basic/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin/prog.exe -?msvc:usr/bin/prog.pdb diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/1 basic/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/1 basic/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/1 basic/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/1 basic/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "installed": [ + {"type": "file", "file": "usr/bin/prog.exe"}, + {"type": "pdb", "file": "usr/bin/prog"} + ] +} diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/6 vs module defs/subdir/somedll.def" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/6 vs module defs/subdir/somedll.def" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/6 vs module defs/subdir/somedll.def" 2016-04-04 20:24:22.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/6 vs module defs/subdir/somedll.def" 2021-11-02 19:58:07.000000000 +0000 @@ -1,3 +1,2 @@ EXPORTS somedllfunc - diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/7 dll versioning/installed_files.txt" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/7 dll versioning/installed_files.txt" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/7 dll versioning/installed_files.txt" 2019-12-04 18:45:50.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/7 dll versioning/installed_files.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -?msvc:usr/bin/some-0.dll -?msvc:usr/bin/some-0.pdb -?msvc:usr/lib/some.lib -?msvc:usr/bin/noversion.dll -?msvc:usr/bin/noversion.pdb -?msvc:usr/lib/noversion.lib -?msvc:usr/bin/onlyversion-1.dll -?msvc:usr/bin/onlyversion-1.pdb -?msvc:usr/lib/onlyversion.lib -?msvc:usr/bin/onlysoversion-5.dll -?msvc:usr/bin/onlysoversion-5.pdb -?msvc:usr/lib/onlysoversion.lib -?msvc:usr/libexec/customdir.dll -?msvc:usr/libexec/customdir.lib -?msvc:usr/libexec/customdir.pdb -?msvc:usr/lib/modules/module.dll -?msvc:usr/lib/modules/module.lib -?msvc:usr/lib/modules/module.pdb -?gcc:usr/bin/?libsome-0.dll -?gcc:usr/lib/libsome.dll.a -?gcc:usr/bin/?libnoversion.dll -?gcc:usr/lib/libnoversion.dll.a -?gcc:usr/bin/?libonlyversion-1.dll -?gcc:usr/lib/libonlyversion.dll.a -?gcc:usr/bin/?libonlysoversion-5.dll -?gcc:usr/lib/libonlysoversion.dll.a -?gcc:usr/libexec/?libcustomdir.dll -?gcc:usr/libexec/libcustomdir.dll.a -?gcc:usr/lib/modules/?libmodule.dll -?gcc:usr/lib/modules/libmodule.dll.a diff -Nru "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/7 dll versioning/test.json" "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/7 dll versioning/test.json" --- "/tmp/tmp8m2kkste/paEM1KDMJp/meson-0.53.2/test cases/windows/7 dll versioning/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp8m2kkste/X6c9W2ICyZ/meson-0.61.2/test cases/windows/7 dll versioning/test.json" 2020-08-15 16:27:05.000000000 +0000 @@ -0,0 +1,34 @@ +{ + "installed": [ + {"type": "file", "platform": "msvc", "file": "usr/bin/some-0.dll"}, + {"type": "pdb", "file": "usr/bin/some-0"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/some.lib"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/noversion.dll"}, + {"type": "pdb", "file": "usr/bin/noversion"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/noversion.lib"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/onlyversion-1.dll"}, + {"type": "pdb", "file": "usr/bin/onlyversion-1"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/onlyversion.lib"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/onlysoversion-5.dll"}, + {"type": "pdb", "file": "usr/bin/onlysoversion-5"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/onlysoversion.lib"}, + {"type": "file", "platform": "msvc", "file": "usr/libexec/customdir.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/libexec/customdir.lib"}, + {"type": "pdb", "file": "usr/libexec/customdir"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/modules/module.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/modules/module.lib"}, + {"type": "pdb", "file": "usr/lib/modules/module"}, + {"type": "expr", "platform": "gcc", "file": "usr/bin/?libsome-0.dll"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libsome.dll.a"}, + {"type": "expr", "platform": "gcc", "file": "usr/bin/?libnoversion.dll"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libnoversion.dll.a"}, + {"type": "expr", "platform": "gcc", "file": "usr/bin/?libonlyversion-1.dll"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libonlyversion.dll.a"}, + {"type": "expr", "platform": "gcc", "file": "usr/bin/?libonlysoversion-5.dll"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libonlysoversion.dll.a"}, + {"type": "expr", "platform": "gcc", "file": "usr/libexec/?libcustomdir.dll"}, + {"type": "file", "platform": "gcc", "file": "usr/libexec/libcustomdir.dll.a"}, + {"type": "expr", "platform": "gcc", "file": "usr/lib/modules/?libmodule.dll"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/modules/libmodule.dll.a"} + ] +} diff -Nru meson-0.53.2/tools/ac_converter.py meson-0.61.2/tools/ac_converter.py --- meson-0.53.2/tools/ac_converter.py 2019-12-29 22:47:27.000000000 +0000 +++ meson-0.61.2/tools/ac_converter.py 2021-07-20 08:56:20.000000000 +0000 @@ -371,7 +371,7 @@ print(help_message.format(sys.argv[0])) sys.exit(0) -with open(sys.argv[1]) as f: +with open(sys.argv[1], encoding='utf-8') as f: for line in f: line = line.strip() arr = line.split() @@ -414,7 +414,7 @@ print('check_headers = [') for token, hname in headers: - print(" ['{}', '{}'],".format(token, hname)) + print(f" ['{token}', '{hname}'],") print(']\n') print('''foreach h : check_headers @@ -430,7 +430,7 @@ for tok in functions: if len(tok) == 3: tokstr, fdata0, fdata1 = tok - print(" ['{}', '{}', '#include<{}>'],".format(tokstr, fdata0, fdata1)) + print(f" ['{tokstr}', '{fdata0}', '#include<{fdata1}>'],") else: print('# check token', tok) print(']\n') @@ -445,7 +445,7 @@ # Convert sizeof checks. for elem, typename in sizes: - print("cdata.set('{}', cc.sizeof('{}'))".format(elem, typename)) + print(f"cdata.set('{elem}', cc.sizeof('{typename}'))") print(''' configure_file(input : 'config.h.meson', diff -Nru meson-0.53.2/tools/boost_names.py meson-0.61.2/tools/boost_names.py --- meson-0.53.2/tools/boost_names.py 2019-12-04 18:45:50.000000000 +0000 +++ meson-0.61.2/tools/boost_names.py 2021-07-20 08:56:20.000000000 +0000 @@ -24,164 +24,277 @@ """ import sys -import os -import collections -import pprint import json import re +import textwrap +import functools +import typing as T +from pathlib import Path + +lib_dir = Path('libs') +jamroot = Path('Jamroot') + +not_modules = ['config', 'disjoint_sets', 'headers'] + +export_modules = False + + +@functools.total_ordering +class BoostLibrary(): + def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]): + self.name = name + self.shared = sorted(set(shared)) + self.static = sorted(set(static)) + self.single = sorted(set(single)) + self.multi = sorted(set(multi)) + + def __lt__(self, other: object) -> bool: + if isinstance(other, BoostLibrary): + return self.name < other.name + return NotImplemented + + def __eq__(self, other: object) -> bool: + if isinstance(other, BoostLibrary): + return self.name == other.name + elif isinstance(other, str): + return self.name == other + return NotImplemented + + def __hash__(self) -> int: + return hash(self.name) + +@functools.total_ordering +class BoostModule(): + def __init__(self, name: str, key: str, desc: str, libs: T.List[BoostLibrary]): + self.name = name + self.key = key + self.desc = desc + self.libs = libs + + def __lt__(self, other: object) -> bool: + if isinstance(other, BoostModule): + return self.key < other.key + return NotImplemented + + +def get_boost_version() -> T.Optional[str]: + raw = jamroot.read_text(encoding='utf-8') + m = re.search(r'BOOST_VERSION\s*:\s*([0-9\.]+)\s*;', raw) + if m: + return m.group(1) + return None + + +def get_libraries(jamfile: Path) -> T.List[BoostLibrary]: + # Extract libraries from the boost Jamfiles. This includes: + # - library name + # - compiler flags + + libs: T.List[BoostLibrary] = [] + raw = jamfile.read_text(encoding='utf-8') + raw = re.sub(r'#.*\n', '\n', raw) # Remove comments + raw = re.sub(r'\s+', ' ', raw) # Force single space + raw = re.sub(r'}', ';', raw) # Cheat code blocks by converting } to ; + + cmds = raw.split(';') # Commands always terminate with a ; (I hope) + cmds = [x.strip() for x in cmds] # Some cleanup + + project_usage_requirements: T.List[str] = [] + + # "Parse" the relevant sections + for i in cmds: + parts = i.split(' ') + parts = [x for x in parts if x not in ['']] + if not parts: + continue -Module = collections.namedtuple('Module', ['dirname', 'name', 'libnames']) -Module.__repr__ = lambda self: str((self.dirname, self.name, self.libnames)) # type: ignore + # Parse project + if parts[0] in ['project']: + attributes: T.Dict[str, T.List[str]] = {} + curr: T.Optional[str] = None + + for j in parts: + if j == ':': + curr = None + elif curr is None: + curr = j + else: + if curr not in attributes: + attributes[curr] = [] + attributes[curr] += [j] + + if 'usage-requirements' in attributes: + project_usage_requirements = attributes['usage-requirements'] + + # Parse libraries + elif parts[0] in ['lib', 'boost-lib']: + assert len(parts) >= 2 + + # Get and check the library name + lname = parts[1] + if parts[0] == 'boost-lib': + lname = f'boost_{lname}' + if not lname.startswith('boost_'): + continue + + # Count `:` to only select the 'usage-requirements' + # See https://boostorg.github.io/build/manual/master/index.html#bbv2.main-target-rule-syntax + colon_counter = 0 + usage_requirements: T.List[str] = [] + for j in parts: + if j == ':': + colon_counter += 1 + elif colon_counter >= 4: + usage_requirements += [j] + + # Get shared / static defines + shared: T.List[str] = [] + static: T.List[str] = [] + single: T.List[str] = [] + multi: T.List[str] = [] + for j in usage_requirements + project_usage_requirements: + m1 = re.match(r'shared:(.*)', j) + m2 = re.match(r'static:(.*)', j) + m3 = re.match(r'single:(.*)', j) + m4 = re.match(r'multi:(.*)', j) + + if m1: + shared += [f'-D{m1.group(1)}'] + if m2: + static += [f'-D{m2.group(1)}'] + if m3: + single +=[f'-D{m3.group(1)}'] + if m4: + multi += [f'-D{m4.group(1)}'] -LIBS = 'libs' + libs += [BoostLibrary(lname, shared, static, single, multi)] -manual_map = { - 'callable_traits': 'Call Traits', - 'crc': 'CRC', - 'dll': 'DLL', - 'gil': 'GIL', - 'graph_parallel': 'GraphParallel', - 'icl': 'ICL', - 'io': 'IO State Savers', - 'msm': 'Meta State Machine', - 'mpi': 'MPI', - 'mpl': 'MPL', - 'multi_array': 'Multi-Array', - 'multi_index': 'Multi-Index', - 'numeric': 'Numeric Conversion', - 'ptr_container': 'Pointer Container', - 'poly_collection': 'PolyCollection', - 'qvm': 'QVM', - 'throw_exception': 'ThrowException', - 'tti': 'TTI', - 'vmd': 'VMD', -} - -extra = [ - Module('utility', 'Compressed Pair', []), - Module('core', 'Enable If', []), - Module('functional', 'Functional/Factory', []), - Module('functional', 'Functional/Forward', []), - Module('functional', 'Functional/Hash', []), - Module('functional', 'Functional/Overloaded Function', []), - Module('utility', 'Identity Type', []), - Module('utility', 'In Place Factory, Typed In Place Factory', []), - Module('numeric', 'Interval', []), - Module('math', 'Math Common Factor', []), - Module('math', 'Math Octonion', []), - Module('math', 'Math Quaternion', []), - Module('math', 'Math/Special Functions', []), - Module('math', 'Math/Statistical Distributions', []), - Module('bind', 'Member Function', []), - Module('algorithm', 'Min-Max', []), - Module('numeric', 'Odeint', []), - Module('utility', 'Operators', []), - Module('core', 'Ref', []), - Module('utility', 'Result Of', []), - Module('algorithm', 'String Algo', []), - Module('core', 'Swap', []), - Module('', 'Tribool', []), - Module('numeric', 'uBLAS', []), - Module('utility', 'Value Initialized', []), -] - -# Cannot find the following modules in the documentation of boost -not_modules = ['beast', 'logic', 'mp11', 'winapi'] - -def eprint(message): - print(message, file=sys.stderr) - -def get_library_names(jamfile): - libs = [] - with open(jamfile) as jamfh: - jam = jamfh.read() - res = re.finditer(r'^lib[\s]+([A-Za-z0-9_]+)([^;]*);', jam, re.MULTILINE | re.DOTALL) - for matches in res: - if ':' in matches.group(2): - libs.append(matches.group(1)) - res = re.finditer(r'^boost-lib[\s]+([A-Za-z0-9_]+)([^;]*);', jam, re.MULTILINE | re.DOTALL) - for matches in res: - if ':' in matches.group(2): - libs.append('boost_{}'.format(matches.group(1))) return libs -def exists(modules, module): - return len([x for x in modules if x.dirname == module.dirname]) != 0 -def get_modules(init=extra): - modules = init - for directory in os.listdir(LIBS): - if not os.path.isdir(os.path.join(LIBS, directory)): - continue - if directory in not_modules: - continue - jamfile = os.path.join(LIBS, directory, 'build', 'Jamfile.v2') - if os.path.isfile(jamfile): - libs = get_library_names(jamfile) - else: - libs = [] - if directory in manual_map.keys(): - modname = manual_map[directory] - else: - modname = directory.replace('_', ' ').title() - modules.append(Module(directory, modname, libs)) +def process_lib_dir(ldir: Path) -> T.List[BoostModule]: + meta_file = ldir / 'meta' / 'libraries.json' + bjam_file = ldir / 'build' / 'Jamfile.v2' + if not meta_file.exists(): + print(f'WARNING: Meta file {meta_file} does not exist') + return [] + + # Extract libs + libs: T.List[BoostLibrary] = [] + if bjam_file.exists(): + libs = get_libraries(bjam_file) + + # Extract metadata + data = json.loads(meta_file.read_text(encoding='utf-8')) + if not isinstance(data, list): + data = [data] + + modules: T.List[BoostModule] = [] + for i in data: + modules += [BoostModule(i['name'], i['key'], i['description'], libs)] + return modules -def get_modules_2(): - modules = [] - # The python module uses an older build system format and is not easily parseable. - # We add the python module libraries manually. - modules.append(Module('python', 'Python', ['boost_python', 'boost_python3', 'boost_numpy', 'boost_numpy3'])) - for (root, _, files) in os.walk(LIBS): - for f in files: - if f == "libraries.json": - projectdir = os.path.dirname(root) - - jamfile = os.path.join(projectdir, 'build', 'Jamfile.v2') - if os.path.isfile(jamfile): - libs = get_library_names(jamfile) - else: - libs = [] - # Get metadata for module - jsonfile = os.path.join(root, f) - with open(jsonfile) as jsonfh: - boost_modules = json.loads(jsonfh.read()) - if(isinstance(boost_modules, dict)): - boost_modules = [boost_modules] - for boost_module in boost_modules: - modules.append(Module(boost_module['key'], boost_module['name'], libs)) - - # Some subprojects do not have meta directory with json file. Find those - jsonless_modules = [x for x in get_modules([]) if not exists(modules, x)] - for module in jsonless_modules: - eprint("WARNING: {} does not have meta/libraries.json. Will guess pretty name '{}'".format(module.dirname, module.name)) - modules.extend(jsonless_modules) +def get_modules() -> T.List[BoostModule]: + modules: T.List[BoostModule] = [] + for i in lib_dir.iterdir(): + if not i.is_dir() or i.name in not_modules: + continue + + # numeric has sub libs + subdirs = i / 'sublibs' + metadir = i / 'meta' + if subdirs.exists() and not metadir.exists(): + for j in i.iterdir(): + if not j.is_dir(): + continue + modules += process_lib_dir(j) + else: + modules += process_lib_dir(i) return modules -def main(args): - if not os.path.isdir(LIBS): - eprint("ERROR: script must be run in boost source directory") - - # It will pick jsonless algorithm if 1 is given as argument - impl = 0 - if len(args) > 1: - if args[1] == '1': - impl = 1 - - if impl == 1: - modules = get_modules() - else: - modules = get_modules_2() - - sorted_modules = sorted(modules, key=lambda module: module.name.lower()) - sorted_modules = [x[2] for x in sorted_modules if x[2]] - sorted_modules = sum(sorted_modules, []) - sorted_modules = [x for x in sorted_modules if x.startswith('boost')] - pp = pprint.PrettyPrinter() - pp.pprint(sorted_modules) +def main() -> int: + if not lib_dir.is_dir() or not jamroot.exists(): + print("ERROR: script must be run in boost source directory") + return 1 + + vers = get_boost_version() + modules = get_modules() + modules = sorted(modules) + libraries = [x for y in modules for x in y.libs] + libraries = sorted(set(libraries)) + + print(textwrap.dedent(f'''\ + #### ---- BEGIN GENERATED ---- #### + # # + # Generated with tools/boost_names.py: + # - boost version: {vers} + # - modules found: {len(modules)} + # - libraries found: {len(libraries)} + # + + class BoostLibrary(): + def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]): + self.name = name + self.shared = shared + self.static = static + self.single = single + self.multi = multi + + class BoostModule(): + def __init__(self, name: str, key: str, desc: str, libs: T.List[str]): + self.name = name + self.key = key + self.desc = desc + self.libs = libs + + + # dict of all know libraries with additional compile options + boost_libraries = {{\ + ''')) + + for i in libraries: + print(textwrap.indent(textwrap.dedent(f"""\ + '{i.name}': BoostLibrary( + name='{i.name}', + shared={i.shared}, + static={i.static}, + single={i.single}, + multi={i.multi}, + ),\ + """), ' ')) + + if export_modules: + print(textwrap.dedent(f'''\ + }} + + + # dict of all modules with metadata + boost_modules = {{\ + ''')) + + for mod in modules: + desc_excaped = re.sub(r"'", "\\'", mod.desc) + print(textwrap.indent(textwrap.dedent(f"""\ + '{mod.key}': BoostModule( + name='{mod.name}', + key='{mod.key}', + desc='{desc_excaped}', + libs={[x.name for x in mod.libs]}, + ),\ + """), ' ')) + + print(textwrap.dedent(f'''\ + }} + + # # + #### ---- END GENERATED ---- ####\ + ''')) + + return 0 if __name__ == '__main__': - main(sys.argv) + sys.exit(main()) diff -Nru meson-0.53.2/tools/build_website.py meson-0.61.2/tools/build_website.py --- meson-0.53.2/tools/build_website.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/tools/build_website.py 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import os, subprocess, shutil + +assert os.getcwd() == '/home/jpakkane' + +from glob import glob + +def purge(fname: str) -> None: + if not os.path.exists(fname): + return + if os.path.isdir(fname): + shutil.rmtree(fname) + os.unlink(fname) + +def update() -> None: + webdir = 'mesonweb' + repodir = 'mesonwebbuild' + docdir = os.path.join(repodir, 'docs') + builddir = os.path.join(docdir, 'builddir') + htmldir = os.path.join(builddir, 'Meson documentation-doc/html') +# subprocess.check_call(['git', 'pull'], cwd=webdir) + subprocess.check_call(['git', 'fetch', '-a'], cwd=repodir) + subprocess.check_call(['git', 'reset', '--hard', 'origin/master'], + cwd=repodir) + if os.path.isdir(htmldir): + shutil.rmtree(htmldir) + if os.path.isdir(builddir): + shutil.rmtree(builddir) + env = os.environ.copy() + env['PATH'] = env['PATH'] + ':/home/jpakkane/.local/bin' + subprocess.check_call(['../meson.py', '.', 'builddir'], cwd=docdir, env=env) + subprocess.check_call(['ninja'], cwd=builddir) + old_files = glob(os.path.join(webdir, '*')) + for f in old_files: + base = f[len(webdir)+1:] + if base == 'CNAME' or base == 'favicon.png': + continue + subprocess.check_call(['git', 'rm', '-rf', base], cwd=webdir) + assert os.path.isdir(webdir) + new_entries = glob(os.path.join(htmldir, '*')) + for e in new_entries: + shutil.move(e, webdir) + subprocess.check_call('git add *', shell=True, cwd=webdir) + subprocess.check_call(['git', 'commit', '-a', '-m', 'Bleep. Bloop. I am a bot.'], + cwd=webdir) + subprocess.check_call(['git', 'push'], cwd=webdir) + shutil.rmtree(builddir) + +if __name__ == '__main__': + update() diff -Nru meson-0.53.2/tools/cmake2meson.py meson-0.61.2/tools/cmake2meson.py --- meson-0.53.2/tools/cmake2meson.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/tools/cmake2meson.py 2021-07-20 08:56:20.000000000 +0000 @@ -34,7 +34,7 @@ self.args = args class Lexer: - def __init__(self): + def __init__(self) -> None: self.token_specification = [ # Need to be sorted longest to shortest. ('ignore', re.compile(r'[ \t]')), @@ -81,17 +81,17 @@ elif tid == 'varexp': yield(Token('varexp', match_text[2:-1])) else: - raise ValueError('lex: unknown element {}'.format(tid)) + raise ValueError(f'lex: unknown element {tid}') break if not matched: raise ValueError('Lexer got confused line %d column %d' % (lineno, col)) class Parser: - def __init__(self, code: str): + def __init__(self, code: str) -> None: self.stream = Lexer().lex(code) self.getsym() - def getsym(self): + def getsym(self) -> None: try: self.current = next(self.stream) except StopIteration: @@ -106,7 +106,7 @@ def expect(self, s: str) -> bool: if self.accept(s): return True - raise ValueError('Expecting %s got %s.' % (s, self.current.tid), self.current.lineno, self.current.colno) + raise ValueError(f'Expecting {s} got {self.current.tid}.', self.current.lineno, self.current.colno) def statement(self) -> Statement: cur = self.current @@ -118,8 +118,8 @@ self.expect('rparen') return Statement(cur.value, args) - def arguments(self) -> list: - args = [] + def arguments(self) -> T.List[T.Union[Token, T.Any]]: + args = [] # type: T.List[T.Union[Token, T.Any]] if self.accept('lparen'): args.append(self.arguments()) self.expect('rparen') @@ -139,6 +139,17 @@ while not self.accept('eof'): yield(self.statement()) +def token_or_group(arg: T.Union[Token, T.List[Token]]) -> str: + if isinstance(arg, Token): + return ' ' + arg.value + elif isinstance(arg, list): + line = ' (' + for a in arg: + line += ' ' + token_or_group(a) + line += ' )' + return line + raise RuntimeError('Conversion error in token_or_group') + class Converter: ignored_funcs = {'cmake_minimum_required': True, 'enable_testing': True, @@ -166,14 +177,14 @@ elif i.tid == 'string': res.append("'%s'" % i.value) else: - raise ValueError('Unknown arg type {}'.format(i.tid)) + raise ValueError(f'Unknown arg type {i.tid}') if len(res) > 1: return start + ', '.join(res) + end if len(res) == 1: return res[0] return '' - def write_entry(self, outfile: T.TextIO, t: Statement): + def write_entry(self, outfile: T.TextIO, t: Statement) -> None: if t.name in Converter.ignored_funcs: return preincrement = 0 @@ -186,15 +197,15 @@ varname = t.args[0].value.lower() mods = ["dependency('%s')" % i.value for i in t.args[1:]] if len(mods) == 1: - line = '%s = %s' % (varname, mods[0]) + line = '{} = {}'.format(varname, mods[0]) else: - line = '%s = [%s]' % (varname, ', '.join(["'%s'" % i for i in mods])) + line = '{} = [{}]'.format(varname, ', '.join(["'%s'" % i for i in mods])) elif t.name == 'find_package': - line = "%s_dep = dependency('%s')" % (t.args[0].value, t.args[0].value) + line = "{}_dep = dependency('{}')".format(t.args[0].value, t.args[0].value) elif t.name == 'find_library': - line = "%s = find_library('%s')" % (t.args[0].value.lower(), t.args[0].value) + line = "{} = find_library('{}')".format(t.args[0].value.lower(), t.args[0].value) elif t.name == 'add_executable': - line = '%s_exe = executable(%s)' % (t.args[0].value, self.convert_args(t.args, False)) + line = '{}_exe = executable({})'.format(t.args[0].value, self.convert_args(t.args, False)) elif t.name == 'add_library': if t.args[1].value == 'SHARED': libcmd = 'shared_library' @@ -205,7 +216,7 @@ else: libcmd = 'library' args = t.args - line = '%s_lib = %s(%s)' % (t.args[0].value, libcmd, self.convert_args(args, False)) + line = '{}_lib = {}({})'.format(t.args[0].value, libcmd, self.convert_args(args, False)) elif t.name == 'add_test': line = 'test(%s)' % self.convert_args(t.args, False) elif t.name == 'option': @@ -229,7 +240,7 @@ line = 'project(' + ', '.join(args) + ", default_options : ['default_library=static'])" elif t.name == 'set': varname = t.args[0].value.lower() - line = '%s = %s\n' % (varname, self.convert_args(t.args[1:])) + line = '{} = {}\n'.format(varname, self.convert_args(t.args[1:])) elif t.name == 'if': postincrement = 1 try: @@ -237,17 +248,16 @@ except AttributeError: # complex if statements line = t.name for arg in t.args: - if isinstance(arg, Token): - line += ' ' + arg.value - elif isinstance(arg, list): - line += ' (' - for a in arg: - line += ' ' + a.value - line += ' )' + line += token_or_group(arg) elif t.name == 'elseif': preincrement = -1 postincrement = 1 - line = 'elif %s' % self.convert_args(t.args, False) + try: + line = 'elif %s' % self.convert_args(t.args, False) + except AttributeError: # complex if statements + line = t.name + for arg in t.args: + line += token_or_group(arg) elif t.name == 'else': preincrement = -1 postincrement = 1 @@ -256,7 +266,7 @@ preincrement = -1 line = 'endif' else: - line = '''# %s(%s)''' % (t.name, self.convert_args(t.args)) + line = '''# {}({})'''.format(t.name, self.convert_args(t.args)) self.indent_level += preincrement indent = self.indent_level * self.indent_unit outfile.write(indent) @@ -265,18 +275,18 @@ outfile.write('\n') self.indent_level += postincrement - def convert(self, subdir: Path = None): + def convert(self, subdir: Path = None) -> None: if not subdir: subdir = self.cmake_root cfile = Path(subdir).expanduser() / 'CMakeLists.txt' try: - with cfile.open() as f: + with cfile.open(encoding='utf-8') as f: cmakecode = f.read() except FileNotFoundError: print('\nWarning: No CMakeLists.txt in', subdir, '\n', file=sys.stderr) return p = Parser(cmakecode) - with (subdir / 'meson.build').open('w') as outfile: + with (subdir / 'meson.build').open('w', encoding='utf-8') as outfile: for t in p.parse(): if t.name == 'add_subdirectory': # print('\nRecursing to subdir', @@ -288,9 +298,9 @@ if subdir == self.cmake_root and len(self.options) > 0: self.write_options() - def write_options(self): + def write_options(self) -> None: filename = self.cmake_root / 'meson_options.txt' - with filename.open('w') as optfile: + with filename.open('w', encoding='utf-8') as optfile: for o in self.options: (optname, description, default) = o if default is None: @@ -306,7 +316,7 @@ else: typestr = ' type : \'string\',' defaultstr = ' value : %s,' % default - line = "option(%r,%s%s description : '%s')\n" % (optname, + line = "option({!r},{}{} description : '{}')\n".format(optname, typestr, defaultstr, description) diff -Nru meson-0.53.2/tools/copy_files.py meson-0.61.2/tools/copy_files.py --- meson-0.53.2/tools/copy_files.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/tools/copy_files.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + + +# Copyright 2018 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. + +''' +Copy files +''' + +import argparse +import shutil +import typing as T +from pathlib import Path + +PathLike = T.Union[Path,str] + +def copy_files(files: T.List[str], input_dir: PathLike, output_dir: PathLike) -> None: + if not input_dir: + raise ValueError(f'Input directory value is not set') + if not output_dir: + raise ValueError(f'Output directory value is not set') + + input_dir = Path(input_dir).resolve() + output_dir = Path(output_dir).resolve() + output_dir.mkdir(parents=True, exist_ok=True) + + for f in files: + if (input_dir/f).is_dir(): + shutil.copytree(input_dir/f, output_dir/f) + else: + shutil.copy2(input_dir/f, output_dir/f) + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Copy files') + parser.add_argument('files', metavar='FILE', nargs='*') + parser.add_argument('-C', dest='input_dir', required=True) + parser.add_argument('--output-dir', required=True) + + args = parser.parse_args() + + copy_files(files=args.files, + input_dir=args.input_dir, + output_dir=args.output_dir) diff -Nru meson-0.53.2/tools/dircondenser.py meson-0.61.2/tools/dircondenser.py --- meson-0.53.2/tools/dircondenser.py 2020-01-23 12:51:19.000000000 +0000 +++ meson-0.61.2/tools/dircondenser.py 2022-01-02 20:12:32.000000000 +0000 @@ -48,20 +48,20 @@ try: numstr = int(number) except ValueError: - raise SystemExit('Dir name {} does not start with a number.'.format(e)) + raise SystemExit(f'Dir name {e} does not start with a number.') entries.append((numstr, rest)) entries.sort() return entries -def replace_source(sourcefile: str, replacements: T.List[T.Tuple[str, str]]): - with open(sourcefile, 'r') as f: +def replace_source(sourcefile: str, replacements: T.List[T.Tuple[str, str]]) -> None: + with open(sourcefile, encoding='utf-8') as f: contents = f.read() for old_name, new_name in replacements: contents = contents.replace(old_name, new_name) - with open(sourcefile, 'w') as f: + with open(sourcefile, 'w', encoding='utf-8') as f: f.write(contents) -def condense(dirname: str): +def condense(dirname: str) -> None: curdir = os.getcwd() os.chdir(dirname) entries = get_entries() @@ -74,9 +74,15 @@ #print('git mv "%s" "%s"' % (old_name, new_name)) subprocess.check_call(['git', 'mv', old_name, new_name]) replacements.append((old_name, new_name)) + # update any appearances of old_name in expected stdout in test.json + json = os.path.join(new_name, 'test.json') + if os.path.isfile(json): + replace_source(json, [(old_name, new_name)]) os.chdir(curdir) replace_source('run_unittests.py', replacements) replace_source('run_project_tests.py', replacements) + for f in glob('unittests/*.py'): + replace_source(f, replacements) if __name__ == '__main__': if len(sys.argv) != 1: diff -Nru meson-0.53.2/tools/gen_data.py meson-0.61.2/tools/gen_data.py --- meson-0.53.2/tools/gen_data.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/tools/gen_data.py 2022-01-17 10:50:45.000000000 +0000 @@ -0,0 +1,140 @@ +#!/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 -Nru meson-0.53.2/tools/regenerate_docs.py meson-0.61.2/tools/regenerate_docs.py --- meson-0.53.2/tools/regenerate_docs.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/tools/regenerate_docs.py 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 + + +# Copyright 2018 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. + +''' +Regenerate markdown docs by using `meson.py` from the root dir +''' + +import argparse +import os +import re +import subprocess +import sys +import textwrap +import json +import typing as T +from pathlib import Path +from urllib.request import urlopen + +PathLike = T.Union[Path,str] + +def _get_meson_output(root_dir: Path, args: T.List) -> str: + env = os.environ.copy() + env['COLUMNS'] = '80' + return subprocess.run([str(sys.executable), str(root_dir/'meson.py')] + args, check=True, capture_output=True, text=True, env=env).stdout.strip() + +def get_commands_data(root_dir: Path) -> T.Dict[str, T.Any]: + usage_start_pattern = re.compile(r'^usage: ', re.MULTILINE) + positional_start_pattern = re.compile(r'^positional arguments:[\t ]*[\r\n]+', re.MULTILINE) + options_start_pattern = re.compile(r'^optional arguments:[\t ]*[\r\n]+', re.MULTILINE) + commands_start_pattern = re.compile(r'^[A-Za-z ]*[Cc]ommands:[\t ]*[\r\n]+', re.MULTILINE) + + def get_next_start(iterators: T.Sequence[T.Any], end: T.Optional[int]) -> int: + return next((i.start() for i in iterators if i), end) + + def normalize_text(text: str) -> str: + # clean up formatting + out = text + out = re.sub(r'\r\n', r'\r', out, flags=re.MULTILINE) # replace newlines with a linux EOL + out = re.sub(r'^ +$', '', out, flags=re.MULTILINE) # remove trailing whitespace + out = re.sub(r'(?:^\n+|\n+$)', '', out) # remove trailing empty lines + return out + + def parse_cmd(cmd: str) -> T.Dict[str, str]: + cmd_len = len(cmd) + usage = usage_start_pattern.search(cmd) + positionals = positional_start_pattern.search(cmd) + options = options_start_pattern.search(cmd) + commands = commands_start_pattern.search(cmd) + + arguments_start = get_next_start([positionals, options, commands], None) + assert arguments_start + + # replace `usage:` with `$` and dedent + dedent_size = (usage.end() - usage.start()) - len('$ ') + usage_text = textwrap.dedent(f'{dedent_size * " "}$ {normalize_text(cmd[usage.end():arguments_start])}') + + return { + 'usage': usage_text, + 'arguments': normalize_text(cmd[arguments_start:cmd_len]), + } + + def clean_dir_arguments(text: str) -> str: + # Remove platform specific defaults + args = [ + 'prefix', + 'bindir', + 'datadir', + 'includedir', + 'infodir', + 'libdir', + 'libexecdir', + 'localedir', + 'localstatedir', + 'mandir', + 'sbindir', + 'sharedstatedir', + 'sysconfdir' + ] + out = text + for a in args: + out = re.sub(r'(--' + a + r' .+?)\s+\(default:.+?\)(\.)?', r'\1\2', out, flags=re.MULTILINE|re.DOTALL) + return out + + output = _get_meson_output(root_dir, ['--help']) + commands = {c.strip() for c in re.findall(r'usage:(?:.+)?{((?:[a-z]+,*)+?)}', output, re.MULTILINE|re.DOTALL)[0].split(',')} + commands.remove('help') + + cmd_data = dict() + + for cmd in commands: + cmd_output = _get_meson_output(root_dir, [cmd, '--help']) + cmd_data[cmd] = parse_cmd(cmd_output) + if cmd in ['setup', 'configure']: + cmd_data[cmd]['arguments'] = clean_dir_arguments(cmd_data[cmd]['arguments']) + + return cmd_data + +def generate_hotdoc_includes(root_dir: Path, output_dir: Path) -> None: + cmd_data = get_commands_data(root_dir) + + for cmd, parsed in cmd_data.items(): + for typ in parsed.keys(): + with open(output_dir / (cmd+'_'+typ+'.inc'), 'w', encoding='utf-8') as f: + f.write(parsed[typ]) + +def generate_wrapdb_table(output_dir: Path) -> None: + url = urlopen('https://wrapdb.mesonbuild.com/v2/releases.json') + releases = json.loads(url.read().decode()) + with open(output_dir / 'wrapdb-table.md', 'w', encoding='utf-8') as f: + f.write('| Project | Versions | Provided dependencies | Provided programs |\n') + f.write('| ------- | -------- | --------------------- | ----------------- |\n') + for name, info in releases.items(): + versions = [f'[{v}](https://wrapdb.mesonbuild.com/v2/{name}_{v}/{name}.wrap)' for v in info['versions']] + # Highlight latest version. + versions_str = f'**{versions[0]}**
' + ', '.join(versions[1:]) + dependency_names = info.get('dependency_names', []) + dependency_names_str = ', '.join(dependency_names) + program_names = info.get('program_names', []) + program_names_str = ', '.join(program_names) + f.write(f'| {name} | {versions_str} | {dependency_names_str} | {program_names_str} |\n') + +def regenerate_docs(output_dir: PathLike, + dummy_output_file: T.Optional[PathLike]) -> None: + if not output_dir: + raise ValueError(f'Output directory value is not set') + + output_dir = Path(output_dir).resolve() + output_dir.mkdir(parents=True, exist_ok=True) + + root_dir = Path(__file__).resolve().parent.parent + + generate_hotdoc_includes(root_dir, output_dir) + generate_wrapdb_table(output_dir) + + if dummy_output_file: + with open(output_dir/dummy_output_file, 'w', encoding='utf-8') as f: + f.write('dummy file for custom_target output') + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Generate meson docs') + parser.add_argument('--output-dir', required=True) + parser.add_argument('--dummy-output-file', type=str) + + args = parser.parse_args() + + regenerate_docs(output_dir=args.output_dir, + dummy_output_file=args.dummy_output_file) diff -Nru meson-0.53.2/tools/run_with_cov.py meson-0.61.2/tools/run_with_cov.py --- meson-0.53.2/tools/run_with_cov.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/tools/run_with_cov.py 2021-08-18 11:22:15.000000000 +0000 @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# Copyright 2021 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 subprocess +import coverage +import os +import sys +from pathlib import Path + +root_path = Path(__file__).parent.parent.absolute() + +# Python magic so we can import mesonlib +sys.path.append(root_path.as_posix()) +from mesonbuild import mesonlib + +def generate_coveragerc() -> Path: + i_file = (root_path / 'data' / '.coveragerc.in') + o_file = (root_path / '.coveragerc') + raw = i_file.read_text(encoding='utf-8') + raw = raw.replace('@ROOT@', root_path.as_posix()) + o_file.write_text(raw, encoding='utf-8') + return o_file + +def main() -> int: + # Remove old run data + out_dir = root_path / '.coverage' + mesonlib.windows_proof_rmtree(out_dir.as_posix()) + out_dir.mkdir(parents=True, exist_ok=True) + + # Setup coverage + python_path = (root_path / 'ci').as_posix() + os.environ['PYTHONPATH'] = os.pathsep.join([python_path, os.environ.get('PYTHONPATH', '')]) + os.environ['COVERAGE_PROCESS_START'] = generate_coveragerc().as_posix() + coverage.process_startup() + + # Run the actual command + cmd = mesonlib.python_command + sys.argv[1:] + return subprocess.run(cmd, env=os.environ.copy()).returncode + +if __name__ == '__main__': + raise SystemExit(main()) diff -Nru meson-0.53.2/unittests/allplatformstests.py meson-0.61.2/unittests/allplatformstests.py --- meson-0.53.2/unittests/allplatformstests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/allplatformstests.py 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,4167 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from mesonbuild.mesonlib.universal import windows_proof_rm +import subprocess +import re +import json +import tempfile +import textwrap +import os +import shutil +import platform +import pickle +import zipfile, tarfile +import sys +from unittest import mock, SkipTest, skipIf, skipUnless +from contextlib import contextmanager +from glob import glob +from pathlib import (PurePath, Path) +import typing as T + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + BuildDirLock, MachineChoice, is_windows, is_osx, is_cygwin, is_dragonflybsd, + is_sunos, windows_proof_rmtree, python_command, version_compare, split_args, quote_arg, + relpath, is_linux, git, search_version, do_conf_file, do_conf_str, default_prefix, + MesonException, EnvironmentException, OptionKey +) + +from mesonbuild.compilers import ( + GnuCompiler, ClangCompiler, IntelGnuLikeCompiler, VisualStudioCCompiler, + VisualStudioCPPCompiler, ClangClCCompiler, ClangClCPPCompiler, + detect_static_linker, detect_c_compiler, compiler_from_language, + detect_compiler_for +) + +from mesonbuild.dependencies import PkgConfigDependency +from mesonbuild.build import Target, ConfigurationData, Executable, SharedLibrary, StaticLibrary +import mesonbuild.modules.pkgconfig +from mesonbuild.scripts import destdir_join + +from mesonbuild.wrap.wrap import PackageDefinition, WrapException + +from run_tests import ( + Backend, exe_suffix, get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@contextmanager +def temp_filename(): + '''A context manager which provides a filename to an empty temporary file. + + On exit the file will be deleted. + ''' + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + yield filename + finally: + try: + os.remove(filename) + except OSError: + pass + +def _git_init(project_dir): + # If a user has git configuration init.defaultBranch set we want to override that + with tempfile.TemporaryDirectory() as d: + out = git(['--version'], str(d))[1] + if version_compare(search_version(out), '>= 2.28'): + extra_cmd = ['--initial-branch', 'master'] + else: + extra_cmd = [] + + subprocess.check_call(['git', 'init'] + extra_cmd, cwd=project_dir, stdout=subprocess.DEVNULL) + subprocess.check_call(['git', 'config', + 'user.name', 'Author Person'], cwd=project_dir) + subprocess.check_call(['git', 'config', + 'user.email', 'teh_coderz@example.com'], cwd=project_dir) + _git_add_all(project_dir) + +def _git_add_all(project_dir): + subprocess.check_call('git add *', cwd=project_dir, shell=True, + stdout=subprocess.DEVNULL) + subprocess.check_call(['git', 'commit', '--no-gpg-sign', '-a', '-m', 'I am a project'], cwd=project_dir, + stdout=subprocess.DEVNULL) + +class AllPlatformTests(BasePlatformTests): + ''' + Tests that should run on all platforms + ''' + + def test_default_options_prefix(self): + ''' + Tests that setting a prefix in default_options in project() works. + Can't be an ordinary test because we pass --prefix to meson there. + https://github.com/mesonbuild/meson/issues/1349 + ''' + testdir = os.path.join(self.common_test_dir, '87 default options') + self.init(testdir, default_args=False, inprocess=True) + opts = self.introspect('--buildoptions') + for opt in opts: + if opt['name'] == 'prefix': + prefix = opt['value'] + break + else: + raise self.fail('Did not find option "prefix"') + self.assertEqual(prefix, '/absoluteprefix') + + def test_do_conf_file_preserve_newlines(self): + + def conf_file(in_data, confdata): + with temp_filename() as fin: + with open(fin, 'wb') as fobj: + fobj.write(in_data.encode('utf-8')) + with temp_filename() as fout: + do_conf_file(fin, fout, confdata, 'meson') + with open(fout, 'rb') as fobj: + return fobj.read().decode('utf-8') + + confdata = {'VAR': ('foo', 'bar')} + self.assertEqual(conf_file('@VAR@\n@VAR@\n', confdata), 'foo\nfoo\n') + self.assertEqual(conf_file('@VAR@\r\n@VAR@\r\n', confdata), 'foo\r\nfoo\r\n') + + def test_do_conf_file_by_format(self): + def conf_str(in_data, confdata, vformat): + (result, missing_variables, confdata_useless) = do_conf_str('configuration_file', in_data, confdata, variable_format = vformat) + return '\n'.join(result) + + def check_formats(confdata, result): + self.assertEqual(conf_str(['#mesondefine VAR'], confdata, 'meson'), result) + self.assertEqual(conf_str(['#cmakedefine VAR ${VAR}'], confdata, 'cmake'), result) + self.assertEqual(conf_str(['#cmakedefine VAR @VAR@'], confdata, 'cmake@'), result) + + confdata = ConfigurationData() + # Key error as they do not exists + check_formats(confdata, '/* #undef VAR */\n') + + # Check boolean + confdata.values = {'VAR': (False, 'description')} + check_formats(confdata, '#undef VAR\n') + confdata.values = {'VAR': (True, 'description')} + check_formats(confdata, '#define VAR\n') + + # Check string + confdata.values = {'VAR': ('value', 'description')} + check_formats(confdata, '#define VAR value\n') + + # Check integer + confdata.values = {'VAR': (10, 'description')} + check_formats(confdata, '#define VAR 10\n') + + # Check multiple string with cmake formats + confdata.values = {'VAR': ('value', 'description')} + self.assertEqual(conf_str(['#cmakedefine VAR xxx @VAR@ yyy @VAR@'], confdata, 'cmake@'), '#define VAR xxx value yyy value\n') + self.assertEqual(conf_str(['#define VAR xxx @VAR@ yyy @VAR@'], confdata, 'cmake@'), '#define VAR xxx value yyy value') + self.assertEqual(conf_str(['#cmakedefine VAR xxx ${VAR} yyy ${VAR}'], confdata, 'cmake'), '#define VAR xxx value yyy value\n') + self.assertEqual(conf_str(['#define VAR xxx ${VAR} yyy ${VAR}'], confdata, 'cmake'), '#define VAR xxx value yyy value') + + # Handles meson format exceptions + # Unknown format + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR xxx'], confdata, 'unknown_format') + # More than 2 params in mesondefine + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR xxx'], confdata, 'meson') + # Mismatched line with format + self.assertRaises(MesonException, conf_str, ['#cmakedefine VAR'], confdata, 'meson') + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR'], confdata, 'cmake') + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR'], confdata, 'cmake@') + # Dict value in confdata + confdata.values = {'VAR': (['value'], 'description')} + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR'], confdata, 'meson') + + def test_absolute_prefix_libdir(self): + ''' + Tests that setting absolute paths for --prefix and --libdir work. Can't + be an ordinary test because these are set via the command-line. + https://github.com/mesonbuild/meson/issues/1341 + https://github.com/mesonbuild/meson/issues/1345 + ''' + testdir = os.path.join(self.common_test_dir, '87 default options') + # on Windows, /someabs is *not* an absolute path + prefix = 'x:/someabs' if is_windows() else '/someabs' + libdir = 'libdir' + extra_args = ['--prefix=' + prefix, + # This can just be a relative path, but we want to test + # that passing this as an absolute path also works + '--libdir=' + prefix + '/' + libdir] + self.init(testdir, extra_args=extra_args, default_args=False) + opts = self.introspect('--buildoptions') + for opt in opts: + if opt['name'] == 'prefix': + self.assertEqual(prefix, opt['value']) + elif opt['name'] == 'libdir': + self.assertEqual(libdir, opt['value']) + + def test_libdir_must_be_inside_prefix(self): + ''' + Tests that libdir is forced to be inside prefix no matter how it is set. + Must be a unit test for obvious reasons. + ''' + testdir = os.path.join(self.common_test_dir, '1 trivial') + # libdir being inside prefix is ok + if is_windows(): + args = ['--prefix', 'x:/opt', '--libdir', 'x:/opt/lib32'] + else: + args = ['--prefix', '/opt', '--libdir', '/opt/lib32'] + self.init(testdir, extra_args=args) + self.wipe() + # libdir not being inside prefix is not ok + if is_windows(): + args = ['--prefix', 'x:/usr', '--libdir', 'x:/opt/lib32'] + else: + args = ['--prefix', '/usr', '--libdir', '/opt/lib32'] + self.assertRaises(subprocess.CalledProcessError, self.init, testdir, extra_args=args) + self.wipe() + # libdir must be inside prefix even when set via mesonconf + self.init(testdir) + if is_windows(): + self.assertRaises(subprocess.CalledProcessError, self.setconf, '-Dlibdir=x:/opt', False) + else: + self.assertRaises(subprocess.CalledProcessError, self.setconf, '-Dlibdir=/opt', False) + + def test_prefix_dependent_defaults(self): + ''' + Tests that configured directory paths are set to prefix dependent + defaults. + ''' + testdir = os.path.join(self.common_test_dir, '1 trivial') + expected = { + '/opt': {'prefix': '/opt', + 'bindir': 'bin', 'datadir': 'share', 'includedir': 'include', + 'infodir': 'share/info', + 'libexecdir': 'libexec', 'localedir': 'share/locale', + 'localstatedir': 'var', 'mandir': 'share/man', + 'sbindir': 'sbin', 'sharedstatedir': 'com', + 'sysconfdir': 'etc'}, + '/usr': {'prefix': '/usr', + 'bindir': 'bin', 'datadir': 'share', 'includedir': 'include', + 'infodir': 'share/info', + 'libexecdir': 'libexec', 'localedir': 'share/locale', + 'localstatedir': '/var', 'mandir': 'share/man', + 'sbindir': 'sbin', 'sharedstatedir': '/var/lib', + 'sysconfdir': '/etc'}, + '/usr/local': {'prefix': '/usr/local', + 'bindir': 'bin', 'datadir': 'share', + 'includedir': 'include', 'infodir': 'share/info', + 'libexecdir': 'libexec', + 'localedir': 'share/locale', + 'localstatedir': '/var/local', 'mandir': 'share/man', + 'sbindir': 'sbin', 'sharedstatedir': '/var/local/lib', + 'sysconfdir': 'etc'}, + # N.B. We don't check 'libdir' as it's platform dependent, see + # default_libdir(): + } + + if default_prefix() == '/usr/local': + expected[None] = expected['/usr/local'] + + for prefix in expected: + args = [] + if prefix: + args += ['--prefix', prefix] + self.init(testdir, extra_args=args, default_args=False) + opts = self.introspect('--buildoptions') + for opt in opts: + name = opt['name'] + value = opt['value'] + if name in expected[prefix]: + self.assertEqual(value, expected[prefix][name]) + self.wipe() + + def test_default_options_prefix_dependent_defaults(self): + ''' + Tests that setting a prefix in default_options in project() sets prefix + dependent defaults for other options, and that those defaults can + be overridden in default_options or by the command line. + ''' + testdir = os.path.join(self.common_test_dir, '163 default options prefix dependent defaults') + expected = { + '': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/sharedstate'}, + '--prefix=/usr': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/sharedstate'}, + '--sharedstatedir=/var/state': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/var/state'}, + '--sharedstatedir=/var/state --prefix=/usr --sysconfdir=sysconf': + {'prefix': '/usr', + 'sysconfdir': 'sysconf', + 'localstatedir': '/var', + 'sharedstatedir': '/var/state'}, + } + for args in expected: + self.init(testdir, extra_args=args.split(), default_args=False) + opts = self.introspect('--buildoptions') + for opt in opts: + name = opt['name'] + value = opt['value'] + if name in expected[args]: + self.assertEqual(value, expected[args][name]) + self.wipe() + + def test_clike_get_library_dirs(self): + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + for d in cc.get_library_dirs(env): + self.assertTrue(os.path.exists(d)) + self.assertTrue(os.path.isdir(d)) + self.assertTrue(os.path.isabs(d)) + + def test_static_library_overwrite(self): + ''' + Tests that static libraries are never appended to, always overwritten. + Has to be a unit test because this involves building a project, + reconfiguring, and building it again so that `ar` is run twice on the + same static library. + https://github.com/mesonbuild/meson/issues/1355 + ''' + testdir = os.path.join(self.common_test_dir, '3 static') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + static_linker = detect_static_linker(env, cc) + if is_windows(): + raise SkipTest('https://github.com/mesonbuild/meson/issues/1526') + if not isinstance(static_linker, mesonbuild.linkers.ArLinker): + raise SkipTest('static linker is not `ar`') + # Configure + self.init(testdir) + # Get name of static library + targets = self.introspect('--targets') + self.assertEqual(len(targets), 1) + libname = targets[0]['filename'][0] + # Build and get contents of static library + self.build() + before = self._run(['ar', 't', os.path.join(self.builddir, libname)]).split() + # Filter out non-object-file contents + before = [f for f in before if f.endswith(('.o', '.obj'))] + # Static library should contain only one object + self.assertEqual(len(before), 1, msg=before) + # Change the source to be built into the static library + self.setconf('-Dsource=libfile2.c') + self.build() + after = self._run(['ar', 't', os.path.join(self.builddir, libname)]).split() + # Filter out non-object-file contents + after = [f for f in after if f.endswith(('.o', '.obj'))] + # Static library should contain only one object + self.assertEqual(len(after), 1, msg=after) + # and the object must have changed + self.assertNotEqual(before, after) + + def test_static_compile_order(self): + ''' + Test that the order of files in a compiler command-line while compiling + and linking statically is deterministic. This can't be an ordinary test + case because we need to inspect the compiler database. + https://github.com/mesonbuild/meson/pull/951 + ''' + testdir = os.path.join(self.common_test_dir, '5 linkstatic') + self.init(testdir) + compdb = self.get_compdb() + # Rules will get written out in this order + self.assertTrue(compdb[0]['file'].endswith("libfile.c")) + self.assertTrue(compdb[1]['file'].endswith("libfile2.c")) + self.assertTrue(compdb[2]['file'].endswith("libfile3.c")) + self.assertTrue(compdb[3]['file'].endswith("libfile4.c")) + # FIXME: We don't have access to the linker command + + def test_run_target_files_path(self): + ''' + Test that run_targets are run from the correct directory + https://github.com/mesonbuild/meson/issues/957 + ''' + testdir = os.path.join(self.common_test_dir, '51 run target') + self.init(testdir) + self.run_target('check_exists') + self.run_target('check-env') + self.run_target('check-env-ct') + + def test_run_target_subdir(self): + ''' + Test that run_targets are run from the correct directory + https://github.com/mesonbuild/meson/issues/957 + ''' + testdir = os.path.join(self.common_test_dir, '51 run target') + self.init(testdir) + self.run_target('textprinter') + + def test_install_introspection(self): + ''' + Tests that the Meson introspection API exposes install filenames correctly + https://github.com/mesonbuild/meson/issues/829 + ''' + if self.backend is not Backend.ninja: + raise SkipTest(f'{self.backend.name!r} backend can\'t install files') + testdir = os.path.join(self.common_test_dir, '8 install') + self.init(testdir) + intro = self.introspect('--targets') + if intro[0]['type'] == 'executable': + intro = intro[::-1] + self.assertPathListEqual(intro[0]['install_filename'], ['/usr/lib/libstat.a']) + self.assertPathListEqual(intro[1]['install_filename'], ['/usr/bin/prog' + exe_suffix]) + + def test_install_subdir_introspection(self): + ''' + Test that the Meson introspection API also contains subdir install information + https://github.com/mesonbuild/meson/issues/5556 + ''' + testdir = os.path.join(self.common_test_dir, '59 install subdir') + self.init(testdir) + intro = self.introspect('--installed') + expected = { + 'sub2': 'share/sub2', + 'subdir/sub1': 'share/sub1', + 'subdir/sub_elided': 'share', + 'sub1': 'share/sub1', + 'sub/sub1': 'share/sub1', + 'sub_elided': 'share', + 'nested_elided/sub': 'share', + 'new_directory': 'share/new_directory', + } + + self.assertEqual(len(intro), len(expected)) + + # Convert expected to PurePath + expected_converted = {PurePath(os.path.join(testdir, key)): PurePath(os.path.join(self.prefix, val)) for key, val in expected.items()} + intro_converted = {PurePath(key): PurePath(val) for key, val in intro.items()} + + for src, dst in expected_converted.items(): + self.assertIn(src, intro_converted) + self.assertEqual(dst, intro_converted[src]) + + def test_install_introspection_multiple_outputs(self): + ''' + Tests that the Meson introspection API exposes multiple install filenames correctly without crashing + https://github.com/mesonbuild/meson/pull/4555 + + Reverted to the first file only because of https://github.com/mesonbuild/meson/pull/4547#discussion_r244173438 + TODO Change the format to a list officially in a followup PR + ''' + if self.backend is not Backend.ninja: + raise SkipTest(f'{self.backend.name!r} backend can\'t install files') + testdir = os.path.join(self.common_test_dir, '140 custom target multiple outputs') + self.init(testdir) + intro = self.introspect('--targets') + if intro[0]['type'] == 'executable': + intro = intro[::-1] + self.assertPathListEqual(intro[0]['install_filename'], ['/usr/include/diff.h', '/usr/bin/diff.sh']) + self.assertPathListEqual(intro[1]['install_filename'], ['/opt/same.h', '/opt/same.sh']) + self.assertPathListEqual(intro[2]['install_filename'], ['/usr/include/first.h', None]) + self.assertPathListEqual(intro[3]['install_filename'], [None, '/usr/bin/second.sh']) + + def read_install_logs(self): + # Find logged files and directories + with Path(self.builddir, 'meson-logs', 'install-log.txt').open(encoding='utf-8') as f: + return list(map(lambda l: Path(l.strip()), + filter(lambda l: not l.startswith('#'), + f.readlines()))) + + def test_install_log_content(self): + ''' + Tests that the install-log.txt is consistent with the installed files and directories. + Specifically checks that the log file only contains one entry per file/directory. + https://github.com/mesonbuild/meson/issues/4499 + ''' + testdir = os.path.join(self.common_test_dir, '59 install subdir') + self.init(testdir) + self.install() + installpath = Path(self.installdir) + # Find installed files and directories + expected = {installpath: 0} + for name in installpath.rglob('*'): + expected[name] = 0 + logged = self.read_install_logs() + for name in logged: + self.assertTrue(name in expected, f'Log contains extra entry {name}') + expected[name] += 1 + + for name, count in expected.items(): + self.assertGreater(count, 0, f'Log is missing entry for {name}') + self.assertLess(count, 2, f'Log has multiple entries for {name}') + + # Verify that with --dry-run we obtain the same logs but with nothing + # actually installed + windows_proof_rmtree(self.installdir) + self._run(self.meson_command + ['install', '--dry-run', '--destdir', self.installdir], workdir=self.builddir) + self.assertEqual(logged, self.read_install_logs()) + self.assertFalse(os.path.exists(self.installdir)) + + # If destdir is relative to build directory it should install + # exactly the same files. + rel_installpath = os.path.relpath(self.installdir, self.builddir) + self._run(self.meson_command + ['install', '--dry-run', '--destdir', rel_installpath, '-C', self.builddir]) + self.assertEqual(logged, self.read_install_logs()) + + def test_uninstall(self): + exename = os.path.join(self.installdir, 'usr/bin/prog' + exe_suffix) + dirname = os.path.join(self.installdir, 'usr/share/dir') + testdir = os.path.join(self.common_test_dir, '8 install') + self.init(testdir) + self.assertPathDoesNotExist(exename) + self.install() + self.assertPathExists(exename) + self.uninstall() + self.assertPathDoesNotExist(exename) + self.assertPathDoesNotExist(dirname) + + def test_forcefallback(self): + testdir = os.path.join(self.unit_test_dir, '31 forcefallback') + self.init(testdir, extra_args=['--wrap-mode=forcefallback']) + self.build() + self.run_tests() + + def test_implicit_forcefallback(self): + testdir = os.path.join(self.unit_test_dir, '96 implicit force fallback') + with self.assertRaises(subprocess.CalledProcessError): + self.init(testdir) + self.init(testdir, extra_args=['--wrap-mode=forcefallback']) + self.new_builddir() + self.init(testdir, extra_args=['--force-fallback-for=something']) + + def test_nopromote(self): + testdir = os.path.join(self.common_test_dir, '98 subproject subdir') + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir, extra_args=['--wrap-mode=nopromote']) + self.assertIn('dependency subsub found: NO', cm.exception.stdout) + + def test_force_fallback_for(self): + testdir = os.path.join(self.unit_test_dir, '31 forcefallback') + self.init(testdir, extra_args=['--force-fallback-for=zlib,foo']) + self.build() + self.run_tests() + + def test_force_fallback_for_nofallback(self): + testdir = os.path.join(self.unit_test_dir, '31 forcefallback') + self.init(testdir, extra_args=['--force-fallback-for=zlib,foo', '--wrap-mode=nofallback']) + self.build() + self.run_tests() + + def test_testrepeat(self): + testdir = os.path.join(self.common_test_dir, '206 tap tests') + self.init(testdir) + self.build() + self._run(self.mtest_command + ['--repeat=2']) + + def test_testsetups(self): + if not shutil.which('valgrind'): + raise SkipTest('Valgrind not installed.') + testdir = os.path.join(self.unit_test_dir, '2 testsetups') + self.init(testdir) + self.build() + # Run tests without setup + self.run_tests() + with open(os.path.join(self.logdir, 'testlog.txt'), encoding='utf-8') as f: + basic_log = f.read() + # Run buggy test with setup that has env that will make it fail + self.assertRaises(subprocess.CalledProcessError, + self._run, self.mtest_command + ['--setup=valgrind']) + with open(os.path.join(self.logdir, 'testlog-valgrind.txt'), encoding='utf-8') as f: + vg_log = f.read() + self.assertNotIn('TEST_ENV is set', basic_log) + self.assertNotIn('Memcheck', basic_log) + self.assertIn('TEST_ENV is set', vg_log) + self.assertIn('Memcheck', vg_log) + # Run buggy test with setup without env that will pass + self._run(self.mtest_command + ['--setup=wrapper']) + # Setup with no properties works + self._run(self.mtest_command + ['--setup=empty']) + # Setup with only env works + self._run(self.mtest_command + ['--setup=onlyenv']) + self._run(self.mtest_command + ['--setup=onlyenv2']) + self._run(self.mtest_command + ['--setup=onlyenv3']) + # Setup with only a timeout works + self._run(self.mtest_command + ['--setup=timeout']) + # Setup that does not define a wrapper works with --wrapper + self._run(self.mtest_command + ['--setup=timeout', '--wrapper', shutil.which('valgrind')]) + # Setup that skips test works + self._run(self.mtest_command + ['--setup=good']) + with open(os.path.join(self.logdir, 'testlog-good.txt'), encoding='utf-8') as f: + exclude_suites_log = f.read() + self.assertNotIn('buggy', exclude_suites_log) + # --suite overrides add_test_setup(xclude_suites) + self._run(self.mtest_command + ['--setup=good', '--suite', 'buggy']) + with open(os.path.join(self.logdir, 'testlog-good.txt'), encoding='utf-8') as f: + include_suites_log = f.read() + self.assertIn('buggy', include_suites_log) + + def test_testsetup_selection(self): + testdir = os.path.join(self.unit_test_dir, '14 testsetup selection') + self.init(testdir) + self.build() + + # Run tests without setup + self.run_tests() + + self.assertRaises(subprocess.CalledProcessError, self._run, self.mtest_command + ['--setup=missingfromfoo']) + self._run(self.mtest_command + ['--setup=missingfromfoo', '--no-suite=foo:']) + + self._run(self.mtest_command + ['--setup=worksforall']) + self._run(self.mtest_command + ['--setup=main:worksforall']) + + self.assertRaises(subprocess.CalledProcessError, self._run, + self.mtest_command + ['--setup=onlyinbar']) + self.assertRaises(subprocess.CalledProcessError, self._run, + self.mtest_command + ['--setup=onlyinbar', '--no-suite=main:']) + self._run(self.mtest_command + ['--setup=onlyinbar', '--no-suite=main:', '--no-suite=foo:']) + self._run(self.mtest_command + ['--setup=bar:onlyinbar']) + self.assertRaises(subprocess.CalledProcessError, self._run, + self.mtest_command + ['--setup=foo:onlyinbar']) + self.assertRaises(subprocess.CalledProcessError, self._run, + self.mtest_command + ['--setup=main:onlyinbar']) + + def test_testsetup_default(self): + testdir = os.path.join(self.unit_test_dir, '49 testsetup default') + self.init(testdir) + self.build() + + # Run tests without --setup will cause the default setup to be used + self.run_tests() + with open(os.path.join(self.logdir, 'testlog.txt'), encoding='utf-8') as f: + default_log = f.read() + + # Run tests with explicitly using the same setup that is set as default + self._run(self.mtest_command + ['--setup=mydefault']) + with open(os.path.join(self.logdir, 'testlog-mydefault.txt'), encoding='utf-8') as f: + mydefault_log = f.read() + + # Run tests with another setup + self._run(self.mtest_command + ['--setup=other']) + with open(os.path.join(self.logdir, 'testlog-other.txt'), encoding='utf-8') as f: + other_log = f.read() + + self.assertIn('ENV_A is 1', default_log) + self.assertIn('ENV_B is 2', default_log) + self.assertIn('ENV_C is 2', default_log) + + self.assertIn('ENV_A is 1', mydefault_log) + self.assertIn('ENV_B is 2', mydefault_log) + self.assertIn('ENV_C is 2', mydefault_log) + + self.assertIn('ENV_A is 1', other_log) + self.assertIn('ENV_B is 3', other_log) + self.assertIn('ENV_C is 2', other_log) + + def assertFailedTestCount(self, failure_count, command): + try: + self._run(command) + self.assertEqual(0, failure_count, 'Expected %d tests to fail.' % failure_count) + except subprocess.CalledProcessError as e: + self.assertEqual(e.returncode, failure_count) + + def test_suite_selection(self): + testdir = os.path.join(self.unit_test_dir, '4 suite selection') + self.init(testdir) + self.build() + + self.assertFailedTestCount(4, self.mtest_command) + + self.assertFailedTestCount(0, self.mtest_command + ['--suite', ':success']) + self.assertFailedTestCount(3, self.mtest_command + ['--suite', ':fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', ':success']) + self.assertFailedTestCount(1, self.mtest_command + ['--no-suite', ':fail']) + + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'mainprj']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc']) + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail']) + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjmix']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix']) + + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'mainprj:fail']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'mainprj:success']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj:fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'mainprj:success']) + + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail:fail']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjfail:success']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail:fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjfail:success']) + + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc:fail']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc:success']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc:fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc:success']) + + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjmix:fail']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjmix:success']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix:fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjmix:success']) + + self.assertFailedTestCount(2, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix:fail']) + self.assertFailedTestCount(3, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj']) + self.assertFailedTestCount(2, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj', '--no-suite', 'subprjmix:fail']) + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj', '--no-suite', 'subprjmix:fail', 'mainprj-failing_test']) + + self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'subprjfail:fail', '--no-suite', 'subprjmix:fail']) + + def test_build_by_default(self): + testdir = os.path.join(self.common_test_dir, '129 build by default') + self.init(testdir) + self.build() + genfile1 = os.path.join(self.builddir, 'generated1.dat') + genfile2 = os.path.join(self.builddir, 'generated2.dat') + exe1 = os.path.join(self.builddir, 'fooprog' + exe_suffix) + exe2 = os.path.join(self.builddir, 'barprog' + exe_suffix) + self.assertPathExists(genfile1) + self.assertPathExists(genfile2) + self.assertPathDoesNotExist(exe1) + self.assertPathDoesNotExist(exe2) + self.build(target=('fooprog' + exe_suffix)) + self.assertPathExists(exe1) + self.build(target=('barprog' + exe_suffix)) + self.assertPathExists(exe2) + + def test_internal_include_order(self): + if mesonbuild.environment.detect_msys2_arch() and ('MESON_RSP_THRESHOLD' in os.environ): + raise SkipTest('Test does not yet support gcc rsp files on msys2') + + testdir = os.path.join(self.common_test_dir, '130 include order') + self.init(testdir) + execmd = fxecmd = None + for cmd in self.get_compdb(): + if 'someexe' in cmd['command']: + execmd = cmd['command'] + continue + if 'somefxe' in cmd['command']: + fxecmd = cmd['command'] + continue + if not execmd or not fxecmd: + raise Exception('Could not find someexe and somfxe commands') + # Check include order for 'someexe' + incs = [a for a in split_args(execmd) if a.startswith("-I")] + self.assertEqual(len(incs), 9) + # Need to run the build so the private dir is created. + self.build() + pdirs = glob(os.path.join(self.builddir, 'sub4/someexe*.p')) + self.assertEqual(len(pdirs), 1) + privdir = pdirs[0][len(self.builddir)+1:] + self.assertPathEqual(incs[0], "-I" + privdir) + # target build subdir + self.assertPathEqual(incs[1], "-Isub4") + # target source subdir + self.assertPathBasenameEqual(incs[2], 'sub4') + # include paths added via per-target c_args: ['-I'...] + self.assertPathBasenameEqual(incs[3], 'sub3') + # target include_directories: build dir + self.assertPathEqual(incs[4], "-Isub2") + # target include_directories: source dir + self.assertPathBasenameEqual(incs[5], 'sub2') + # target internal dependency include_directories: build dir + self.assertPathEqual(incs[6], "-Isub1") + # target internal dependency include_directories: source dir + self.assertPathBasenameEqual(incs[7], 'sub1') + # custom target include dir + self.assertPathEqual(incs[8], '-Ictsub') + # Check include order for 'somefxe' + incs = [a for a in split_args(fxecmd) if a.startswith('-I')] + self.assertEqual(len(incs), 9) + # target private dir + pdirs = glob(os.path.join(self.builddir, 'somefxe*.p')) + self.assertEqual(len(pdirs), 1) + privdir = pdirs[0][len(self.builddir)+1:] + self.assertPathEqual(incs[0], '-I' + privdir) + # target build dir + self.assertPathEqual(incs[1], '-I.') + # target source dir + self.assertPathBasenameEqual(incs[2], os.path.basename(testdir)) + # target internal dependency correct include_directories: build dir + self.assertPathEqual(incs[3], "-Isub4") + # target internal dependency correct include_directories: source dir + self.assertPathBasenameEqual(incs[4], 'sub4') + # target internal dependency dep include_directories: build dir + self.assertPathEqual(incs[5], "-Isub1") + # target internal dependency dep include_directories: source dir + self.assertPathBasenameEqual(incs[6], 'sub1') + # target internal dependency wrong include_directories: build dir + self.assertPathEqual(incs[7], "-Isub2") + # target internal dependency wrong include_directories: source dir + self.assertPathBasenameEqual(incs[8], 'sub2') + + def test_compiler_detection(self): + ''' + Test that automatic compiler detection and setting from the environment + both work just fine. This is needed because while running project tests + and other unit tests, we always read CC/CXX/etc from the environment. + ''' + gnu = GnuCompiler + clang = ClangCompiler + intel = IntelGnuLikeCompiler + msvc = (VisualStudioCCompiler, VisualStudioCPPCompiler) + clangcl = (ClangClCCompiler, ClangClCPPCompiler) + ar = mesonbuild.linkers.ArLinker + lib = mesonbuild.linkers.VisualStudioLinker + langs = [('c', 'CC'), ('cpp', 'CXX')] + if not is_windows() and platform.machine().lower() != 'e2k': + langs += [('objc', 'OBJC'), ('objcpp', 'OBJCXX')] + testdir = os.path.join(self.unit_test_dir, '5 compiler detection') + env = get_fake_env(testdir, self.builddir, self.prefix) + for lang, evar in langs: + # Detect with evar and do sanity checks on that + if evar in os.environ: + ecc = compiler_from_language(env, lang, MachineChoice.HOST) + self.assertTrue(ecc.version) + elinker = detect_static_linker(env, ecc) + # Pop it so we don't use it for the next detection + evalue = os.environ.pop(evar) + # Very rough/strict heuristics. Would never work for actual + # compiler detection, but should be ok for the tests. + ebase = os.path.basename(evalue) + if ebase.startswith('g') or ebase.endswith(('-gcc', '-g++')): + self.assertIsInstance(ecc, gnu) + self.assertIsInstance(elinker, ar) + elif 'clang-cl' in ebase: + self.assertIsInstance(ecc, clangcl) + self.assertIsInstance(elinker, lib) + elif 'clang' in ebase: + self.assertIsInstance(ecc, clang) + self.assertIsInstance(elinker, ar) + elif ebase.startswith('ic'): + self.assertIsInstance(ecc, intel) + self.assertIsInstance(elinker, ar) + elif ebase.startswith('cl'): + self.assertIsInstance(ecc, msvc) + self.assertIsInstance(elinker, lib) + else: + raise AssertionError(f'Unknown compiler {evalue!r}') + # Check that we actually used the evalue correctly as the compiler + self.assertEqual(ecc.get_exelist(), split_args(evalue)) + # Do auto-detection of compiler based on platform, PATH, etc. + cc = compiler_from_language(env, lang, MachineChoice.HOST) + self.assertTrue(cc.version) + linker = detect_static_linker(env, cc) + # Check compiler type + if isinstance(cc, gnu): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + elif is_sunos(): + self.assertIsInstance(cc.linker, (mesonbuild.linkers.SolarisDynamicLinker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin)) + else: + self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin) + if isinstance(cc, clangcl): + self.assertIsInstance(linker, lib) + self.assertIsInstance(cc.linker, mesonbuild.linkers.ClangClDynamicLinker) + if isinstance(cc, clang): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + elif is_windows(): + # This is clang, not clang-cl. This can be either an + # ld-like linker of link.exe-like linker (usually the + # former for msys2, the latter otherwise) + self.assertIsInstance(cc.linker, (mesonbuild.linkers.MSVCDynamicLinker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin)) + else: + self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin) + if isinstance(cc, intel): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + elif is_windows(): + self.assertIsInstance(cc.linker, mesonbuild.linkers.XilinkDynamicLinker) + else: + self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuDynamicLinker) + if isinstance(cc, msvc): + self.assertTrue(is_windows()) + self.assertIsInstance(linker, lib) + self.assertEqual(cc.id, 'msvc') + self.assertTrue(hasattr(cc, 'is_64')) + self.assertIsInstance(cc.linker, mesonbuild.linkers.MSVCDynamicLinker) + # If we're on Windows CI, we know what the compiler will be + if 'arch' in os.environ: + if os.environ['arch'] == 'x64': + self.assertTrue(cc.is_64) + else: + self.assertFalse(cc.is_64) + # Set evar ourselves to a wrapper script that just calls the same + # exelist + some argument. This is meant to test that setting + # something like `ccache gcc -pipe` or `distcc ccache gcc` works. + wrapper = os.path.join(testdir, 'compiler wrapper.py') + wrappercc = python_command + [wrapper] + cc.get_exelist() + ['-DSOME_ARG'] + os.environ[evar] = ' '.join(quote_arg(w) for w in wrappercc) + + # Check static linker too + wrapperlinker = python_command + [wrapper] + linker.get_exelist() + linker.get_always_args() + os.environ['AR'] = ' '.join(quote_arg(w) for w in wrapperlinker) + + # Need a new env to re-run environment loading + env = get_fake_env(testdir, self.builddir, self.prefix) + + wcc = compiler_from_language(env, lang, MachineChoice.HOST) + wlinker = detect_static_linker(env, wcc) + # Pop it so we don't use it for the next detection + os.environ.pop('AR') + # Must be the same type since it's a wrapper around the same exelist + self.assertIs(type(cc), type(wcc)) + self.assertIs(type(linker), type(wlinker)) + # Ensure that the exelist is correct + self.assertEqual(wcc.get_exelist(), wrappercc) + self.assertEqual(wlinker.get_exelist(), wrapperlinker) + # Ensure that the version detection worked correctly + self.assertEqual(cc.version, wcc.version) + if hasattr(cc, 'is_64'): + self.assertEqual(cc.is_64, wcc.is_64) + + def test_always_prefer_c_compiler_for_asm(self): + testdir = os.path.join(self.common_test_dir, '133 c cpp and asm') + # Skip if building with MSVC + env = get_fake_env(testdir, self.builddir, self.prefix) + if detect_c_compiler(env, MachineChoice.HOST).get_id() == 'msvc': + raise SkipTest('MSVC can\'t compile assembly') + self.init(testdir) + commands = {'c-asm': {}, 'cpp-asm': {}, 'cpp-c-asm': {}, 'c-cpp-asm': {}} + for cmd in self.get_compdb(): + # Get compiler + split = split_args(cmd['command']) + if split[0] == 'ccache': + compiler = split[1] + else: + compiler = split[0] + # Classify commands + if 'Ic-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['c-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['c-asm']['c'] = compiler + else: + raise AssertionError('{!r} found in cpp-asm?'.format(cmd['command'])) + elif 'Icpp-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['cpp-asm']['asm'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['cpp-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in cpp-asm?'.format(cmd['command'])) + elif 'Ic-cpp-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['c-cpp-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['c-cpp-asm']['c'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['c-cpp-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in c-cpp-asm?'.format(cmd['command'])) + elif 'Icpp-c-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['cpp-c-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['cpp-c-asm']['c'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['cpp-c-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in cpp-c-asm?'.format(cmd['command'])) + else: + raise AssertionError('Unknown command {!r} found'.format(cmd['command'])) + # Check that .S files are always built with the C compiler + self.assertEqual(commands['c-asm']['asm'], commands['c-asm']['c']) + self.assertEqual(commands['c-asm']['asm'], commands['cpp-asm']['asm']) + self.assertEqual(commands['cpp-asm']['asm'], commands['c-cpp-asm']['c']) + self.assertEqual(commands['c-cpp-asm']['asm'], commands['c-cpp-asm']['c']) + self.assertEqual(commands['cpp-c-asm']['asm'], commands['cpp-c-asm']['c']) + self.assertNotEqual(commands['cpp-asm']['asm'], commands['cpp-asm']['cpp']) + self.assertNotEqual(commands['c-cpp-asm']['c'], commands['c-cpp-asm']['cpp']) + self.assertNotEqual(commands['cpp-c-asm']['c'], commands['cpp-c-asm']['cpp']) + # Check that the c-asm target is always linked with the C linker + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + m = re.search('build c-asm.*: c_LINKER', contents) + self.assertIsNotNone(m, msg=contents) + + def test_preprocessor_checks_CPPFLAGS(self): + ''' + Test that preprocessor compiler checks read CPPFLAGS and also CFLAGS but + not LDFLAGS. + ''' + testdir = os.path.join(self.common_test_dir, '132 get define') + define = 'MESON_TEST_DEFINE_VALUE' + # NOTE: this list can't have \n, ' or " + # \n is never substituted by the GNU pre-processor via a -D define + # ' and " confuse split_args() even when they are escaped + # % and # confuse the MSVC preprocessor + # !, ^, *, and < confuse lcc preprocessor + value = 'spaces and fun@$&()-=_+{}[]:;>?,./~`' + for env_var in ['CPPFLAGS', 'CFLAGS']: + env = {} + env[env_var] = f'-D{define}="{value}"' + env['LDFLAGS'] = '-DMESON_FAIL_VALUE=cflags-read' + self.init(testdir, extra_args=[f'-D{define}={value}'], override_envvars=env) + + def test_custom_target_exe_data_deterministic(self): + testdir = os.path.join(self.common_test_dir, '109 custom target capture') + self.init(testdir) + meson_exe_dat1 = glob(os.path.join(self.privatedir, 'meson_exe*.dat')) + self.wipe() + self.init(testdir) + meson_exe_dat2 = glob(os.path.join(self.privatedir, 'meson_exe*.dat')) + self.assertListEqual(meson_exe_dat1, meson_exe_dat2) + + def test_noop_changes_cause_no_rebuilds(self): + ''' + Test that no-op changes to the build files such as mtime do not cause + a rebuild of anything. + ''' + testdir = os.path.join(self.common_test_dir, '6 linkshared') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of meson.build should not rebuild anything + self.utime(os.path.join(testdir, 'meson.build')) + self.assertReconfiguredBuildIsNoop() + # Changing mtime of libefile.c should rebuild the library, but not relink the executable + self.utime(os.path.join(testdir, 'libfile.c')) + self.assertBuildRelinkedOnlyTarget('mylib') + + def test_source_changes_cause_rebuild(self): + ''' + Test that changes to sources and headers cause rebuilds, but not + changes to unused files (as determined by the dependency file) in the + input files list. + ''' + testdir = os.path.join(self.common_test_dir, '19 header in file list') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of header.h should rebuild everything + self.utime(os.path.join(testdir, 'header.h')) + self.assertBuildRelinkedOnlyTarget('prog') + + def test_custom_target_changes_cause_rebuild(self): + ''' + Test that in a custom target, changes to the input files, the + ExternalProgram, and any File objects on the command-line cause + a rebuild. + ''' + testdir = os.path.join(self.common_test_dir, '57 custom header generator') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of these should rebuild everything + for f in ('input.def', 'makeheader.py', 'somefile.txt'): + self.utime(os.path.join(testdir, f)) + self.assertBuildRelinkedOnlyTarget('prog') + + def test_source_generator_program_cause_rebuild(self): + ''' + Test that changes to generator programs in the source tree cause + a rebuild. + ''' + testdir = os.path.join(self.common_test_dir, '90 gen extra') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of generator should rebuild the executable + self.utime(os.path.join(testdir, 'srcgen.py')) + self.assertRebuiltTarget('basic') + + def test_static_library_lto(self): + ''' + Test that static libraries can be built with LTO and linked to + executables. On Linux, this requires the use of gcc-ar. + https://github.com/mesonbuild/meson/issues/1646 + ''' + testdir = os.path.join(self.common_test_dir, '5 linkstatic') + + env = get_fake_env(testdir, self.builddir, self.prefix) + if detect_c_compiler(env, MachineChoice.HOST).get_id() == 'clang' and is_windows(): + raise SkipTest('LTO not (yet) supported by windows clang') + + self.init(testdir, extra_args='-Db_lto=true') + self.build() + self.run_tests() + + @skip_if_not_base_option('b_lto_threads') + def test_lto_threads(self): + testdir = os.path.join(self.common_test_dir, '6 linkshared') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + extra_args: T.List[str] = [] + if cc.get_id() == 'clang': + if is_windows(): + raise SkipTest('LTO not (yet) supported by windows clang') + + self.init(testdir, extra_args=['-Db_lto=true', '-Db_lto_threads=8'] + extra_args) + self.build() + self.run_tests() + + expected = set(cc.get_lto_compile_args(threads=8)) + targets = self.introspect('--targets') + # This assumes all of the targets support lto + for t in targets: + for s in t['target_sources']: + for e in expected: + self.assertIn(e, s['parameters']) + + @skip_if_not_base_option('b_lto_mode') + @skip_if_not_base_option('b_lto_threads') + def test_lto_mode(self): + testdir = os.path.join(self.common_test_dir, '6 linkshared') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() != 'clang': + raise SkipTest('Only clang currently supports thinLTO') + if cc.linker.id not in {'ld.lld', 'ld.gold', 'ld64', 'lld-link'}: + raise SkipTest('thinLTO requires ld.lld, ld.gold, ld64, or lld-link') + elif is_windows(): + raise SkipTest('LTO not (yet) supported by windows clang') + + self.init(testdir, extra_args=['-Db_lto=true', '-Db_lto_mode=thin', '-Db_lto_threads=8', '-Dc_args=-Werror=unused-command-line-argument']) + self.build() + self.run_tests() + + expected = set(cc.get_lto_compile_args(threads=8, mode='thin')) + targets = self.introspect('--targets') + # This assumes all of the targets support lto + for t in targets: + for s in t['target_sources']: + self.assertTrue(expected.issubset(set(s['parameters'])), f'Incorrect values for {t["name"]}') + + def test_dist_git(self): + if not shutil.which('git'): + raise SkipTest('Git not found') + if self.backend is not Backend.ninja: + raise SkipTest('Dist is only supported with Ninja') + + try: + self.dist_impl(_git_init, _git_add_all) + except PermissionError: + # When run under Windows CI, something (virus scanner?) + # holds on to the git files so cleaning up the dir + # fails sometimes. + pass + + def has_working_hg(self): + if not shutil.which('hg'): + return False + try: + # This check should not be necessary, but + # CI under macOS passes the above test even + # though Mercurial is not installed. + if subprocess.call(['hg', '--version'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) != 0: + return False + return True + except FileNotFoundError: + return False + + def test_dist_hg(self): + if not self.has_working_hg(): + raise SkipTest('Mercurial not found or broken.') + if self.backend is not Backend.ninja: + raise SkipTest('Dist is only supported with Ninja') + + def hg_init(project_dir): + subprocess.check_call(['hg', 'init'], cwd=project_dir) + with open(os.path.join(project_dir, '.hg', 'hgrc'), 'w', encoding='utf-8') as f: + print('[ui]', file=f) + print('username=Author Person ', file=f) + subprocess.check_call(['hg', 'add', 'meson.build', 'distexe.c'], cwd=project_dir) + subprocess.check_call(['hg', 'commit', '-m', 'I am a project'], cwd=project_dir) + + try: + self.dist_impl(hg_init, include_subprojects=False) + except PermissionError: + # When run under Windows CI, something (virus scanner?) + # holds on to the hg files so cleaning up the dir + # fails sometimes. + pass + + def test_dist_git_script(self): + if not shutil.which('git'): + raise SkipTest('Git not found') + if self.backend is not Backend.ninja: + raise SkipTest('Dist is only supported with Ninja') + + try: + with tempfile.TemporaryDirectory() as tmpdir: + project_dir = os.path.join(tmpdir, 'a') + shutil.copytree(os.path.join(self.unit_test_dir, '35 dist script'), + project_dir) + _git_init(project_dir) + self.init(project_dir) + self.build('dist') + + self.new_builddir() + self.init(project_dir, extra_args=['-Dsub:broken_dist_script=false']) + self._run(self.meson_command + ['dist', '--include-subprojects'], workdir=self.builddir) + except PermissionError: + # When run under Windows CI, something (virus scanner?) + # holds on to the git files so cleaning up the dir + # fails sometimes. + pass + + def create_dummy_subproject(self, project_dir, name): + path = os.path.join(project_dir, 'subprojects', name) + os.makedirs(path) + with open(os.path.join(path, 'meson.build'), 'w', encoding='utf-8') as ofile: + ofile.write(f"project('{name}', version: '1.0')") + return path + + def dist_impl(self, vcs_init, vcs_add_all=None, include_subprojects=True): + # Create this on the fly because having rogue .git directories inside + # the source tree leads to all kinds of trouble. + with tempfile.TemporaryDirectory() as project_dir: + with open(os.path.join(project_dir, 'meson.build'), 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent('''\ + project('disttest', 'c', version : '1.4.3') + e = executable('distexe', 'distexe.c') + test('dist test', e) + subproject('vcssub', required : false) + subproject('tarballsub', required : false) + subproject('samerepo', required : false) + ''')) + with open(os.path.join(project_dir, 'distexe.c'), 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent('''\ + #include + + int main(int argc, char **argv) { + printf("I am a distribution test.\\n"); + return 0; + } + ''')) + xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz') + xz_checksumfile = xz_distfile + '.sha256sum' + gz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.gz') + gz_checksumfile = gz_distfile + '.sha256sum' + zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip') + zip_checksumfile = zip_distfile + '.sha256sum' + vcs_init(project_dir) + if include_subprojects: + vcs_init(self.create_dummy_subproject(project_dir, 'vcssub')) + self.create_dummy_subproject(project_dir, 'tarballsub') + self.create_dummy_subproject(project_dir, 'unusedsub') + if vcs_add_all: + vcs_add_all(self.create_dummy_subproject(project_dir, 'samerepo')) + self.init(project_dir) + self.build('dist') + self.assertPathExists(xz_distfile) + self.assertPathExists(xz_checksumfile) + self.assertPathDoesNotExist(gz_distfile) + self.assertPathDoesNotExist(gz_checksumfile) + self.assertPathDoesNotExist(zip_distfile) + self.assertPathDoesNotExist(zip_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'gztar'], + workdir=self.builddir) + self.assertPathExists(gz_distfile) + self.assertPathExists(gz_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'zip'], + workdir=self.builddir) + self.assertPathExists(zip_distfile) + self.assertPathExists(zip_checksumfile) + os.remove(xz_distfile) + os.remove(xz_checksumfile) + os.remove(gz_distfile) + os.remove(gz_checksumfile) + os.remove(zip_distfile) + os.remove(zip_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'xztar,gztar,zip'], + workdir=self.builddir) + self.assertPathExists(xz_distfile) + self.assertPathExists(xz_checksumfile) + self.assertPathExists(gz_distfile) + self.assertPathExists(gz_checksumfile) + self.assertPathExists(zip_distfile) + self.assertPathExists(zip_checksumfile) + + if include_subprojects: + # Verify that without --include-subprojects we have files from + # the main project and also files from subprojects part of the + # main vcs repository. + z = zipfile.ZipFile(zip_distfile) + expected = ['disttest-1.4.3/', + 'disttest-1.4.3/meson.build', + 'disttest-1.4.3/distexe.c'] + if vcs_add_all: + expected += ['disttest-1.4.3/subprojects/', + 'disttest-1.4.3/subprojects/samerepo/', + 'disttest-1.4.3/subprojects/samerepo/meson.build'] + self.assertEqual(sorted(expected), + sorted(z.namelist())) + # Verify that with --include-subprojects we now also have files + # from tarball and separate vcs subprojects. But not files from + # unused subprojects. + self._run(self.meson_command + ['dist', '--formats', 'zip', '--include-subprojects'], + workdir=self.builddir) + z = zipfile.ZipFile(zip_distfile) + expected += ['disttest-1.4.3/subprojects/tarballsub/', + 'disttest-1.4.3/subprojects/tarballsub/meson.build', + 'disttest-1.4.3/subprojects/vcssub/', + 'disttest-1.4.3/subprojects/vcssub/meson.build'] + self.assertEqual(sorted(expected), + sorted(z.namelist())) + if vcs_add_all: + # Verify we can distribute separately subprojects in the same vcs + # repository as the main project. + subproject_dir = os.path.join(project_dir, 'subprojects', 'samerepo') + self.new_builddir() + self.init(subproject_dir) + self.build('dist') + xz_distfile = os.path.join(self.distdir, 'samerepo-1.0.tar.xz') + xz_checksumfile = xz_distfile + '.sha256sum' + self.assertPathExists(xz_distfile) + self.assertPathExists(xz_checksumfile) + tar = tarfile.open(xz_distfile, "r:xz") # [ignore encoding] + self.assertEqual(sorted(['samerepo-1.0', + 'samerepo-1.0/meson.build']), + sorted(i.name for i in tar)) + + def test_rpath_uses_ORIGIN(self): + ''' + Test that built targets use $ORIGIN in rpath, which ensures that they + are relocatable and ensures that builds are reproducible since the + build directory won't get embedded into the built binaries. + ''' + if is_windows() or is_cygwin(): + raise SkipTest('Windows PE/COFF binaries do not use RPATH') + testdir = os.path.join(self.common_test_dir, '39 library chain') + self.init(testdir) + self.build() + for each in ('prog', 'subdir/liblib1.so', ): + rpath = get_rpath(os.path.join(self.builddir, each)) + self.assertTrue(rpath, f'Rpath could not be determined for {each}.') + if is_dragonflybsd(): + # DragonflyBSD will prepend /usr/lib/gccVERSION to the rpath, + # so ignore that. + self.assertTrue(rpath.startswith('/usr/lib/gcc')) + rpaths = rpath.split(':')[1:] + else: + rpaths = rpath.split(':') + for path in rpaths: + self.assertTrue(path.startswith('$ORIGIN'), msg=(each, path)) + # These two don't link to anything else, so they do not need an rpath entry. + for each in ('subdir/subdir2/liblib2.so', 'subdir/subdir3/liblib3.so'): + rpath = get_rpath(os.path.join(self.builddir, each)) + if is_dragonflybsd(): + # The rpath should be equal to /usr/lib/gccVERSION + self.assertTrue(rpath.startswith('/usr/lib/gcc')) + self.assertEqual(len(rpath.split(':')), 1) + else: + self.assertIsNone(rpath) + + def test_dash_d_dedup(self): + testdir = os.path.join(self.unit_test_dir, '9 d dedup') + self.init(testdir) + cmd = self.get_compdb()[0]['command'] + self.assertTrue('-D FOO -D BAR' in cmd or + '"-D" "FOO" "-D" "BAR"' in cmd or + '/D FOO /D BAR' in cmd or + '"/D" "FOO" "/D" "BAR"' in cmd) + + def test_all_forbidden_targets_tested(self): + ''' + Test that all forbidden targets are tested in the '150 reserved targets' + test. Needs to be a unit test because it accesses Meson internals. + ''' + testdir = os.path.join(self.common_test_dir, '150 reserved targets') + targets = mesonbuild.coredata.FORBIDDEN_TARGET_NAMES + # We don't actually define a target with this name + targets.pop('build.ninja') + # Remove this to avoid multiple entries with the same name + # but different case. + targets.pop('PHONY') + for i in targets: + self.assertPathExists(os.path.join(testdir, i)) + + def detect_prebuild_env(self): + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + stlinker = detect_static_linker(env, cc) + if is_windows(): + object_suffix = 'obj' + shared_suffix = 'dll' + elif is_cygwin(): + object_suffix = 'o' + shared_suffix = 'dll' + elif is_osx(): + object_suffix = 'o' + shared_suffix = 'dylib' + else: + object_suffix = 'o' + shared_suffix = 'so' + return (cc, stlinker, object_suffix, shared_suffix) + + def pbcompile(self, compiler, source, objectfile, extra_args=None): + cmd = compiler.get_exelist() + extra_args = extra_args or [] + if compiler.get_argument_syntax() == 'msvc': + cmd += ['/nologo', '/Fo' + objectfile, '/c', source] + extra_args + else: + cmd += ['-c', source, '-o', objectfile] + extra_args + subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def test_prebuilt_object(self): + (compiler, _, object_suffix, _) = self.detect_prebuild_env() + tdir = os.path.join(self.unit_test_dir, '15 prebuilt object') + source = os.path.join(tdir, 'source.c') + objectfile = os.path.join(tdir, 'prebuilt.' + object_suffix) + self.pbcompile(compiler, source, objectfile) + try: + self.init(tdir) + self.build() + self.run_tests() + finally: + os.unlink(objectfile) + + def build_static_lib(self, compiler, linker, source, objectfile, outfile, extra_args=None): + if extra_args is None: + extra_args = [] + link_cmd = linker.get_exelist() + link_cmd += linker.get_always_args() + link_cmd += linker.get_std_link_args(False) + link_cmd += linker.get_output_args(outfile) + link_cmd += [objectfile] + self.pbcompile(compiler, source, objectfile, extra_args=extra_args) + try: + subprocess.check_call(link_cmd) + finally: + os.unlink(objectfile) + + def test_prebuilt_static_lib(self): + (cc, stlinker, object_suffix, _) = self.detect_prebuild_env() + tdir = os.path.join(self.unit_test_dir, '16 prebuilt static') + source = os.path.join(tdir, 'libdir/best.c') + objectfile = os.path.join(tdir, 'libdir/best.' + object_suffix) + stlibfile = os.path.join(tdir, 'libdir/libbest.a') + self.build_static_lib(cc, stlinker, source, objectfile, stlibfile) + # Run the test + try: + self.init(tdir) + self.build() + self.run_tests() + finally: + os.unlink(stlibfile) + + def build_shared_lib(self, compiler, source, objectfile, outfile, impfile, extra_args=None): + if extra_args is None: + extra_args = [] + if compiler.get_argument_syntax() == 'msvc': + link_cmd = compiler.get_linker_exelist() + [ + '/NOLOGO', '/DLL', '/DEBUG', '/IMPLIB:' + impfile, + '/OUT:' + outfile, objectfile] + else: + if not (compiler.info.is_windows() or compiler.info.is_cygwin() or compiler.info.is_darwin()): + extra_args += ['-fPIC'] + link_cmd = compiler.get_exelist() + ['-shared', '-o', outfile, objectfile] + if not is_osx(): + link_cmd += ['-Wl,-soname=' + os.path.basename(outfile)] + self.pbcompile(compiler, source, objectfile, extra_args=extra_args) + try: + subprocess.check_call(link_cmd) + finally: + os.unlink(objectfile) + + def test_prebuilt_shared_lib(self): + (cc, _, object_suffix, shared_suffix) = self.detect_prebuild_env() + tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') + source = os.path.join(tdir, 'alexandria.c') + objectfile = os.path.join(tdir, 'alexandria.' + object_suffix) + impfile = os.path.join(tdir, 'alexandria.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(tdir, 'alexandria.' + shared_suffix) + elif is_cygwin(): + shlibfile = os.path.join(tdir, 'cygalexandria.' + shared_suffix) + else: + shlibfile = os.path.join(tdir, 'libalexandria.' + shared_suffix) + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + + if is_windows(): + def cleanup() -> None: + """Clean up all the garbage MSVC writes in the source tree.""" + + for fname in glob(os.path.join(tdir, 'alexandria.*')): + if os.path.splitext(fname)[1] not in {'.c', '.h'}: + os.unlink(fname) + self.addCleanup(cleanup) + else: + self.addCleanup(os.unlink, shlibfile) + + # Run the test + self.init(tdir) + self.build() + self.run_tests() + + def test_prebuilt_shared_lib_rpath(self) -> None: + (cc, _, object_suffix, shared_suffix) = self.detect_prebuild_env() + tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') + with tempfile.TemporaryDirectory() as d: + source = os.path.join(tdir, 'alexandria.c') + objectfile = os.path.join(d, 'alexandria.' + object_suffix) + impfile = os.path.join(d, 'alexandria.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(d, 'alexandria.' + shared_suffix) + elif is_cygwin(): + shlibfile = os.path.join(d, 'cygalexandria.' + shared_suffix) + else: + shlibfile = os.path.join(d, 'libalexandria.' + shared_suffix) + # Ensure MSVC extra files end up in the directory that gets deleted + # at the end + with chdir(d): + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + + # Run the test + self.init(tdir, extra_args=[f'-Dsearch_dir={d}']) + self.build() + self.run_tests() + + @skipIfNoPkgconfig + def test_pkgconfig_static(self): + ''' + Test that the we prefer static libraries when `static: true` is + passed to dependency() with pkg-config. Can't be an ordinary test + because we need to build libs and try to find them from meson.build + + Also test that it's not a hard error to have unsatisfiable library deps + since system libraries -lm will never be found statically. + https://github.com/mesonbuild/meson/issues/2785 + ''' + (cc, stlinker, objext, shext) = self.detect_prebuild_env() + testdir = os.path.join(self.unit_test_dir, '18 pkgconfig static') + source = os.path.join(testdir, 'foo.c') + objectfile = os.path.join(testdir, 'foo.' + objext) + stlibfile = os.path.join(testdir, 'libfoo.a') + impfile = os.path.join(testdir, 'foo.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(testdir, 'foo.' + shext) + elif is_cygwin(): + shlibfile = os.path.join(testdir, 'cygfoo.' + shext) + else: + shlibfile = os.path.join(testdir, 'libfoo.' + shext) + # Build libs + self.build_static_lib(cc, stlinker, source, objectfile, stlibfile, extra_args=['-DFOO_STATIC']) + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + # Run test + try: + self.init(testdir, override_envvars={'PKG_CONFIG_LIBDIR': self.builddir}) + self.build() + self.run_tests() + finally: + os.unlink(stlibfile) + os.unlink(shlibfile) + if is_windows(): + # Clean up all the garbage MSVC writes in the + # source tree. + for fname in glob(os.path.join(testdir, 'foo.*')): + if os.path.splitext(fname)[1] not in ['.c', '.h', '.in']: + os.unlink(fname) + + @skipIfNoPkgconfig + @mock.patch.dict(os.environ) + def test_pkgconfig_gen_escaping(self): + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + prefix = '/usr/with spaces' + libdir = 'lib' + self.init(testdir, extra_args=['--prefix=' + prefix, + '--libdir=' + libdir]) + # Find foo dependency + os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir + env = get_fake_env(testdir, self.builddir, self.prefix) + kwargs = {'required': True, 'silent': True} + foo_dep = PkgConfigDependency('libanswer', env, kwargs) + # Ensure link_args are properly quoted + libdir = PurePath(prefix) / PurePath(libdir) + 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') + cargs = ['-I' + incdir.as_posix(), '-DLIBFOO'] + # pkg-config and pkgconf does not respect the same order + self.assertEqual(sorted(foo_dep.get_compile_args()), sorted(cargs)) + + def test_array_option_change(self): + def get_opt(): + opts = self.introspect('--buildoptions') + for x in opts: + if x.get('name') == 'list': + return x + raise Exception(opts) + + expected = { + 'name': 'list', + 'description': 'list', + 'section': 'user', + 'type': 'array', + 'value': ['foo', 'bar'], + 'choices': ['foo', 'bar', 'oink', 'boink'], + 'machine': 'any', + } + tdir = os.path.join(self.unit_test_dir, '19 array option') + self.init(tdir) + original = get_opt() + self.assertDictEqual(original, expected) + + expected['value'] = ['oink', 'boink'] + self.setconf('-Dlist=oink,boink') + changed = get_opt() + self.assertEqual(changed, expected) + + def test_array_option_bad_change(self): + def get_opt(): + opts = self.introspect('--buildoptions') + for x in opts: + if x.get('name') == 'list': + return x + raise Exception(opts) + + expected = { + 'name': 'list', + 'description': 'list', + 'section': 'user', + 'type': 'array', + 'value': ['foo', 'bar'], + 'choices': ['foo', 'bar', 'oink', 'boink'], + 'machine': 'any', + } + tdir = os.path.join(self.unit_test_dir, '19 array option') + self.init(tdir) + original = get_opt() + self.assertDictEqual(original, expected) + with self.assertRaises(subprocess.CalledProcessError): + self.setconf('-Dlist=bad') + changed = get_opt() + self.assertDictEqual(changed, expected) + + def test_array_option_empty_equivalents(self): + """Array options treat -Dopt=[] and -Dopt= as equivalent.""" + def get_opt(): + opts = self.introspect('--buildoptions') + for x in opts: + if x.get('name') == 'list': + return x + raise Exception(opts) + + expected = { + 'name': 'list', + 'description': 'list', + 'section': 'user', + 'type': 'array', + 'value': [], + 'choices': ['foo', 'bar', 'oink', 'boink'], + 'machine': 'any', + } + tdir = os.path.join(self.unit_test_dir, '19 array option') + self.init(tdir, extra_args='-Dlist=') + original = get_opt() + self.assertDictEqual(original, expected) + + def opt_has(self, name, value): + res = self.introspect('--buildoptions') + found = False + for i in res: + if i['name'] == name: + self.assertEqual(i['value'], value) + found = True + break + self.assertTrue(found, "Array option not found in introspect data.") + + def test_free_stringarray_setting(self): + testdir = os.path.join(self.common_test_dir, '40 options') + self.init(testdir) + self.opt_has('free_array_opt', []) + self.setconf('-Dfree_array_opt=foo,bar', will_build=False) + self.opt_has('free_array_opt', ['foo', 'bar']) + self.setconf("-Dfree_array_opt=['a,b', 'c,d']", will_build=False) + self.opt_has('free_array_opt', ['a,b', 'c,d']) + + # When running under Travis Mac CI, the file updates seem to happen + # too fast so the timestamps do not get properly updated. + # Call this method before file operations in appropriate places + # to make things work. + def mac_ci_delay(self): + if is_osx() and is_ci(): + import time + time.sleep(1) + + def test_options_with_choices_changing(self) -> None: + """Detect when options like arrays or combos have their choices change.""" + testdir = Path(os.path.join(self.unit_test_dir, '84 change option choices')) + options1 = str(testdir / 'meson_options.1.txt') + options2 = str(testdir / 'meson_options.2.txt') + + # Test that old options are changed to the new defaults if they are not valid + real_options = str(testdir / 'meson_options.txt') + self.addCleanup(os.unlink, real_options) + + shutil.copy(options1, real_options) + self.init(str(testdir)) + self.mac_ci_delay() + shutil.copy(options2, real_options) + + self.build() + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == 'combo': + self.assertEqual(item['value'], 'b') + self.assertEqual(item['choices'], ['b', 'c', 'd']) + elif item['name'] == 'array': + self.assertEqual(item['value'], ['b']) + self.assertEqual(item['choices'], ['b', 'c', 'd']) + + self.wipe() + self.mac_ci_delay() + + # When the old options are valid they should remain + shutil.copy(options1, real_options) + self.init(str(testdir), extra_args=['-Dcombo=c', '-Darray=b,c']) + self.mac_ci_delay() + shutil.copy(options2, real_options) + self.build() + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == 'combo': + self.assertEqual(item['value'], 'c') + self.assertEqual(item['choices'], ['b', 'c', 'd']) + elif item['name'] == 'array': + self.assertEqual(item['value'], ['b', 'c']) + self.assertEqual(item['choices'], ['b', 'c', 'd']) + + def test_subproject_promotion(self): + testdir = os.path.join(self.unit_test_dir, '12 promote') + workdir = os.path.join(self.builddir, 'work') + shutil.copytree(testdir, workdir) + spdir = os.path.join(workdir, 'subprojects') + s3dir = os.path.join(spdir, 's3') + scommondir = os.path.join(spdir, 'scommon') + self.assertFalse(os.path.isdir(s3dir)) + subprocess.check_call(self.wrap_command + ['promote', 's3'], + cwd=workdir, + stdout=subprocess.DEVNULL) + self.assertTrue(os.path.isdir(s3dir)) + self.assertFalse(os.path.isdir(scommondir)) + self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'scommon'], + cwd=workdir, + stderr=subprocess.DEVNULL), 0) + self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'invalid/path/to/scommon'], + cwd=workdir, + stderr=subprocess.DEVNULL), 0) + self.assertFalse(os.path.isdir(scommondir)) + subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/scommon'], cwd=workdir) + self.assertTrue(os.path.isdir(scommondir)) + promoted_wrap = os.path.join(spdir, 'athing.wrap') + self.assertFalse(os.path.isfile(promoted_wrap)) + subprocess.check_call(self.wrap_command + ['promote', 'athing'], cwd=workdir) + self.assertTrue(os.path.isfile(promoted_wrap)) + self.init(workdir) + self.build() + + def test_subproject_promotion_wrap(self): + testdir = os.path.join(self.unit_test_dir, '44 promote wrap') + workdir = os.path.join(self.builddir, 'work') + shutil.copytree(testdir, workdir) + spdir = os.path.join(workdir, 'subprojects') + + ambiguous_wrap = os.path.join(spdir, 'ambiguous.wrap') + self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'ambiguous'], + cwd=workdir, + stderr=subprocess.DEVNULL), 0) + self.assertFalse(os.path.isfile(ambiguous_wrap)) + subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/ambiguous.wrap'], cwd=workdir) + self.assertTrue(os.path.isfile(ambiguous_wrap)) + + def test_warning_location(self): + tdir = os.path.join(self.unit_test_dir, '22 warning location') + out = self.init(tdir) + for expected in [ + r'meson.build:4: WARNING: Keyword argument "link_with" defined multiple times.', + r'sub' + os.path.sep + r'meson.build:3: WARNING: Keyword argument "link_with" defined multiple times.', + r'meson.build:6: WARNING: a warning of some sort', + r'sub' + os.path.sep + r'meson.build:4: WARNING: subdir warning', + r'meson.build:7: WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases.', + r"meson.build:11: WARNING: The variable(s) 'MISSING' in the input file 'conf.in' are not present in the given configuration data.", + ]: + self.assertRegex(out, re.escape(expected)) + + for wd in [ + self.src_root, + self.builddir, + os.getcwd(), + ]: + self.new_builddir() + out = self.init(tdir, workdir=wd) + expected = os.path.join(relpath(tdir, self.src_root), 'meson.build') + relwd = relpath(self.src_root, wd) + if relwd != '.': + expected = os.path.join(relwd, expected) + expected = '\n' + expected + ':' + self.assertIn(expected, out) + + def test_error_location_path(self): + '''Test locations in meson errors contain correct paths''' + # this list contains errors from all the different steps in the + # lexer/parser/interpreter we have tests for. + for (t, f) in [ + ('10 out of bounds', 'meson.build'), + ('18 wrong plusassign', 'meson.build'), + ('60 bad option argument', 'meson_options.txt'), + ('98 subdir parse error', os.path.join('subdir', 'meson.build')), + ('99 invalid option file', 'meson_options.txt'), + ]: + tdir = os.path.join(self.src_root, 'test cases', 'failing', t) + + for wd in [ + self.src_root, + self.builddir, + os.getcwd(), + ]: + try: + self.init(tdir, workdir=wd) + except subprocess.CalledProcessError as e: + expected = os.path.join('test cases', 'failing', t, f) + relwd = relpath(self.src_root, wd) + if relwd != '.': + expected = os.path.join(relwd, expected) + expected = '\n' + expected + ':' + self.assertIn(expected, e.output) + else: + self.fail('configure unexpectedly succeeded') + + def test_permitted_method_kwargs(self): + tdir = os.path.join(self.unit_test_dir, '25 non-permitted kwargs') + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(tdir) + self.assertIn('ERROR: compiler.has_header_symbol got unknown keyword arguments "prefixxx"', cm.exception.output) + + def test_templates(self): + ninja = mesonbuild.environment.detect_ninja() + if ninja is None: + raise SkipTest('This test currently requires ninja. Fix this once "meson build" works.') + + langs = ['c'] + env = get_fake_env() + for l in ['cpp', 'cs', 'd', 'java', 'cuda', 'fortran', 'objc', 'objcpp', 'rust']: + try: + comp = detect_compiler_for(env, l, MachineChoice.HOST) + with tempfile.TemporaryDirectory() as d: + comp.sanity_check(d, env) + langs.append(l) + except EnvironmentException: + pass + + # The D template fails under mac CI and we don't know why. + # Patches welcome + if is_osx(): + langs = [l for l in langs if l != 'd'] + + for lang in langs: + for target_type in ('executable', 'library'): + # test empty directory + with tempfile.TemporaryDirectory() as tmpdir: + self._run(self.meson_command + ['init', '--language', lang, '--type', target_type], + workdir=tmpdir) + self._run(self.setup_command + ['--backend=ninja', 'builddir'], + workdir=tmpdir) + self._run(ninja, + workdir=os.path.join(tmpdir, 'builddir')) + # test directory with existing code file + if lang in {'c', 'cpp', 'd'}: + with tempfile.TemporaryDirectory() as tmpdir: + with open(os.path.join(tmpdir, 'foo.' + lang), 'w', encoding='utf-8') as f: + f.write('int main(void) {}') + self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) + elif lang in {'java'}: + with tempfile.TemporaryDirectory() as tmpdir: + with open(os.path.join(tmpdir, 'Foo.' + lang), 'w', encoding='utf-8') as f: + f.write('public class Foo { public static void main() {} }') + self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) + + def test_compiler_run_command(self): + ''' + The test checks that the compiler object can be passed to + run_command(). + ''' + testdir = os.path.join(self.unit_test_dir, '24 compiler run_command') + self.init(testdir) + + def test_identical_target_name_in_subproject_flat_layout(self): + ''' + Test that identical targets in different subprojects do not collide + if layout is flat. + ''' + testdir = os.path.join(self.common_test_dir, '172 identical target name in subproject flat layout') + self.init(testdir, extra_args=['--layout=flat']) + self.build() + + def test_identical_target_name_in_subdir_flat_layout(self): + ''' + Test that identical targets in different subdirs do not collide + if layout is flat. + ''' + testdir = os.path.join(self.common_test_dir, '181 same target name flat layout') + self.init(testdir, extra_args=['--layout=flat']) + self.build() + + def test_flock(self): + exception_raised = False + with tempfile.TemporaryDirectory() as tdir: + os.mkdir(os.path.join(tdir, 'meson-private')) + with BuildDirLock(tdir): + try: + with BuildDirLock(tdir): + pass + except MesonException: + exception_raised = True + self.assertTrue(exception_raised, 'Double locking did not raise exception.') + + @skipIf(is_osx(), 'Test not applicable to OSX') + def test_check_module_linking(self): + """ + Test that link_with: a shared module issues a warning + https://github.com/mesonbuild/meson/issues/2865 + (That an error is raised on OSX is exercised by test failing/78) + """ + tdir = os.path.join(self.unit_test_dir, '30 shared_mod linking') + out = self.init(tdir) + msg = ('''DEPRECATION: target prog links against shared module mymod, which is incorrect. + This will be an error in the future, so please use shared_library() for mymod instead. + If shared_module() was used for mymod because it has references to undefined symbols, + use shared_libary() with `override_options: ['b_lundef=false']` instead.''') + self.assertIn(msg, out) + + def test_mixed_language_linker_check(self): + testdir = os.path.join(self.unit_test_dir, '97 compiler.links file arg') + self.init(testdir) + cmds = self.get_meson_log_compiler_checks() + self.assertEqual(len(cmds), 5) + # Path to the compilers, gleaned from cc.compiles tests + cc = cmds[0][0] + cxx = cmds[1][0] + # cc.links + self.assertEqual(cmds[2][0], cc) + # cxx.links with C source + self.assertEqual(cmds[3][0], cc) + self.assertEqual(cmds[4][0], cxx) + if self.backend is Backend.ninja: + # updating the file to check causes a reconfigure + # + # only the ninja backend is competent enough to detect reconfigured + # no-op builds without build targets + self.utime(os.path.join(testdir, 'test.c')) + self.assertReconfiguredBuildIsNoop() + + def test_ndebug_if_release_disabled(self): + testdir = os.path.join(self.unit_test_dir, '28 ndebug if-release') + self.init(testdir, extra_args=['--buildtype=release', '-Db_ndebug=if-release']) + self.build() + exe = os.path.join(self.builddir, 'main') + self.assertEqual(b'NDEBUG=1', subprocess.check_output(exe).strip()) + + def test_ndebug_if_release_enabled(self): + testdir = os.path.join(self.unit_test_dir, '28 ndebug if-release') + self.init(testdir, extra_args=['--buildtype=debugoptimized', '-Db_ndebug=if-release']) + self.build() + exe = os.path.join(self.builddir, 'main') + self.assertEqual(b'NDEBUG=0', subprocess.check_output(exe).strip()) + + def test_guessed_linker_dependencies(self): + ''' + Test that meson adds dependencies for libraries based on the final + linker command line. + ''' + testdirbase = os.path.join(self.unit_test_dir, '29 guessed linker dependencies') + testdirlib = os.path.join(testdirbase, 'lib') + + extra_args = None + libdir_flags = ['-L'] + env = get_fake_env(testdirlib, self.builddir, self.prefix) + if detect_c_compiler(env, MachineChoice.HOST).get_id() in {'msvc', 'clang-cl', 'intel-cl'}: + # msvc-like compiler, also test it with msvc-specific flags + libdir_flags += ['/LIBPATH:', '-LIBPATH:'] + else: + # static libraries are not linkable with -l with msvc because meson installs them + # as .a files which unix_args_to_native will not know as it expects libraries to use + # .lib as extension. For a DLL the import library is installed as .lib. Thus for msvc + # this tests needs to use shared libraries to test the path resolving logic in the + # dependency generation code path. + extra_args = ['--default-library', 'static'] + + initial_builddir = self.builddir + initial_installdir = self.installdir + + for libdir_flag in libdir_flags: + # build library + self.new_builddir() + self.init(testdirlib, extra_args=extra_args) + self.build() + self.install() + libbuilddir = self.builddir + installdir = self.installdir + libdir = os.path.join(self.installdir, self.prefix.lstrip('/').lstrip('\\'), 'lib') + + # build user of library + self.new_builddir() + # replace is needed because meson mangles platform paths passed via LDFLAGS + self.init(os.path.join(testdirbase, 'exe'), + override_envvars={"LDFLAGS": '{}{}'.format(libdir_flag, libdir.replace('\\', '/'))}) + self.build() + self.assertBuildIsNoop() + + # rebuild library + exebuilddir = self.builddir + self.installdir = installdir + self.builddir = libbuilddir + # Microsoft's compiler is quite smart about touching import libs on changes, + # so ensure that there is actually a change in symbols. + self.setconf('-Dmore_exports=true') + self.build() + self.install() + # no ensure_backend_detects_changes needed because self.setconf did that already + + # assert user of library will be rebuild + self.builddir = exebuilddir + self.assertRebuiltTarget('app') + + # restore dirs for the next test case + self.installdir = initial_builddir + self.builddir = initial_installdir + + def test_conflicting_d_dash_option(self): + testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as e: + self.init(testdir, extra_args=['-Dbindir=foo', '--bindir=bar']) + # Just to ensure that we caught the correct error + self.assertIn('as both', e.stderr) + + def _test_same_option_twice(self, arg, args): + testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') + self.init(testdir, extra_args=args) + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == arg: + self.assertEqual(item['value'], 'bar') + return + raise Exception(f'Missing {arg} value?') + + def test_same_dash_option_twice(self): + self._test_same_option_twice('bindir', ['--bindir=foo', '--bindir=bar']) + + def test_same_d_option_twice(self): + self._test_same_option_twice('bindir', ['-Dbindir=foo', '-Dbindir=bar']) + + def test_same_project_d_option_twice(self): + self._test_same_option_twice('one', ['-Done=foo', '-Done=bar']) + + def _test_same_option_twice_configure(self, arg, args): + testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') + self.init(testdir) + self.setconf(args) + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == arg: + self.assertEqual(item['value'], 'bar') + return + raise Exception(f'Missing {arg} value?') + + def test_same_dash_option_twice_configure(self): + self._test_same_option_twice_configure( + 'bindir', ['--bindir=foo', '--bindir=bar']) + + def test_same_d_option_twice_configure(self): + self._test_same_option_twice_configure( + 'bindir', ['-Dbindir=foo', '-Dbindir=bar']) + + def test_same_project_d_option_twice_configure(self): + self._test_same_option_twice_configure( + 'one', ['-Done=foo', '-Done=bar']) + + def test_command_line(self): + testdir = os.path.join(self.unit_test_dir, '34 command line') + + # Verify default values when passing no args that affect the + # configuration, and as a bonus, test that --profile-self works. + out = self.init(testdir, extra_args=['--profile-self', '--fatal-meson-warnings']) + self.assertNotIn('[default: true]', out) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('default_library')].value, 'static') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') + self.assertEqual(obj.options[OptionKey('set_sub_opt')].value, True) + self.assertEqual(obj.options[OptionKey('subp_opt', 'subp')].value, 'default3') + self.wipe() + + # warning_level is special, it's --warnlevel instead of --warning-level + # for historical reasons + self.init(testdir, extra_args=['--warnlevel=2', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '2') + self.setconf('--warnlevel=3') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '3') + self.wipe() + + # But when using -D syntax, it should be 'warning_level' + self.init(testdir, extra_args=['-Dwarning_level=2', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '2') + self.setconf('-Dwarning_level=3') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '3') + self.wipe() + + # Mixing --option and -Doption is forbidden + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.init(testdir, extra_args=['--warnlevel=1', '-Dwarning_level=3']) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn('as both', cm.exception.output) + else: + self.assertIn('as both', str(cm.exception)) + self.init(testdir) + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.setconf(['--warnlevel=1', '-Dwarning_level=3']) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn('as both', cm.exception.output) + else: + self.assertIn('as both', str(cm.exception)) + self.wipe() + + # --default-library should override default value from project() + self.init(testdir, extra_args=['--default-library=both', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('default_library')].value, 'both') + self.setconf('--default-library=shared') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('default_library')].value, 'shared') + if self.backend is Backend.ninja: + # reconfigure target works only with ninja backend + self.build('reconfigure') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('default_library')].value, 'shared') + self.wipe() + + # Should fail on unknown options + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.init(testdir, extra_args=['-Dbad=1', '-Dfoo=2', '-Dwrong_link_args=foo']) + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn(msg, cm.exception.output) + self.wipe() + + # Should fail on malformed option + msg = "Option 'foo' must have a value separated by equals sign." + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.init(testdir, extra_args=['-Dfoo']) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn(msg, cm.exception.output) + else: + self.assertIn(msg, str(cm.exception)) + self.init(testdir) + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.setconf('-Dfoo') + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn(msg, cm.exception.output) + else: + self.assertIn(msg, str(cm.exception)) + self.wipe() + + # It is not an error to set wrong option for unknown subprojects or + # language because we don't have control on which one will be selected. + self.init(testdir, extra_args=['-Dc_wrong=1', '-Dwrong:bad=1', '-Db_wrong=1']) + self.wipe() + + # Test we can set subproject option + self.init(testdir, extra_args=['-Dsubp:subp_opt=foo', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('subp_opt', 'subp')].value, 'foo') + self.wipe() + + # c_args value should be parsed with split_args + self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dfoo', '-Dbar', '-Dthird=one two']) + + self.setconf('-Dc_args="foo bar" one two') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['foo bar', 'one', 'two']) + self.wipe() + + self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('set_percent_opt')].value, 'myoption%') + self.wipe() + + # Setting a 2nd time the same option should override the first value + try: + self.init(testdir, extra_args=['--bindir=foo', '--bindir=bar', + '-Dbuildtype=plain', '-Dbuildtype=release', + '-Db_sanitize=address', '-Db_sanitize=thread', + '-Dc_args=-Dfoo', '-Dc_args=-Dbar', + '-Db_lundef=false', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('bindir')].value, 'bar') + self.assertEqual(obj.options[OptionKey('buildtype')].value, 'release') + self.assertEqual(obj.options[OptionKey('b_sanitize')].value, 'thread') + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dbar']) + self.setconf(['--bindir=bar', '--bindir=foo', + '-Dbuildtype=release', '-Dbuildtype=plain', + '-Db_sanitize=thread', '-Db_sanitize=address', + '-Dc_args=-Dbar', '-Dc_args=-Dfoo']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('bindir')].value, 'foo') + self.assertEqual(obj.options[OptionKey('buildtype')].value, 'plain') + self.assertEqual(obj.options[OptionKey('b_sanitize')].value, 'address') + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dfoo']) + self.wipe() + except KeyError: + # Ignore KeyError, it happens on CI for compilers that does not + # support b_sanitize. We have to test with a base option because + # they used to fail this test with Meson 0.46 an earlier versions. + pass + + def test_warning_level_0(self): + testdir = os.path.join(self.common_test_dir, '207 warning level 0') + + # Verify default values when passing no args + self.init(testdir) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') + self.wipe() + + # verify we can override w/ --warnlevel + self.init(testdir, extra_args=['--warnlevel=1']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') + self.setconf('--warnlevel=0') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') + self.wipe() + + # verify we can override w/ -Dwarning_level + self.init(testdir, extra_args=['-Dwarning_level=1']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') + self.setconf('-Dwarning_level=0') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') + self.wipe() + + def test_feature_check_usage_subprojects(self): + testdir = os.path.join(self.unit_test_dir, '41 featurenew subprojects') + out = self.init(testdir) + # Parent project warns correctly + self.assertRegex(out, "WARNING: Project targeting '>=0.45'.*'0.47.0': dict") + # Subprojects warn correctly + self.assertRegex(out, r"foo\| .*WARNING: Project targeting '>=0.40'.*'0.44.0': disabler") + self.assertRegex(out, r"baz\| .*WARNING: Project targeting '!=0.40'.*'0.44.0': disabler") + # Subproject has a new-enough meson_version, no warning + self.assertNotRegex(out, "WARNING: Project targeting.*Python") + # Ensure a summary is printed in the subproject and the outer project + self.assertRegex(out, r"\| WARNING: Project specifies a minimum meson_version '>=0.40'") + self.assertRegex(out, r"\| \* 0.44.0: {'disabler'}") + self.assertRegex(out, "WARNING: Project specifies a minimum meson_version '>=0.45'") + self.assertRegex(out, " * 0.47.0: {'dict'}") + + def test_configure_file_warnings(self): + testdir = os.path.join(self.common_test_dir, "14 configure file") + out = self.init(testdir) + self.assertRegex(out, "WARNING:.*'empty'.*config.h.in.*not present.*") + self.assertRegex(out, "WARNING:.*'FOO_BAR'.*nosubst-nocopy2.txt.in.*not present.*") + self.assertRegex(out, "WARNING:.*'empty'.*config.h.in.*not present.*") + self.assertRegex(out, "WARNING:.*empty configuration_data.*test.py.in") + # Warnings for configuration files that are overwritten. + self.assertRegex(out, "WARNING:.*\"double_output.txt\".*overwrites") + self.assertRegex(out, "WARNING:.*\"subdir.double_output2.txt\".*overwrites") + self.assertNotRegex(out, "WARNING:.*no_write_conflict.txt.*overwrites") + self.assertNotRegex(out, "WARNING:.*@BASENAME@.*overwrites") + self.assertRegex(out, "WARNING:.*\"sameafterbasename\".*overwrites") + # No warnings about empty configuration data objects passed to files with substitutions + self.assertNotRegex(out, "WARNING:.*empty configuration_data.*nosubst-nocopy1.txt.in") + self.assertNotRegex(out, "WARNING:.*empty configuration_data.*nosubst-nocopy2.txt.in") + with open(os.path.join(self.builddir, 'nosubst-nocopy1.txt'), 'rb') as f: + 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: + with tempfile.TemporaryDirectory(dir=containing) as srcdir: + mfile = os.path.join(srcdir, 'meson.build') + of = open(mfile, 'w', encoding='utf-8') + of.write("project('foobar', 'c')\n") + of.close() + pc = subprocess.run(self.setup_command, + cwd=srcdir, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + self.assertIn(b'Must specify at least one directory name', pc.stdout) + with tempfile.TemporaryDirectory(dir=srcdir) as builddir: + subprocess.run(self.setup_command, + check=True, + cwd=builddir, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + + def get_opts_as_dict(self): + result = {} + for i in self.introspect('--buildoptions'): + result[i['name']] = i['value'] + return result + + def test_buildtype_setting(self): + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + opts = self.get_opts_as_dict() + self.assertEqual(opts['buildtype'], 'debug') + self.assertEqual(opts['debug'], True) + self.setconf('-Ddebug=false') + opts = self.get_opts_as_dict() + self.assertEqual(opts['debug'], False) + self.assertEqual(opts['buildtype'], 'debug') + self.assertEqual(opts['optimization'], '0') + self.setconf('-Doptimization=g') + opts = self.get_opts_as_dict() + self.assertEqual(opts['debug'], False) + self.assertEqual(opts['buildtype'], 'debug') + self.assertEqual(opts['optimization'], 'g') + + @skipIfNoPkgconfig + @skipIf(is_windows(), 'Help needed with fixing this test on windows') + def test_native_dep_pkgconfig(self): + testdir = os.path.join(self.unit_test_dir, + '46 native dep pkgconfig var') + with tempfile.NamedTemporaryFile(mode='w', delete=False) as crossfile: + crossfile.write(textwrap.dedent( + '''[binaries] + pkgconfig = '{}' + + [properties] + + [host_machine] + system = 'linux' + cpu_family = 'arm' + cpu = 'armv7' + endian = 'little' + '''.format(os.path.join(testdir, 'cross_pkgconfig.py')))) + crossfile.flush() + self.meson_cross_files = [crossfile.name] + + env = {'PKG_CONFIG_LIBDIR': os.path.join(testdir, + 'native_pkgconfig')} + self.init(testdir, extra_args=['-Dstart_native=false'], override_envvars=env) + self.wipe() + self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env) + + @skipIfNoPkgconfig + @skipIf(is_windows(), 'Help needed with fixing this test on windows') + def test_pkg_config_libdir(self): + testdir = os.path.join(self.unit_test_dir, + '46 native dep pkgconfig var') + with tempfile.NamedTemporaryFile(mode='w', delete=False) as crossfile: + crossfile.write(textwrap.dedent( + '''[binaries] + pkgconfig = 'pkg-config' + + [properties] + pkg_config_libdir = ['{}'] + + [host_machine] + system = 'linux' + cpu_family = 'arm' + cpu = 'armv7' + endian = 'little' + '''.format(os.path.join(testdir, 'cross_pkgconfig')))) + crossfile.flush() + self.meson_cross_files = [crossfile.name] + + env = {'PKG_CONFIG_LIBDIR': os.path.join(testdir, + 'native_pkgconfig')} + self.init(testdir, extra_args=['-Dstart_native=false'], override_envvars=env) + self.wipe() + self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env) + + def __reconfigure(self): + # Set an older version to force a reconfigure from scratch + filename = os.path.join(self.privatedir, 'coredata.dat') + with open(filename, 'rb') as f: + obj = pickle.load(f) + obj.version = '0.47.0' + with open(filename, 'wb') as f: + pickle.dump(obj, f) + + def test_reconfigure(self): + testdir = os.path.join(self.unit_test_dir, '48 reconfigure') + self.init(testdir, extra_args=['-Dopt1=val1', '-Dsub1:werror=true']) + self.setconf('-Dopt2=val2') + + self.__reconfigure() + + out = self.init(testdir, extra_args=['--reconfigure', '-Dopt3=val3']) + self.assertRegex(out, 'Regenerating configuration from scratch') + self.assertRegex(out, 'opt1 val1') + self.assertRegex(out, 'opt2 val2') + self.assertRegex(out, 'opt3 val3') + self.assertRegex(out, 'opt4 default4') + self.assertRegex(out, 'sub1:werror true') + self.build() + self.run_tests() + + # Create a file in builddir and verify wipe command removes it + filename = os.path.join(self.builddir, 'something') + open(filename, 'w', encoding='utf-8').close() + self.assertTrue(os.path.exists(filename)) + out = self.init(testdir, extra_args=['--wipe', '-Dopt4=val4']) + self.assertFalse(os.path.exists(filename)) + self.assertRegex(out, 'opt1 val1') + self.assertRegex(out, 'opt2 val2') + self.assertRegex(out, 'opt3 val3') + self.assertRegex(out, 'opt4 val4') + self.assertRegex(out, 'sub1:werror true') + self.assertTrue(Path(self.builddir, '.gitignore').exists()) + self.build() + self.run_tests() + + def test_wipe_from_builddir(self): + testdir = os.path.join(self.common_test_dir, '157 custom target subdir depend files') + self.init(testdir) + self.__reconfigure() + self.init(testdir, extra_args=['--wipe'], workdir=self.builddir) + + def test_target_construct_id_from_path(self): + # This id is stable but not guessable. + # The test is supposed to prevent unintentional + # changes of target ID generation. + target_id = Target.construct_id_from_path('some/obscure/subdir', + 'target-id', '@suffix') + self.assertEqual('5e002d3@@target-id@suffix', target_id) + target_id = Target.construct_id_from_path('subproject/foo/subdir/bar', + 'target2-id', '@other') + self.assertEqual('81d46d1@@target2-id@other', target_id) + + def test_introspect_projectinfo_without_configured_build(self): + testfile = os.path.join(self.common_test_dir, '33 run program', 'meson.build') + res = self.introspect_directory(testfile, '--projectinfo') + self.assertEqual(set(res['buildsystem_files']), {'meson.build'}) + self.assertEqual(res['version'], 'undefined') + self.assertEqual(res['descriptive_name'], 'run command') + self.assertEqual(res['subprojects'], []) + + testfile = os.path.join(self.common_test_dir, '40 options', 'meson.build') + res = self.introspect_directory(testfile, '--projectinfo') + self.assertEqual(set(res['buildsystem_files']), {'meson_options.txt', 'meson.build'}) + self.assertEqual(res['version'], 'undefined') + self.assertEqual(res['descriptive_name'], 'options') + self.assertEqual(res['subprojects'], []) + + testfile = os.path.join(self.common_test_dir, '43 subproject options', 'meson.build') + res = self.introspect_directory(testfile, '--projectinfo') + self.assertEqual(set(res['buildsystem_files']), {'meson_options.txt', 'meson.build'}) + self.assertEqual(res['version'], 'undefined') + self.assertEqual(res['descriptive_name'], 'suboptions') + self.assertEqual(len(res['subprojects']), 1) + subproject_files = {f.replace('\\', '/') for f in res['subprojects'][0]['buildsystem_files']} + self.assertEqual(subproject_files, {'subprojects/subproject/meson_options.txt', 'subprojects/subproject/meson.build'}) + self.assertEqual(res['subprojects'][0]['name'], 'subproject') + self.assertEqual(res['subprojects'][0]['version'], 'undefined') + self.assertEqual(res['subprojects'][0]['descriptive_name'], 'subproject') + + def test_introspect_projectinfo_subprojects(self): + testdir = os.path.join(self.common_test_dir, '98 subproject subdir') + self.init(testdir) + res = self.introspect('--projectinfo') + expected = { + 'descriptive_name': 'proj', + 'version': 'undefined', + 'subproject_dir': 'subprojects', + 'subprojects': [ + { + 'descriptive_name': 'sub', + 'name': 'sub', + 'version': '1.0' + }, + { + 'descriptive_name': 'sub_implicit', + 'name': 'sub_implicit', + 'version': '1.0', + }, + { + 'descriptive_name': 'sub-novar', + 'name': 'sub_novar', + 'version': '1.0', + }, + { + 'descriptive_name': 'sub_static', + 'name': 'sub_static', + 'version': 'undefined' + }, + { + 'descriptive_name': 'subsub', + 'name': 'subsub', + 'version': 'undefined' + }, + { + 'descriptive_name': 'subsubsub', + 'name': 'subsubsub', + 'version': 'undefined' + }, + ] + } + res['subprojects'] = sorted(res['subprojects'], key=lambda i: i['name']) + self.assertDictEqual(expected, res) + + def test_introspection_target_subproject(self): + testdir = os.path.join(self.common_test_dir, '42 subproject') + self.init(testdir) + res = self.introspect('--targets') + + expected = { + 'sublib': 'sublib', + 'simpletest': 'sublib', + 'user': None + } + + for entry in res: + name = entry['name'] + self.assertEqual(entry['subproject'], expected[name]) + + def test_introspect_projectinfo_subproject_dir(self): + testdir = os.path.join(self.common_test_dir, '75 custom subproject dir') + self.init(testdir) + res = self.introspect('--projectinfo') + + self.assertEqual(res['subproject_dir'], 'custom_subproject_dir') + + def test_introspect_projectinfo_subproject_dir_from_source(self): + testfile = os.path.join(self.common_test_dir, '75 custom subproject dir', 'meson.build') + res = self.introspect_directory(testfile, '--projectinfo') + + self.assertEqual(res['subproject_dir'], 'custom_subproject_dir') + + @skipIfNoExecutable('clang-format') + def test_clang_format(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Clang-format is for now only supported on Ninja, not {self.backend.name}') + testdir = os.path.join(self.unit_test_dir, '54 clang-format') + + # Ensure that test project is in git even when running meson from tarball. + srcdir = os.path.join(self.builddir, 'src') + shutil.copytree(testdir, srcdir) + _git_init(srcdir) + testdir = srcdir + self.new_builddir() + + testfile = os.path.join(testdir, 'prog.c') + badfile = os.path.join(testdir, 'prog_orig_c') + goodfile = os.path.join(testdir, 'prog_expected_c') + testheader = os.path.join(testdir, 'header.h') + badheader = os.path.join(testdir, 'header_orig_h') + goodheader = os.path.join(testdir, 'header_expected_h') + includefile = os.path.join(testdir, '.clang-format-include') + try: + shutil.copyfile(badfile, testfile) + shutil.copyfile(badheader, testheader) + self.init(testdir) + self.assertNotEqual(Path(testfile).read_text(encoding='utf-8'), + Path(goodfile).read_text(encoding='utf-8')) + self.assertNotEqual(Path(testheader).read_text(encoding='utf-8'), + Path(goodheader).read_text(encoding='utf-8')) + + # test files are not in git so this should do nothing + self.run_target('clang-format') + self.assertNotEqual(Path(testfile).read_text(encoding='utf-8'), + Path(goodfile).read_text(encoding='utf-8')) + self.assertNotEqual(Path(testheader).read_text(encoding='utf-8'), + Path(goodheader).read_text(encoding='utf-8')) + + # Add an include file to reformat everything + with open(includefile, 'w', encoding='utf-8') as f: + f.write('*') + self.run_target('clang-format') + self.assertEqual(Path(testheader).read_text(encoding='utf-8'), + Path(goodheader).read_text(encoding='utf-8')) + finally: + if os.path.exists(testfile): + os.unlink(testfile) + if os.path.exists(testheader): + os.unlink(testheader) + if os.path.exists(includefile): + os.unlink(includefile) + + @skipIfNoExecutable('clang-tidy') + def test_clang_tidy(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Clang-tidy is for now only supported on Ninja, not {self.backend.name}') + if shutil.which('c++') is None: + raise SkipTest('Clang-tidy breaks when ccache is used and "c++" not in path.') + if is_osx(): + raise SkipTest('Apple ships a broken clang-tidy that chokes on -pipe.') + testdir = os.path.join(self.unit_test_dir, '69 clang-tidy') + dummydir = os.path.join(testdir, 'dummydir.h') + self.init(testdir, override_envvars={'CXX': 'c++'}) + out = self.run_target('clang-tidy') + self.assertIn('cttest.cpp:4:20', out) + self.assertNotIn(dummydir, out) + + def test_identity_cross(self): + testdir = os.path.join(self.unit_test_dir, '70 cross') + # Do a build to generate a cross file where the host is this target + self.init(testdir, extra_args=['-Dgenerate=true']) + self.meson_cross_files = [os.path.join(self.builddir, "crossfile")] + self.assertTrue(os.path.exists(self.meson_cross_files[0])) + # Now verify that this is detected as cross + self.new_builddir() + self.init(testdir) + + def test_introspect_buildoptions_without_configured_build(self): + testdir = os.path.join(self.unit_test_dir, '59 introspect buildoptions') + testfile = os.path.join(testdir, 'meson.build') + res_nb = self.introspect_directory(testfile, ['--buildoptions'] + self.meson_args) + self.init(testdir, default_args=False) + res_wb = self.introspect('--buildoptions') + self.maxDiff = None + # XXX: These now generate in a different order, is that okay? + self.assertListEqual(sorted(res_nb, key=lambda x: x['name']), sorted(res_wb, key=lambda x: x['name'])) + + def test_meson_configure_from_source_does_not_crash(self): + testdir = os.path.join(self.unit_test_dir, '59 introspect buildoptions') + self._run(self.mconf_command + [testdir]) + + def test_introspect_buildoptions_cross_only(self): + testdir = os.path.join(self.unit_test_dir, '83 cross only introspect') + testfile = os.path.join(testdir, 'meson.build') + res = self.introspect_directory(testfile, ['--buildoptions'] + self.meson_args) + optnames = [o['name'] for o in res] + self.assertIn('c_args', optnames) + self.assertNotIn('build.c_args', optnames) + + def test_introspect_json_flat(self): + testdir = os.path.join(self.unit_test_dir, '57 introspection') + self.init(testdir, extra_args=['-Dlayout=flat']) + infodir = os.path.join(self.builddir, 'meson-info') + self.assertPathExists(infodir) + + with open(os.path.join(infodir, 'intro-targets.json'), encoding='utf-8') as fp: + targets = json.load(fp) + + for i in targets: + for out in i['filename']: + assert os.path.relpath(out, self.builddir).startswith('meson-out') + + def test_introspect_json_dump(self): + testdir = os.path.join(self.unit_test_dir, '57 introspection') + self.init(testdir) + infodir = os.path.join(self.builddir, 'meson-info') + self.assertPathExists(infodir) + + def assertKeyTypes(key_type_list, obj, strict: bool = True): + for i in key_type_list: + if isinstance(i[1], (list, tuple)) and None in i[1]: + i = (i[0], tuple(x for x in i[1] if x is not None)) + if i[0] not in obj or obj[i[0]] is None: + continue + self.assertIn(i[0], obj) + self.assertIsInstance(obj[i[0]], i[1]) + if strict: + for k in obj.keys(): + found = False + for i in key_type_list: + if k == i[0]: + found = True + break + self.assertTrue(found, f'Key "{k}" not in expected list') + + root_keylist = [ + ('benchmarks', list), + ('buildoptions', list), + ('buildsystem_files', list), + ('dependencies', list), + ('installed', dict), + ('projectinfo', dict), + ('targets', list), + ('tests', list), + ] + + test_keylist = [ + ('cmd', list), + ('env', dict), + ('name', str), + ('timeout', int), + ('suite', list), + ('is_parallel', bool), + ('protocol', str), + ('depends', list), + ('workdir', (str, None)), + ('priority', int), + ] + + buildoptions_keylist = [ + ('name', str), + ('section', str), + ('type', str), + ('description', str), + ('machine', str), + ('choices', (list, None)), + ('value', (str, int, bool, list)), + ] + + buildoptions_typelist = [ + ('combo', str, [('choices', list)]), + ('string', str, []), + ('boolean', bool, []), + ('integer', int, []), + ('array', list, []), + ] + + buildoptions_sections = ['core', 'backend', 'base', 'compiler', 'directory', 'user', 'test'] + buildoptions_machines = ['any', 'build', 'host'] + + dependencies_typelist = [ + ('name', str), + ('version', str), + ('compile_args', list), + ('link_args', list), + ] + + targets_typelist = [ + ('name', str), + ('id', str), + ('type', str), + ('defined_in', str), + ('filename', list), + ('build_by_default', bool), + ('target_sources', list), + ('extra_files', list), + ('subproject', (str, None)), + ('install_filename', (list, None)), + ('installed', bool), + ] + + targets_sources_typelist = [ + ('language', str), + ('compiler', list), + ('parameters', list), + ('sources', list), + ('generated_sources', list), + ] + + # First load all files + res = {} + for i in root_keylist: + curr = os.path.join(infodir, 'intro-{}.json'.format(i[0])) + self.assertPathExists(curr) + with open(curr, encoding='utf-8') as fp: + res[i[0]] = json.load(fp) + + assertKeyTypes(root_keylist, res) + + # Match target ids to input and output files for ease of reference + src_to_id = {} + out_to_id = {} + name_to_out = {} + for i in res['targets']: + print(json.dump(i, sys.stdout)) + out_to_id.update({os.path.relpath(out, self.builddir): i['id'] + for out in i['filename']}) + name_to_out.update({i['name']: i['filename']}) + for group in i['target_sources']: + src_to_id.update({os.path.relpath(src, testdir): i['id'] + for src in group['sources']}) + + # Check Tests and benchmarks + tests_to_find = ['test case 1', 'test case 2', 'benchmark 1'] + deps_to_find = {'test case 1': [src_to_id['t1.cpp']], + 'test case 2': [src_to_id['t2.cpp'], src_to_id['t3.cpp']], + 'benchmark 1': [out_to_id['file2'], out_to_id['file3'], out_to_id['file4'], src_to_id['t3.cpp']]} + for i in res['benchmarks'] + res['tests']: + assertKeyTypes(test_keylist, i) + if i['name'] in tests_to_find: + tests_to_find.remove(i['name']) + self.assertEqual(sorted(i['depends']), + sorted(deps_to_find[i['name']])) + self.assertListEqual(tests_to_find, []) + + # Check buildoptions + buildopts_to_find = {'cpp_std': 'c++11'} + for i in res['buildoptions']: + assertKeyTypes(buildoptions_keylist, i) + valid_type = False + for j in buildoptions_typelist: + if i['type'] == j[0]: + self.assertIsInstance(i['value'], j[1]) + assertKeyTypes(j[2], i, strict=False) + valid_type = True + break + + self.assertIn(i['section'], buildoptions_sections) + self.assertIn(i['machine'], buildoptions_machines) + self.assertTrue(valid_type) + if i['name'] in buildopts_to_find: + self.assertEqual(i['value'], buildopts_to_find[i['name']]) + buildopts_to_find.pop(i['name'], None) + self.assertDictEqual(buildopts_to_find, {}) + + # Check buildsystem_files + bs_files = ['meson.build', 'meson_options.txt', 'sharedlib/meson.build', 'staticlib/meson.build'] + bs_files = [os.path.join(testdir, x) for x in bs_files] + self.assertPathListEqual(list(sorted(res['buildsystem_files'])), list(sorted(bs_files))) + + # Check dependencies + dependencies_to_find = ['threads'] + for i in res['dependencies']: + assertKeyTypes(dependencies_typelist, i) + if i['name'] in dependencies_to_find: + dependencies_to_find.remove(i['name']) + self.assertListEqual(dependencies_to_find, []) + + # Check projectinfo + self.assertDictEqual(res['projectinfo'], {'version': '1.2.3', 'descriptive_name': 'introspection', 'subproject_dir': 'subprojects', 'subprojects': []}) + + # Check targets + targets_to_find = { + 'sharedTestLib': ('shared library', True, False, 'sharedlib/meson.build', + [os.path.join(testdir, 'sharedlib', 'shared.cpp')]), + 'staticTestLib': ('static library', True, False, 'staticlib/meson.build', + [os.path.join(testdir, 'staticlib', 'static.c')]), + 'custom target test 1': ('custom', False, False, 'meson.build', + [os.path.join(testdir, 'cp.py')]), + 'custom target test 2': ('custom', False, False, 'meson.build', + name_to_out['custom target test 1']), + 'test1': ('executable', True, True, 'meson.build', + [os.path.join(testdir, 't1.cpp')]), + 'test2': ('executable', True, False, 'meson.build', + [os.path.join(testdir, 't2.cpp')]), + 'test3': ('executable', True, False, 'meson.build', + [os.path.join(testdir, 't3.cpp')]), + 'custom target test 3': ('custom', False, False, 'meson.build', + name_to_out['test3']), + } + for i in res['targets']: + assertKeyTypes(targets_typelist, i) + if i['name'] in targets_to_find: + tgt = targets_to_find[i['name']] + self.assertEqual(i['type'], tgt[0]) + self.assertEqual(i['build_by_default'], tgt[1]) + self.assertEqual(i['installed'], tgt[2]) + self.assertPathEqual(i['defined_in'], os.path.join(testdir, tgt[3])) + targets_to_find.pop(i['name'], None) + for j in i['target_sources']: + assertKeyTypes(targets_sources_typelist, j) + self.assertEqual(j['sources'], [os.path.normpath(f) for f in tgt[4]]) + self.assertDictEqual(targets_to_find, {}) + + def test_introspect_file_dump_equals_all(self): + testdir = os.path.join(self.unit_test_dir, '57 introspection') + self.init(testdir) + res_all = self.introspect('--all') + res_file = {} + + root_keylist = [ + 'benchmarks', + 'buildoptions', + 'buildsystem_files', + 'dependencies', + 'installed', + 'install_plan', + 'projectinfo', + 'targets', + 'tests', + ] + + infodir = os.path.join(self.builddir, 'meson-info') + self.assertPathExists(infodir) + for i in root_keylist: + curr = os.path.join(infodir, f'intro-{i}.json') + self.assertPathExists(curr) + with open(curr, encoding='utf-8') as fp: + res_file[i] = json.load(fp) + + self.assertEqual(res_all, res_file) + + def test_introspect_meson_info(self): + testdir = os.path.join(self.unit_test_dir, '57 introspection') + introfile = os.path.join(self.builddir, 'meson-info', 'meson-info.json') + self.init(testdir) + self.assertPathExists(introfile) + with open(introfile, encoding='utf-8') as fp: + res1 = json.load(fp) + + for i in ['meson_version', 'directories', 'introspection', 'build_files_updated', 'error']: + self.assertIn(i, res1) + + self.assertEqual(res1['error'], False) + self.assertEqual(res1['build_files_updated'], True) + + def test_introspect_config_update(self): + testdir = os.path.join(self.unit_test_dir, '57 introspection') + introfile = os.path.join(self.builddir, 'meson-info', 'intro-buildoptions.json') + self.init(testdir) + self.assertPathExists(introfile) + with open(introfile, encoding='utf-8') as fp: + res1 = json.load(fp) + + for i in res1: + if i['name'] == 'cpp_std': + i['value'] = 'c++14' + if i['name'] == 'build.cpp_std': + i['value'] = 'c++14' + if i['name'] == 'buildtype': + i['value'] = 'release' + if i['name'] == 'optimization': + i['value'] = '3' + if i['name'] == 'debug': + i['value'] = False + + self.setconf('-Dcpp_std=c++14') + self.setconf('-Dbuildtype=release') + + with open(introfile, encoding='utf-8') as fp: + res2 = json.load(fp) + + self.assertListEqual(res1, res2) + + def test_introspect_targets_from_source(self): + testdir = os.path.join(self.unit_test_dir, '57 introspection') + testfile = os.path.join(testdir, 'meson.build') + introfile = os.path.join(self.builddir, 'meson-info', 'intro-targets.json') + self.init(testdir) + self.assertPathExists(introfile) + with open(introfile, encoding='utf-8') as fp: + res_wb = json.load(fp) + + res_nb = self.introspect_directory(testfile, ['--targets'] + self.meson_args) + + # Account for differences in output + res_wb = [i for i in res_wb if i['type'] != 'custom'] + for i in res_wb: + i['filename'] = [os.path.relpath(x, self.builddir) for x in i['filename']] + if 'install_filename' in i: + del i['install_filename'] + + sources = [] + for j in i['target_sources']: + sources += j['sources'] + i['target_sources'] = [{ + 'language': 'unknown', + 'compiler': [], + 'parameters': [], + 'sources': sources, + 'generated_sources': [] + }] + + self.maxDiff = None + self.assertListEqual(res_nb, res_wb) + + def test_introspect_ast_source(self): + testdir = os.path.join(self.unit_test_dir, '57 introspection') + testfile = os.path.join(testdir, 'meson.build') + res_nb = self.introspect_directory(testfile, ['--ast'] + self.meson_args) + + node_counter = {} + + def accept_node(json_node): + self.assertIsInstance(json_node, dict) + for i in ['lineno', 'colno', 'end_lineno', 'end_colno']: + self.assertIn(i, json_node) + self.assertIsInstance(json_node[i], int) + self.assertIn('node', json_node) + n = json_node['node'] + self.assertIsInstance(n, str) + self.assertIn(n, nodes) + if n not in node_counter: + node_counter[n] = 0 + node_counter[n] = node_counter[n] + 1 + for nodeDesc in nodes[n]: + key = nodeDesc[0] + func = nodeDesc[1] + self.assertIn(key, json_node) + if func is None: + tp = nodeDesc[2] + self.assertIsInstance(json_node[key], tp) + continue + func(json_node[key]) + + def accept_node_list(node_list): + self.assertIsInstance(node_list, list) + for i in node_list: + accept_node(i) + + def accept_kwargs(kwargs): + self.assertIsInstance(kwargs, list) + for i in kwargs: + self.assertIn('key', i) + self.assertIn('val', i) + accept_node(i['key']) + accept_node(i['val']) + + nodes = { + 'BooleanNode': [('value', None, bool)], + 'IdNode': [('value', None, str)], + 'NumberNode': [('value', None, int)], + 'StringNode': [('value', None, str)], + 'FormatStringNode': [('value', None, str)], + 'ContinueNode': [], + 'BreakNode': [], + 'ArgumentNode': [('positional', accept_node_list), ('kwargs', accept_kwargs)], + 'ArrayNode': [('args', accept_node)], + 'DictNode': [('args', accept_node)], + 'EmptyNode': [], + 'OrNode': [('left', accept_node), ('right', accept_node)], + 'AndNode': [('left', accept_node), ('right', accept_node)], + 'ComparisonNode': [('left', accept_node), ('right', accept_node), ('ctype', None, str)], + 'ArithmeticNode': [('left', accept_node), ('right', accept_node), ('op', None, str)], + 'NotNode': [('right', accept_node)], + 'CodeBlockNode': [('lines', accept_node_list)], + 'IndexNode': [('object', accept_node), ('index', accept_node)], + 'MethodNode': [('object', accept_node), ('args', accept_node), ('name', None, str)], + 'FunctionNode': [('args', accept_node), ('name', None, str)], + 'AssignmentNode': [('value', accept_node), ('var_name', None, str)], + 'PlusAssignmentNode': [('value', accept_node), ('var_name', None, str)], + 'ForeachClauseNode': [('items', accept_node), ('block', accept_node), ('varnames', None, list)], + 'IfClauseNode': [('ifs', accept_node_list), ('else', accept_node)], + 'IfNode': [('condition', accept_node), ('block', accept_node)], + 'UMinusNode': [('right', accept_node)], + 'TernaryNode': [('condition', accept_node), ('true', accept_node), ('false', accept_node)], + } + + accept_node(res_nb) + + for n, c in [('ContinueNode', 2), ('BreakNode', 1), ('NotNode', 3)]: + self.assertIn(n, node_counter) + self.assertEqual(node_counter[n], c) + + def test_introspect_dependencies_from_source(self): + testdir = os.path.join(self.unit_test_dir, '57 introspection') + testfile = os.path.join(testdir, 'meson.build') + res_nb = self.introspect_directory(testfile, ['--scan-dependencies'] + self.meson_args) + expected = [ + { + 'name': 'threads', + 'required': True, + 'version': [], + 'has_fallback': False, + 'conditional': False + }, + { + 'name': 'zlib', + 'required': False, + 'version': [], + 'has_fallback': False, + 'conditional': False + }, + { + 'name': 'bugDep1', + 'required': True, + 'version': [], + 'has_fallback': False, + 'conditional': False + }, + { + 'name': 'somethingthatdoesnotexist', + 'required': True, + 'version': ['>=1.2.3'], + 'has_fallback': False, + 'conditional': True + }, + { + 'name': 'look_i_have_a_fallback', + 'required': True, + 'version': ['>=1.0.0', '<=99.9.9'], + 'has_fallback': True, + 'conditional': True + } + ] + self.maxDiff = None + self.assertListEqual(res_nb, expected) + + def test_unstable_coredata(self): + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + # just test that the command does not fail (e.g. because it throws an exception) + self._run([*self.meson_command, 'unstable-coredata', self.builddir]) + + @skip_if_no_cmake + def test_cmake_prefix_path(self): + testdir = os.path.join(self.unit_test_dir, '63 cmake_prefix_path') + self.init(testdir, extra_args=['-Dcmake_prefix_path=' + os.path.join(testdir, 'prefix')]) + + @skip_if_no_cmake + def test_cmake_parser(self): + testdir = os.path.join(self.unit_test_dir, '64 cmake parser') + self.init(testdir, extra_args=['-Dcmake_prefix_path=' + os.path.join(testdir, 'prefix')]) + + def test_alias_target(self): + testdir = os.path.join(self.unit_test_dir, '65 alias target') + self.init(testdir) + self.build() + self.assertPathDoesNotExist(os.path.join(self.builddir, 'prog' + exe_suffix)) + self.assertPathDoesNotExist(os.path.join(self.builddir, 'hello.txt')) + self.run_target('build-all') + self.assertPathExists(os.path.join(self.builddir, 'prog' + exe_suffix)) + self.assertPathExists(os.path.join(self.builddir, 'hello.txt')) + out = self.run_target('aliased-run') + self.assertIn('a run target was here', out) + + def test_configure(self): + testdir = os.path.join(self.common_test_dir, '2 cpp') + self.init(testdir) + self._run(self.mconf_command + [self.builddir]) + + def test_summary(self): + testdir = os.path.join(self.unit_test_dir, '72 summary') + out = self.init(testdir, extra_args=['-Denabled_opt=enabled']) + expected = textwrap.dedent(r''' + Some Subproject 2.0 + + string : bar + integer: 1 + boolean: True + + subsub undefined + + Something: Some value + + My Project 1.0 + + Configuration + Some boolean : False + Another boolean: True + Some string : Hello World + A list : string + 1 + True + empty list : + enabled_opt : enabled + A number : 1 + yes : YES + no : NO + coma list : a, b, c + + Stuff + missing prog : NO + existing prog : ''' + sys.executable + ''' + missing dep : NO + external dep : YES 1.2.3 + internal dep : YES + + Plugins + long coma list : alpha, alphacolor, apetag, audiofx, audioparsers, auparse, + autodetect, avi + + Subprojects + sub : YES + sub2 : NO Problem encountered: This subproject failed + subsub : YES + + User defined options + backend : ''' + self.backend.name + ''' + libdir : lib + prefix : /usr + enabled_opt : enabled + ''') + 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)$') + else: + self.assertEqual(o, e) + + def test_meson_compile(self): + """Test the meson compile command.""" + + def get_exe_name(basename: str) -> str: + if is_windows(): + return f'{basename}.exe' + else: + return basename + + def get_shared_lib_name(basename: str) -> str: + if mesonbuild.environment.detect_msys2_arch(): + return f'lib{basename}.dll' + elif is_windows(): + return f'{basename}.dll' + elif is_cygwin(): + return f'cyg{basename}.dll' + elif is_osx(): + return f'lib{basename}.dylib' + else: + return f'lib{basename}.so' + + def get_static_lib_name(basename: str) -> str: + return f'lib{basename}.a' + + # Base case (no targets or additional arguments) + + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + + self._run([*self.meson_command, 'compile', '-C', self.builddir]) + self.assertPathExists(os.path.join(self.builddir, get_exe_name('trivialprog'))) + + # `--clean` + + self._run([*self.meson_command, 'compile', '-C', self.builddir, '--clean']) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('trivialprog'))) + + # Target specified in a project with unique names + + testdir = os.path.join(self.common_test_dir, '6 linkshared') + self.init(testdir, extra_args=['--wipe']) + # Multiple targets and target type specified + self._run([*self.meson_command, 'compile', '-C', self.builddir, 'mylib', 'mycpplib:shared_library']) + # Check that we have a shared lib, but not an executable, i.e. check that target actually worked + self.assertPathExists(os.path.join(self.builddir, get_shared_lib_name('mylib'))) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('prog'))) + self.assertPathExists(os.path.join(self.builddir, get_shared_lib_name('mycpplib'))) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('cppprog'))) + + # Target specified in a project with non unique names + + testdir = os.path.join(self.common_test_dir, '185 same target name') + self.init(testdir, extra_args=['--wipe']) + self._run([*self.meson_command, 'compile', '-C', self.builddir, './foo']) + self.assertPathExists(os.path.join(self.builddir, get_static_lib_name('foo'))) + self._run([*self.meson_command, 'compile', '-C', self.builddir, 'sub/foo']) + self.assertPathExists(os.path.join(self.builddir, 'sub', get_static_lib_name('foo'))) + + # run_target + + testdir = os.path.join(self.common_test_dir, '51 run target') + self.init(testdir, extra_args=['--wipe']) + out = self._run([*self.meson_command, 'compile', '-C', self.builddir, 'py3hi']) + self.assertIn('I am Python3.', out) + + # `--$BACKEND-args` + + testdir = os.path.join(self.common_test_dir, '1 trivial') + if self.backend is Backend.ninja: + self.init(testdir, extra_args=['--wipe']) + # Dry run - should not create a program + self._run([*self.meson_command, 'compile', '-C', self.builddir, '--ninja-args=-n']) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('trivialprog'))) + elif self.backend is Backend.vs: + self.init(testdir, extra_args=['--wipe']) + self._run([*self.meson_command, 'compile', '-C', self.builddir]) + # Explicitly clean the target through msbuild interface + self._run([*self.meson_command, 'compile', '-C', self.builddir, '--vs-args=-t:{}:Clean'.format(re.sub(r'[\%\$\@\;\.\(\)\']', '_', get_exe_name('trivialprog')))]) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('trivialprog'))) + + def test_spurious_reconfigure_built_dep_file(self): + testdir = os.path.join(self.unit_test_dir, '74 dep files') + + # Regression test: Spurious reconfigure was happening when build + # directory is inside source directory. + # See https://gitlab.freedesktop.org/gstreamer/gst-build/-/issues/85. + srcdir = os.path.join(self.builddir, 'srctree') + shutil.copytree(testdir, srcdir) + builddir = os.path.join(srcdir, '_build') + self.change_builddir(builddir) + + self.init(srcdir) + self.build() + + # During first configure the file did not exist so no dependency should + # have been set. A rebuild should not trigger a reconfigure. + self.clean() + out = self.build() + self.assertNotIn('Project configured', out) + + self.init(srcdir, extra_args=['--reconfigure']) + + # During the reconfigure the file did exist, but is inside build + # directory, so no dependency should have been set. A rebuild should not + # trigger a reconfigure. + self.clean() + out = self.build() + self.assertNotIn('Project configured', out) + + def _test_junit(self, case: str) -> None: + try: + import lxml.etree as et + except ImportError: + raise SkipTest('lxml required, but not found.') + + schema = et.XMLSchema(et.parse(str(Path(self.src_root) / 'data' / 'schema.xsd'))) + + self.init(case) + self.run_tests() + + junit = et.parse(str(Path(self.builddir) / 'meson-logs' / 'testlog.junit.xml')) + try: + schema.assertValid(junit) + except et.DocumentInvalid as e: + self.fail(e.error_log) + + def test_junit_valid_tap(self): + self._test_junit(os.path.join(self.common_test_dir, '206 tap tests')) + + def test_junit_valid_exitcode(self): + self._test_junit(os.path.join(self.common_test_dir, '41 test args')) + + def test_junit_valid_gtest(self): + self._test_junit(os.path.join(self.framework_test_dir, '2 gtest')) + + def test_link_language_linker(self): + # TODO: there should be some way to query how we're linking things + # without resorting to reading the ninja.build file + if self.backend is not Backend.ninja: + raise SkipTest('This test reads the ninja file') + + testdir = os.path.join(self.common_test_dir, '225 link language') + self.init(testdir) + + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + + self.assertRegex(contents, r'build main(\.exe)?.*: c_LINKER') + self.assertRegex(contents, r'build (lib|cyg)?mylib.*: c_LINKER') + + def test_commands_documented(self): + ''' + Test that all listed meson commands are documented in Commands.md. + ''' + + # The docs directory is not in release tarballs. + if not os.path.isdir('docs'): + raise SkipTest('Doc directory does not exist.') + doc_path = 'docs/markdown/Commands.md' + + md = None + with open(doc_path, encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + + ## Get command sections + + section_pattern = re.compile(r'^### (.+)$', re.MULTILINE) + md_command_section_matches = [i for i in section_pattern.finditer(md)] + md_command_sections = dict() + for i, s in enumerate(md_command_section_matches): + section_end = len(md) if i == len(md_command_section_matches) - 1 else md_command_section_matches[i + 1].start() + md_command_sections[s.group(1)] = (s.start(), section_end) + + ## Validate commands + + md_commands = {k for k,v in md_command_sections.items()} + + help_output = self._run(self.meson_command + ['--help']) + help_commands = {c.strip() for c in re.findall(r'usage:(?:.+)?{((?:[a-z]+,*)+?)}', help_output, re.MULTILINE|re.DOTALL)[0].split(',')} + + self.assertEqual(md_commands | {'help'}, help_commands, f'Doc file: `{doc_path}`') + + ## Validate that each section has proper placeholders + + def get_data_pattern(command): + return re.compile( + r'{{ ' + command + r'_usage.inc }}[\r\n]' + r'.*?' + r'{{ ' + command + r'_arguments.inc }}[\r\n]', + flags = re.MULTILINE|re.DOTALL) + + for command in md_commands: + m = get_data_pattern(command).search(md, pos=md_command_sections[command][0], endpos=md_command_sections[command][1]) + self.assertIsNotNone(m, f'Command `{command}` is missing placeholders for dynamic data. Doc file: `{doc_path}`') + + def _check_coverage_files(self, types=('text', 'xml', 'html')): + covdir = Path(self.builddir) / 'meson-logs' + files = [] + if 'text' in types: + files.append('coverage.txt') + if 'xml' in types: + files.append('coverage.xml') + if 'html' in types: + files.append('coveragereport/index.html') + for f in files: + self.assertTrue((covdir / f).is_file(), msg=f'{f} is not a file') + + def test_coverage(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage') + self._check_coverage_files() + + def test_coverage_complex(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '105 generatorcustom') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage') + self._check_coverage_files() + + def test_coverage_html(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-html') + self._check_coverage_files(['html']) + + def test_coverage_text(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-text') + self._check_coverage_files(['text']) + + def test_coverage_xml(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-xml') + self._check_coverage_files(['xml']) + + def test_coverage_escaping(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '243 escape++') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage') + self._check_coverage_files() + + def test_cross_file_constants(self): + with temp_filename() as crossfile1, temp_filename() as crossfile2: + with open(crossfile1, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + ''' + [constants] + compiler = 'gcc' + ''')) + with open(crossfile2, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + ''' + [constants] + toolchain = '/toolchain/' + common_flags = ['--sysroot=' + toolchain / 'sysroot'] + + [properties] + c_args = common_flags + ['-DSOMETHING'] + cpp_args = c_args + ['-DSOMETHING_ELSE'] + + [binaries] + c = toolchain / compiler + ''')) + + values = mesonbuild.coredata.parse_machine_files([crossfile1, crossfile2]) + self.assertEqual(values['binaries']['c'], '/toolchain/gcc') + self.assertEqual(values['properties']['c_args'], + ['--sysroot=/toolchain/sysroot', '-DSOMETHING']) + self.assertEqual(values['properties']['cpp_args'], + ['--sysroot=/toolchain/sysroot', '-DSOMETHING', '-DSOMETHING_ELSE']) + + @skipIf(is_windows(), 'Directory cleanup fails for some reason') + def test_wrap_git(self): + with tempfile.TemporaryDirectory() as tmpdir: + srcdir = os.path.join(tmpdir, 'src') + shutil.copytree(os.path.join(self.unit_test_dir, '81 wrap-git'), srcdir) + upstream = os.path.join(srcdir, 'subprojects', 'wrap_git_upstream') + upstream_uri = Path(upstream).as_uri() + _git_init(upstream) + with open(os.path.join(srcdir, 'subprojects', 'wrap_git.wrap'), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-git] + url = {} + patch_directory = wrap_git_builddef + revision = master + '''.format(upstream_uri))) + self.init(srcdir) + self.build() + self.run_tests() + + def test_extract_objects_custom_target_no_warning(self): + testdir = os.path.join(self.common_test_dir, '22 object extraction') + + out = self.init(testdir) + self.assertNotRegex(out, "WARNING:.*can't be converted to File object") + + def test_multi_output_custom_target_no_warning(self): + testdir = os.path.join(self.common_test_dir, '228 custom_target source') + + out = self.init(testdir) + self.assertNotRegex(out, 'WARNING:.*Using the first one.') + self.build() + self.run_tests() + + @skipUnless(is_linux() and (re.search('^i.86$|^x86$|^x64$|^x86_64$|^amd64$', platform.processor()) is not None), + 'Requires ASM compiler for x86 or x86_64 platform currently only available on Linux CI runners') + def test_nostdlib(self): + testdir = os.path.join(self.unit_test_dir, '78 nostdlib') + machinefile = os.path.join(self.builddir, 'machine.txt') + with open(machinefile, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [properties] + c_stdlib = 'mylibc' + ''')) + + # Test native C stdlib + self.meson_native_files = [machinefile] + self.init(testdir) + self.build() + + # Test cross C stdlib + self.new_builddir() + self.meson_native_files = [] + self.meson_cross_files = [machinefile] + self.init(testdir) + self.build() + + def test_meson_version_compare(self): + testdir = os.path.join(self.unit_test_dir, '82 meson version compare') + out = self.init(testdir) + self.assertNotRegex(out, r'WARNING') + + def test_wrap_redirect(self): + redirect_wrap = os.path.join(self.builddir, 'redirect.wrap') + real_wrap = os.path.join(self.builddir, 'foo/subprojects/real.wrap') + os.makedirs(os.path.dirname(real_wrap)) + + # Invalid redirect, filename must have .wrap extension + with open(redirect_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-redirect] + filename = foo/subprojects/real.wrapper + ''')) + with self.assertRaisesRegex(WrapException, 'wrap-redirect filename must be a .wrap file'): + PackageDefinition(redirect_wrap) + + # Invalid redirect, filename cannot be in parent directory + with open(redirect_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-redirect] + filename = ../real.wrap + ''')) + with self.assertRaisesRegex(WrapException, 'wrap-redirect filename cannot contain ".."'): + PackageDefinition(redirect_wrap) + + # Invalid redirect, filename must be in foo/subprojects/real.wrap + with open(redirect_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-redirect] + filename = foo/real.wrap + ''')) + with self.assertRaisesRegex(WrapException, 'wrap-redirect filename must be in the form foo/subprojects/bar.wrap'): + PackageDefinition(redirect_wrap) + + # Correct redirect + with open(redirect_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-redirect] + filename = foo/subprojects/real.wrap + ''')) + with open(real_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-git] + url = http://invalid + ''')) + wrap = PackageDefinition(redirect_wrap) + self.assertEqual(wrap.get('url'), 'http://invalid') + + @skip_if_no_cmake + def test_nested_cmake_rebuild(self) -> None: + # This checks a bug where if a non-meson project is used as a third + # level (or deeper) subproject it doesn't cause a rebuild if the build + # files for that project are changed + testdir = os.path.join(self.unit_test_dir, '85 nested subproject regenerate depends') + cmakefile = Path(testdir) / 'subprojects' / 'sub2' / 'CMakeLists.txt' + self.init(testdir) + self.build() + with cmakefile.open('a', encoding='utf-8'): + os.utime(str(cmakefile)) + self.assertReconfiguredBuildIsNoop() + + def test_version_file(self): + srcdir = os.path.join(self.common_test_dir, '2 cpp') + self.init(srcdir) + projinfo = self.introspect('--projectinfo') + self.assertEqual(projinfo['version'], '1.0.0') + + def test_cflags_cppflags(self): + envs = {'CPPFLAGS': '-DCPPFLAG', + 'CFLAGS': '-DCFLAG', + 'CXXFLAGS': '-DCXXFLAG'} + srcdir = os.path.join(self.unit_test_dir, '89 multiple envvars') + self.init(srcdir, override_envvars=envs) + self.build() + + def test_build_b_options(self) -> None: + # Currently (0.57) these do nothing, but they've always been allowed + srcdir = os.path.join(self.common_test_dir, '2 cpp') + self.init(srcdir, extra_args=['-Dbuild.b_lto=true']) + + def test_install_skip_subprojects(self): + testdir = os.path.join(self.unit_test_dir, '92 install skip subprojects') + self.init(testdir) + self.build() + + main_expected = [ + '', + 'share', + 'include', + 'foo', + 'bin', + 'share/foo', + 'share/foo/foo.dat', + 'include/foo.h', + 'foo/foofile', + 'bin/foo' + exe_suffix, + ] + bar_expected = [ + 'bar', + 'share/foo/bar.dat', + 'include/bar.h', + 'bin/bar' + exe_suffix, + 'bar/barfile' + ] + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() == 'msvc': + main_expected.append('bin/foo.pdb') + bar_expected.append('bin/bar.pdb') + prefix = destdir_join(self.installdir, self.prefix) + main_expected = [Path(prefix, p) for p in main_expected] + bar_expected = [Path(prefix, p) for p in bar_expected] + all_expected = main_expected + bar_expected + + def check_installed_files(extra_args, expected): + args = ['install', '--destdir', self.installdir] + extra_args + self._run(self.meson_command + args, workdir=self.builddir) + all_files = [p for p in Path(self.installdir).rglob('*')] + self.assertEqual(sorted(expected), sorted(all_files)) + windows_proof_rmtree(self.installdir) + + check_installed_files([], all_expected) + check_installed_files(['--skip-subprojects'], main_expected) + check_installed_files(['--skip-subprojects', 'bar'], main_expected) + check_installed_files(['--skip-subprojects', 'another'], all_expected) + + def test_adding_subproject_to_configure_project(self) -> None: + srcdir = os.path.join(self.unit_test_dir, '93 new subproject in configured project') + self.init(srcdir) + self.build() + self.setconf('-Duse-sub=true') + self.build() + + def test_devenv(self): + testdir = os.path.join(self.unit_test_dir, '91 devenv') + self.init(testdir) + self.build() + + cmd = self.meson_command + ['devenv', '-C', self.builddir] + script = os.path.join(testdir, 'test-devenv.py') + app = os.path.join(self.builddir, 'app') + self._run(cmd + python_command + [script]) + self.assertEqual('This is text.', self._run(cmd + [app]).strip()) + + def test_clang_format_check(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Skipping clang-format tests with {self.backend.name} backend') + if not shutil.which('clang-format'): + raise SkipTest('clang-format not found') + + testdir = os.path.join(self.unit_test_dir, '94 clangformat') + newdir = os.path.join(self.builddir, 'testdir') + shutil.copytree(testdir, newdir) + self.new_builddir() + self.init(newdir) + + # Should reformat 1 file but not return error + output = self.build('clang-format') + self.assertEqual(1, output.count('File reformatted:')) + + # Reset source tree then try again with clang-format-check, it should + # return an error code this time. + windows_proof_rmtree(newdir) + shutil.copytree(testdir, newdir) + with self.assertRaises(subprocess.CalledProcessError): + output = self.build('clang-format-check') + self.assertEqual(1, output.count('File reformatted:')) + + # The check format should not touch any files. Thus + # running format again has some work to do. + output = self.build('clang-format') + self.assertEqual(1, output.count('File reformatted:')) + self.build('clang-format-check') + + def test_custom_target_implicit_include(self): + testdir = os.path.join(self.unit_test_dir, '95 custominc') + self.init(testdir) + self.build() + compdb = self.get_compdb() + matches = 0 + for c in compdb: + if 'prog.c' in c['file']: + self.assertNotIn('easytogrepfor', c['command']) + matches += 1 + self.assertEqual(matches, 1) + matches = 0 + for c in compdb: + if 'prog2.c' in c['file']: + self.assertIn('easytogrepfor', c['command']) + matches += 1 + self.assertEqual(matches, 1) + + def test_env_flags_to_linker(self) -> None: + # Compilers that act as drivers should add their compiler flags to the + # linker, those that do not shouldn't + with mock.patch.dict(os.environ, {'CFLAGS': '-DCFLAG', 'LDFLAGS': '-flto'}): + env = get_fake_env() + + # Get the compiler so we know which compiler class to mock. + cc = detect_compiler_for(env, 'c', MachineChoice.HOST) + cc_type = type(cc) + + # Test a compiler that acts as a linker + with mock.patch.object(cc_type, 'INVOKES_LINKER', True): + cc = detect_compiler_for(env, 'c', MachineChoice.HOST) + link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language) + self.assertEqual(sorted(link_args), sorted(['-DCFLAG', '-flto'])) + + # And one that doesn't + with mock.patch.object(cc_type, 'INVOKES_LINKER', False): + cc = detect_compiler_for(env, 'c', MachineChoice.HOST) + link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language) + self.assertEqual(sorted(link_args), sorted(['-flto'])) + + def test_install_tag(self) -> None: + testdir = os.path.join(self.unit_test_dir, '99 install all targets') + self.init(testdir) + self.build() + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + + def shared_lib_name(name): + if cc.get_id() in {'msvc', 'clang-cl'}: + return f'bin/{name}.dll' + elif is_windows(): + return f'bin/lib{name}.dll' + elif is_cygwin(): + return f'bin/cyg{name}.dll' + elif is_osx(): + return f'lib/lib{name}.dylib' + return f'lib/lib{name}.so' + + def exe_name(name): + if is_windows() or is_cygwin(): + return f'{name}.exe' + return name + + installpath = Path(self.installdir) + + expected_common = { + installpath, + Path(installpath, 'usr'), + } + + expected_devel = expected_common | { + Path(installpath, 'usr/include'), + Path(installpath, 'usr/include/bar-devel.h'), + Path(installpath, 'usr/include/bar2-devel.h'), + Path(installpath, 'usr/include/foo1-devel.h'), + Path(installpath, 'usr/include/foo2-devel.h'), + Path(installpath, 'usr/include/foo3-devel.h'), + Path(installpath, 'usr/include/out-devel.h'), + Path(installpath, 'usr/lib'), + Path(installpath, 'usr/lib/libstatic.a'), + Path(installpath, 'usr/lib/libboth.a'), + Path(installpath, 'usr/lib/libboth2.a'), + } + + if cc.get_id() in {'msvc', 'clang-cl'}: + expected_devel |= { + Path(installpath, 'usr/bin'), + Path(installpath, 'usr/bin/app.pdb'), + Path(installpath, 'usr/bin/app2.pdb'), + Path(installpath, 'usr/bin/both.pdb'), + Path(installpath, 'usr/bin/both2.pdb'), + Path(installpath, 'usr/bin/bothcustom.pdb'), + Path(installpath, 'usr/bin/shared.pdb'), + Path(installpath, 'usr/lib/both.lib'), + Path(installpath, 'usr/lib/both2.lib'), + Path(installpath, 'usr/lib/bothcustom.lib'), + Path(installpath, 'usr/lib/shared.lib'), + } + elif is_windows() or is_cygwin(): + expected_devel |= { + Path(installpath, 'usr/lib/libboth.dll.a'), + Path(installpath, 'usr/lib/libboth2.dll.a'), + Path(installpath, 'usr/lib/libshared.dll.a'), + Path(installpath, 'usr/lib/libbothcustom.dll.a'), + } + + expected_runtime = expected_common | { + Path(installpath, 'usr/bin'), + Path(installpath, 'usr/bin/' + exe_name('app')), + Path(installpath, 'usr/bin/' + exe_name('app2')), + Path(installpath, 'usr/' + shared_lib_name('shared')), + Path(installpath, 'usr/' + shared_lib_name('both')), + Path(installpath, 'usr/' + shared_lib_name('both2')), + } + + expected_custom = expected_common | { + Path(installpath, 'usr/share'), + Path(installpath, 'usr/share/bar-custom.txt'), + Path(installpath, 'usr/share/foo-custom.h'), + Path(installpath, 'usr/share/out1-custom.txt'), + Path(installpath, 'usr/share/out2-custom.txt'), + Path(installpath, 'usr/share/out3-custom.txt'), + Path(installpath, 'usr/share/custom_files'), + Path(installpath, 'usr/share/custom_files/data.txt'), + Path(installpath, 'usr/lib'), + Path(installpath, 'usr/lib/libbothcustom.a'), + Path(installpath, 'usr/' + shared_lib_name('bothcustom')), + } + + if is_windows() or is_cygwin(): + expected_custom |= {Path(installpath, 'usr/bin')} + else: + expected_runtime |= {Path(installpath, 'usr/lib')} + + expected_runtime_custom = expected_runtime | expected_custom + + expected_all = expected_devel | expected_runtime | expected_custom | { + Path(installpath, 'usr/share/foo-notag.h'), + Path(installpath, 'usr/share/bar-notag.txt'), + Path(installpath, 'usr/share/out1-notag.txt'), + Path(installpath, 'usr/share/out2-notag.txt'), + Path(installpath, 'usr/share/out3-notag.txt'), + Path(installpath, 'usr/share/foo2.h'), + Path(installpath, 'usr/share/out1.txt'), + Path(installpath, 'usr/share/out2.txt'), + } + + def do_install(tags, expected_files, expected_scripts): + cmd = self.meson_command + ['install', '--dry-run', '--destdir', self.installdir] + cmd += ['--tags', tags] if tags else [] + stdout = self._run(cmd, workdir=self.builddir) + installed = self.read_install_logs() + self.assertEqual(sorted(expected_files), sorted(installed)) + self.assertEqual(expected_scripts, stdout.count('Running custom install script')) + + do_install('devel', expected_devel, 0) + do_install('runtime', expected_runtime, 0) + do_install('custom', expected_custom, 1) + do_install('runtime,custom', expected_runtime_custom, 1) + do_install(None, expected_all, 2) + + def test_introspect_install_plan(self): + 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) + with open(introfile, encoding='utf-8') as fp: + res = json.load(fp) + + env = get_fake_env(testdir, self.builddir, self.prefix) + + def output_name(name, type_): + return type_(name=name, subdir=None, subproject=None, + for_machine=MachineChoice.HOST, sources=[], + objects=[], environment=env, kwargs={}).filename + + shared_lib_name = lambda name: output_name(name, SharedLibrary) + static_lib_name = lambda name: output_name(name, StaticLibrary) + exe_name = lambda name: output_name(name, Executable) + + expected = { + 'targets': { + f'{self.builddir}/out1-notag.txt': { + 'destination': '{prefix}/share/out1-notag.txt', + 'tag': None, + }, + f'{self.builddir}/out2-notag.txt': { + 'destination': '{prefix}/share/out2-notag.txt', + 'tag': None, + }, + f'{self.builddir}/libstatic.a': { + 'destination': '{libdir_static}/libstatic.a', + 'tag': 'devel', + }, + f'{self.builddir}/' + exe_name('app'): { + 'destination': '{bindir}/' + exe_name('app'), + 'tag': 'runtime', + }, + f'{self.builddir}/subdir/' + exe_name('app2'): { + 'destination': '{bindir}/' + exe_name('app2'), + 'tag': 'runtime', + }, + f'{self.builddir}/' + shared_lib_name('shared'): { + 'destination': '{libdir_shared}/' + shared_lib_name('shared'), + 'tag': 'runtime', + }, + f'{self.builddir}/' + shared_lib_name('both'): { + 'destination': '{libdir_shared}/' + shared_lib_name('both'), + 'tag': 'runtime', + }, + f'{self.builddir}/' + static_lib_name('both'): { + 'destination': '{libdir_static}/' + static_lib_name('both'), + 'tag': 'devel', + }, + f'{self.builddir}/' + shared_lib_name('bothcustom'): { + 'destination': '{libdir_shared}/' + shared_lib_name('bothcustom'), + 'tag': 'custom', + }, + f'{self.builddir}/' + static_lib_name('bothcustom'): { + 'destination': '{libdir_static}/' + static_lib_name('bothcustom'), + 'tag': 'custom', + }, + f'{self.builddir}/subdir/' + shared_lib_name('both2'): { + 'destination': '{libdir_shared}/' + shared_lib_name('both2'), + 'tag': 'runtime', + }, + f'{self.builddir}/subdir/' + static_lib_name('both2'): { + 'destination': '{libdir_static}/' + static_lib_name('both2'), + 'tag': 'devel', + }, + f'{self.builddir}/out1-custom.txt': { + 'destination': '{prefix}/share/out1-custom.txt', + 'tag': 'custom', + }, + f'{self.builddir}/out2-custom.txt': { + 'destination': '{prefix}/share/out2-custom.txt', + 'tag': 'custom', + }, + f'{self.builddir}/out3-custom.txt': { + 'destination': '{prefix}/share/out3-custom.txt', + 'tag': 'custom', + }, + f'{self.builddir}/subdir/out1.txt': { + 'destination': '{prefix}/share/out1.txt', + 'tag': None, + }, + f'{self.builddir}/subdir/out2.txt': { + 'destination': '{prefix}/share/out2.txt', + 'tag': None, + }, + f'{self.builddir}/out-devel.h': { + 'destination': '{prefix}/include/out-devel.h', + 'tag': 'devel', + }, + f'{self.builddir}/out3-notag.txt': { + 'destination': '{prefix}/share/out3-notag.txt', + 'tag': None, + }, + }, + 'configure': { + f'{self.builddir}/foo-notag.h': { + 'destination': '{prefix}/share/foo-notag.h', + 'tag': None, + }, + f'{self.builddir}/foo2-devel.h': { + 'destination': '{prefix}/include/foo2-devel.h', + 'tag': 'devel', + }, + f'{self.builddir}/foo-custom.h': { + 'destination': '{prefix}/share/foo-custom.h', + 'tag': 'custom', + }, + f'{self.builddir}/subdir/foo2.h': { + 'destination': '{prefix}/share/foo2.h', + 'tag': None, + }, + }, + 'data': { + f'{testdir}/bar-notag.txt': { + 'destination': '{datadir}/share/bar-notag.txt', + 'tag': None, + }, + f'{testdir}/bar-devel.h': { + 'destination': '{datadir}/include/bar-devel.h', + 'tag': 'devel', + }, + f'{testdir}/bar-custom.txt': { + 'destination': '{datadir}/share/bar-custom.txt', + 'tag': 'custom', + }, + f'{testdir}/subdir/bar2-devel.h': { + 'destination': '{datadir}/include/bar2-devel.h', + 'tag': 'devel', + }, + }, + 'headers': { + f'{testdir}/foo1-devel.h': { + 'destination': '{includedir}/foo1-devel.h', + 'tag': 'devel', + }, + f'{testdir}/subdir/foo3-devel.h': { + 'destination': '{includedir}/foo3-devel.h', + 'tag': 'devel', + }, + } + } + + fix_path = lambda path: os.path.sep.join(path.split('/')) + expected_fixed = { + data_type: { + fix_path(source): { + key: fix_path(value) if key == 'destination' else value + for key, value in attributes.items() + } + for source, attributes in files.items() + } + for data_type, files in expected.items() + } + + for data_type, files in expected_fixed.items(): + for file, details in files.items(): + with self.subTest(key='{}.{}'.format(data_type, file)): + self.assertEqual(res[data_type][file], details) + + @skip_if_not_language('rust') + @unittest.skipIf(not shutil.which('clippy-driver'), 'Test requires clippy-driver') + def test_rust_clippy(self) -> None: + if self.backend is not Backend.ninja: + raise unittest.SkipTest('Rust is only supported with ninja currently') + # When clippy is used, we should get an exception since a variable named + # "foo" is used, but is on our denylist + testdir = os.path.join(self.rust_test_dir, '1 basic') + self.init(testdir, extra_args=['--werror'], override_envvars={'RUSTC': 'clippy-driver'}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.build() + self.assertIn('error: use of a blacklisted/placeholder name `foo`', cm.exception.stdout) + + @skip_if_not_language('rust') + def test_rust_rlib_linkage(self) -> None: + if self.backend is not Backend.ninja: + raise unittest.SkipTest('Rust is only supported with ninja currently') + template = textwrap.dedent('''\ + use std::process::exit; + + pub fn fun() {{ + exit({}); + }} + ''') + + 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)) + self.addCleanup(windows_proof_rm, gen_file) + + self.init(testdir) + self.build() + self.run_tests() + + with open(gen_file, 'w') as f: + f.write(template.format(39)) + + self.build() + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.run_tests() + self.assertEqual(cm.exception.returncode, 1) + self.assertIn('exit status 39', cm.exception.stdout) + + def test_custom_target_name(self): + testdir = os.path.join(self.unit_test_dir, '100 custom target name') + self.init(testdir) + out = self.build() + if self.backend is Backend.ninja: + self.assertIn('Generating file.txt with a custom command', out) + self.assertIn('Generating subdir/file.txt with a custom command', out) diff -Nru meson-0.53.2/unittests/baseplatformtests.py meson-0.61.2/unittests/baseplatformtests.py --- meson-0.53.2/unittests/baseplatformtests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/baseplatformtests.py 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,468 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import PurePath +from unittest import mock, TestCase, SkipTest +import json +import os +import re +import subprocess +import sys +import tempfile +import typing as T + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.compilers +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + is_cygwin, windows_proof_rmtree, python_command +) +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + Backend, ensure_backend_detects_changes, get_backend_commands, + get_builddir_target_args, get_meson_script, run_configure_inprocess, + run_mtest_inprocess +) + + +class BasePlatformTests(TestCase): + prefix = '/usr' + libdir = 'lib' + + def setUp(self): + super().setUp() + self.maxDiff = None + src_root = str(PurePath(__file__).parents[1]) + self.src_root = src_root + # Get the backend + self.backend = getattr(Backend, os.environ['MESON_UNIT_TEST_BACKEND']) + self.meson_args = ['--backend=' + self.backend.name] + self.meson_native_files = [] + self.meson_cross_files = [] + self.meson_command = python_command + [get_meson_script()] + self.setup_command = self.meson_command + self.meson_args + self.mconf_command = self.meson_command + ['configure'] + self.mintro_command = self.meson_command + ['introspect'] + self.wrap_command = self.meson_command + ['wrap'] + self.rewrite_command = self.meson_command + ['rewrite'] + # Backend-specific build commands + self.build_command, self.clean_command, self.test_command, self.install_command, \ + self.uninstall_command = get_backend_commands(self.backend) + # Test directories + self.common_test_dir = os.path.join(src_root, 'test cases/common') + self.rust_test_dir = os.path.join(src_root, 'test cases/rust') + self.vala_test_dir = os.path.join(src_root, 'test cases/vala') + self.framework_test_dir = os.path.join(src_root, 'test cases/frameworks') + self.unit_test_dir = os.path.join(src_root, 'test cases/unit') + self.rewrite_test_dir = os.path.join(src_root, 'test cases/rewrite') + self.linuxlike_test_dir = os.path.join(src_root, 'test cases/linuxlike') + self.objc_test_dir = os.path.join(src_root, 'test cases/objc') + self.objcpp_test_dir = os.path.join(src_root, 'test cases/objcpp') + + # Misc stuff + self.orig_env = os.environ.copy() + if self.backend is Backend.ninja: + self.no_rebuild_stdout = ['ninja: no work to do.', 'samu: nothing to do'] + else: + # VS doesn't have a stable output when no changes are done + # XCode backend is untested with unit tests, help welcome! + self.no_rebuild_stdout = [f'UNKNOWN BACKEND {self.backend.name!r}'] + + self.builddirs = [] + self.new_builddir() + + def change_builddir(self, newdir): + self.builddir = newdir + self.privatedir = os.path.join(self.builddir, 'meson-private') + self.logdir = os.path.join(self.builddir, 'meson-logs') + self.installdir = os.path.join(self.builddir, 'install') + self.distdir = os.path.join(self.builddir, 'meson-dist') + self.mtest_command = self.meson_command + ['test', '-C', self.builddir] + self.builddirs.append(self.builddir) + + def new_builddir(self): + # Keep builddirs inside the source tree so that virus scanners + # don't complain + newdir = tempfile.mkdtemp(dir=os.getcwd()) + # In case the directory is inside a symlinked directory, find the real + # path otherwise we might not find the srcdir from inside the builddir. + newdir = os.path.realpath(newdir) + self.change_builddir(newdir) + + def new_builddir_in_tempdir(self): + # Can't keep the builddir inside the source tree for the umask tests: + # https://github.com/mesonbuild/meson/pull/5546#issuecomment-509666523 + # And we can't do this for all tests because it causes the path to be + # a short-path which breaks other tests: + # https://github.com/mesonbuild/meson/pull/9497 + newdir = tempfile.mkdtemp() + # In case the directory is inside a symlinked directory, find the real + # path otherwise we might not find the srcdir from inside the builddir. + newdir = os.path.realpath(newdir) + self.change_builddir(newdir) + + def _get_meson_log(self) -> T.Optional[str]: + log = os.path.join(self.logdir, 'meson-log.txt') + if not os.path.isfile(log): + print(f"{log!r} doesn't exist", file=sys.stderr) + return None + with open(log, encoding='utf-8') as f: + return f.read() + + def _print_meson_log(self) -> None: + log = self._get_meson_log() + if log: + print(log) + + def tearDown(self): + for path in self.builddirs: + try: + windows_proof_rmtree(path) + except FileNotFoundError: + pass + os.environ.clear() + os.environ.update(self.orig_env) + super().tearDown() + + def _run(self, command, *, workdir=None, override_envvars: T.Optional[T.Mapping[str, str]] = None): + ''' + Run a command while printing the stdout and stderr to stdout, + and also return a copy of it + ''' + # If this call hangs CI will just abort. It is very hard to distinguish + # between CI issue and test bug in that case. Set timeout and fail loud + # instead. + if override_envvars is None: + env = None + else: + env = os.environ.copy() + env.update(override_envvars) + + p = subprocess.run(command, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, env=env, + encoding='utf-8', + universal_newlines=True, cwd=workdir, timeout=60 * 5) + print(p.stdout) + if p.returncode != 0: + if 'MESON_SKIP_TEST' in p.stdout: + raise SkipTest('Project requested skipping.') + raise subprocess.CalledProcessError(p.returncode, command, output=p.stdout) + return p.stdout + + def init(self, srcdir, *, + extra_args=None, + default_args=True, + inprocess=False, + override_envvars: T.Optional[T.Mapping[str, str]] = None, + workdir=None, + allow_fail: bool = False) -> str: + """Call `meson setup` + + :param allow_fail: If set to true initialization is allowed to fail. + When it does the log will be returned instead of stdout. + :return: the value of stdout on success, or the meson log on failure + when :param allow_fail: is true + """ + self.assertPathExists(srcdir) + if extra_args is None: + extra_args = [] + if not isinstance(extra_args, list): + extra_args = [extra_args] + args = [srcdir, self.builddir] + if default_args: + args += ['--prefix', self.prefix] + if self.libdir: + args += ['--libdir', self.libdir] + for f in self.meson_native_files: + args += ['--native-file', f] + for f in self.meson_cross_files: + args += ['--cross-file', f] + self.privatedir = os.path.join(self.builddir, 'meson-private') + if inprocess: + try: + returncode, out, err = run_configure_inprocess(self.meson_args + args + extra_args, override_envvars) + except Exception as e: + if not allow_fail: + self._print_meson_log() + raise + out = self._get_meson_log() # Best we can do here + err = '' # type checkers can't figure out that on this path returncode will always be 0 + returncode = 0 + finally: + # Close log file to satisfy Windows file locking + mesonbuild.mlog.shutdown() + mesonbuild.mlog.log_dir = None + mesonbuild.mlog.log_file = None + + if 'MESON_SKIP_TEST' in out: + raise SkipTest('Project requested skipping.') + if returncode != 0: + self._print_meson_log() + print('Stdout:\n') + print(out) + print('Stderr:\n') + print(err) + if not allow_fail: + raise RuntimeError('Configure failed') + else: + try: + out = self._run(self.setup_command + args + extra_args, override_envvars=override_envvars, workdir=workdir) + except SkipTest: + raise SkipTest('Project requested skipping: ' + srcdir) + except Exception: + if not allow_fail: + self._print_meson_log() + raise + out = self._get_meson_log() # best we can do here + return out + + def build(self, target=None, *, extra_args=None, override_envvars=None): + if extra_args is None: + extra_args = [] + # Add arguments for building the target (if specified), + # and using the build dir (if required, with VS) + args = get_builddir_target_args(self.backend, self.builddir, target) + return self._run(self.build_command + args + extra_args, workdir=self.builddir, override_envvars=override_envvars) + + def clean(self, *, override_envvars=None): + dir_args = get_builddir_target_args(self.backend, self.builddir, None) + self._run(self.clean_command + dir_args, workdir=self.builddir, override_envvars=override_envvars) + + def run_tests(self, *, inprocess=False, override_envvars=None): + if not inprocess: + return self._run(self.test_command, workdir=self.builddir, override_envvars=override_envvars) + else: + with mock.patch.dict(os.environ, override_envvars): + return run_mtest_inprocess(['-C', self.builddir])[1] + + def install(self, *, use_destdir=True, override_envvars=None): + if self.backend is not Backend.ninja: + raise SkipTest(f'{self.backend.name!r} backend can\'t install files') + if use_destdir: + destdir = {'DESTDIR': self.installdir} + if override_envvars is None: + override_envvars = destdir + else: + override_envvars.update(destdir) + 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) + + def run_target(self, target, *, override_envvars=None): + ''' + Run a Ninja target while printing the stdout and stderr to stdout, + and also return a copy of it + ''' + return self.build(target=target, override_envvars=override_envvars) + + def setconf(self, arg, will_build=True): + if not isinstance(arg, list): + arg = [arg] + if will_build: + ensure_backend_detects_changes(self.backend) + self._run(self.mconf_command + arg + [self.builddir]) + + def wipe(self): + windows_proof_rmtree(self.builddir) + + def utime(self, f): + ensure_backend_detects_changes(self.backend) + os.utime(f) + + def get_compdb(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Compiler db not available with {self.backend.name} backend') + try: + with open(os.path.join(self.builddir, 'compile_commands.json'), encoding='utf-8') as ifile: + contents = json.load(ifile) + except FileNotFoundError: + raise SkipTest('Compiler db not found') + # If Ninja is using .rsp files, generate them, read their contents, and + # replace it as the command for all compile commands in the parsed json. + if len(contents) > 0 and contents[0]['command'].endswith('.rsp'): + # Pretend to build so that the rsp files are generated + self.build(extra_args=['-d', 'keeprsp', '-n']) + for each in contents: + # Extract the actual command from the rsp file + compiler, rsp = each['command'].split(' @') + rsp = os.path.join(self.builddir, rsp) + # Replace the command with its contents + with open(rsp, encoding='utf-8') as f: + each['command'] = compiler + ' ' + f.read() + return contents + + def get_meson_log(self): + with open(os.path.join(self.builddir, 'meson-logs', 'meson-log.txt'), encoding='utf-8') as f: + return f.readlines() + + def get_meson_log_compiler_checks(self): + ''' + Fetch a list command-lines run by meson for compiler checks. + Each command-line is returned as a list of arguments. + ''' + log = self.get_meson_log() + prefix = 'Command line:' + cmds = [l[len(prefix):].split() for l in log if l.startswith(prefix)] + return cmds + + def get_meson_log_sanitychecks(self): + ''' + Same as above, but for the sanity checks that were run + ''' + log = self.get_meson_log() + prefix = 'Sanity check compiler command line:' + cmds = [l[len(prefix):].split() for l in log if l.startswith(prefix)] + return cmds + + def introspect(self, args): + if isinstance(args, str): + args = [args] + out = subprocess.check_output(self.mintro_command + args + [self.builddir], + universal_newlines=True) + return json.loads(out) + + def introspect_directory(self, directory, args): + if isinstance(args, str): + args = [args] + out = subprocess.check_output(self.mintro_command + args + [directory], + universal_newlines=True) + try: + obj = json.loads(out) + except Exception as e: + print(out) + raise e + return obj + + def assertPathEqual(self, path1, path2): + ''' + Handles a lot of platform-specific quirks related to paths such as + separator, case-sensitivity, etc. + ''' + self.assertEqual(PurePath(path1), PurePath(path2)) + + def assertPathListEqual(self, pathlist1, pathlist2): + self.assertEqual(len(pathlist1), len(pathlist2)) + worklist = list(zip(pathlist1, pathlist2)) + for i in worklist: + if i[0] is None: + self.assertEqual(i[0], i[1]) + else: + self.assertPathEqual(i[0], i[1]) + + def assertPathBasenameEqual(self, path, basename): + msg = f'{path!r} does not end with {basename!r}' + # We cannot use os.path.basename because it returns '' when the path + # ends with '/' for some silly reason. This is not how the UNIX utility + # `basename` works. + path_basename = PurePath(path).parts[-1] + self.assertEqual(PurePath(path_basename), PurePath(basename), msg) + + def assertReconfiguredBuildIsNoop(self): + 'Assert that we reconfigured and then there was nothing to do' + ret = self.build() + self.assertIn('The Meson build system', ret) + if self.backend is Backend.ninja: + for line in ret.split('\n'): + if line in self.no_rebuild_stdout: + break + else: + raise AssertionError('build was reconfigured, but was not no-op') + elif self.backend is Backend.vs: + # Ensure that some target said that no rebuild was done + # XXX: Note CustomBuild did indeed rebuild, because of the regen checker! + self.assertIn('ClCompile:\n All outputs are up-to-date.', ret) + self.assertIn('Link:\n All outputs are up-to-date.', ret) + # Ensure that no targets were built + self.assertNotRegex(ret, re.compile('ClCompile:\n [^\n]*cl', flags=re.IGNORECASE)) + self.assertNotRegex(ret, re.compile('Link:\n [^\n]*link', flags=re.IGNORECASE)) + elif self.backend is Backend.xcode: + raise SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError(f'Invalid backend: {self.backend.name!r}') + + def assertBuildIsNoop(self): + ret = self.build() + if self.backend is Backend.ninja: + self.assertIn(ret.split('\n')[-2], self.no_rebuild_stdout) + elif self.backend is Backend.vs: + # Ensure that some target of each type said that no rebuild was done + # We always have at least one CustomBuild target for the regen checker + self.assertIn('CustomBuild:\n All outputs are up-to-date.', ret) + self.assertIn('ClCompile:\n All outputs are up-to-date.', ret) + self.assertIn('Link:\n All outputs are up-to-date.', ret) + # Ensure that no targets were built + self.assertNotRegex(ret, re.compile('CustomBuild:\n [^\n]*cl', flags=re.IGNORECASE)) + self.assertNotRegex(ret, re.compile('ClCompile:\n [^\n]*cl', flags=re.IGNORECASE)) + self.assertNotRegex(ret, re.compile('Link:\n [^\n]*link', flags=re.IGNORECASE)) + elif self.backend is Backend.xcode: + raise SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError(f'Invalid backend: {self.backend.name!r}') + + def assertRebuiltTarget(self, target): + ret = self.build() + if self.backend is Backend.ninja: + self.assertIn(f'Linking target {target}', ret) + elif self.backend is Backend.vs: + # Ensure that this target was rebuilt + linkre = re.compile('Link:\n [^\n]*link[^\n]*' + target, flags=re.IGNORECASE) + self.assertRegex(ret, linkre) + elif self.backend is Backend.xcode: + raise SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError(f'Invalid backend: {self.backend.name!r}') + + @staticmethod + def get_target_from_filename(filename): + base = os.path.splitext(filename)[0] + if base.startswith(('lib', 'cyg')): + return base[3:] + return base + + def assertBuildRelinkedOnlyTarget(self, target): + ret = self.build() + if self.backend is Backend.ninja: + linked_targets = [] + for line in ret.split('\n'): + if 'Linking target' in line: + fname = line.rsplit('target ')[-1] + linked_targets.append(self.get_target_from_filename(fname)) + self.assertEqual(linked_targets, [target]) + elif self.backend is Backend.vs: + # Ensure that this target was rebuilt + linkre = re.compile(r'Link:\n [^\n]*link.exe[^\n]*/OUT:".\\([^"]*)"', flags=re.IGNORECASE) + matches = linkre.findall(ret) + self.assertEqual(len(matches), 1, msg=matches) + self.assertEqual(self.get_target_from_filename(matches[0]), target) + elif self.backend is Backend.xcode: + raise SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError(f'Invalid backend: {self.backend.name!r}') + + def assertPathExists(self, path): + m = f'Path {path!r} should exist' + self.assertTrue(os.path.exists(path), msg=m) + + def assertPathDoesNotExist(self, path): + m = f'Path {path!r} should not exist' + self.assertFalse(os.path.exists(path), msg=m) diff -Nru meson-0.53.2/unittests/darwintests.py meson-0.61.2/unittests/darwintests.py --- meson-0.53.2/unittests/darwintests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/darwintests.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,150 @@ +# Copyright 2016-2021 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 subprocess +import re +import os +import unittest + +from mesonbuild.mesonlib import ( + MachineChoice, is_osx +) +from mesonbuild.compilers import ( + detect_c_compiler +) + + +from run_tests import ( + get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@unittest.skipUnless(is_osx(), "requires Darwin") +class DarwinTests(BasePlatformTests): + ''' + Tests that should run on macOS + ''' + + def setUp(self): + super().setUp() + self.platform_test_dir = os.path.join(self.src_root, 'test cases/osx') + + def test_apple_bitcode(self): + ''' + Test that -fembed-bitcode is correctly added while compiling and + -bitcode_bundle is added while linking when b_bitcode is true and not + when it is false. This can't be an ordinary test case because we need + to inspect the compiler database. + ''' + testdir = os.path.join(self.platform_test_dir, '7 bitcode') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.id != 'clang': + raise unittest.SkipTest('Not using Clang on OSX') + # Try with bitcode enabled + out = self.init(testdir, extra_args='-Db_bitcode=true') + # Warning was printed + self.assertRegex(out, 'WARNING:.*b_bitcode') + # Compiler options were added + for compdb in self.get_compdb(): + if 'module' in compdb['file']: + self.assertNotIn('-fembed-bitcode', compdb['command']) + else: + self.assertIn('-fembed-bitcode', compdb['command']) + build_ninja = os.path.join(self.builddir, 'build.ninja') + # Linker options were added + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + m = re.search('LINK_ARGS =.*-bitcode_bundle', contents) + self.assertIsNotNone(m, msg=contents) + # Try with bitcode disabled + self.setconf('-Db_bitcode=false') + # Regenerate build + self.build() + for compdb in self.get_compdb(): + self.assertNotIn('-fembed-bitcode', compdb['command']) + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + m = re.search('LINK_ARGS =.*-bitcode_bundle', contents) + self.assertIsNone(m, msg=contents) + + def test_apple_bitcode_modules(self): + ''' + Same as above, just for shared_module() + ''' + testdir = os.path.join(self.common_test_dir, '148 shared module resolving symbol in executable') + # Ensure that it builds even with bitcode enabled + self.init(testdir, extra_args='-Db_bitcode=true') + self.build() + self.run_tests() + + def _get_darwin_versions(self, fname): + fname = os.path.join(self.builddir, fname) + out = subprocess.check_output(['otool', '-L', fname], universal_newlines=True) + m = re.match(r'.*version (.*), current version (.*)\)', out.split('\n')[1]) + self.assertIsNotNone(m, msg=out) + return m.groups() + + @skipIfNoPkgconfig + def test_library_versioning(self): + ''' + Ensure that compatibility_version and current_version are set correctly + ''' + testdir = os.path.join(self.platform_test_dir, '2 library versions') + self.init(testdir) + self.build() + targets = {} + for t in self.introspect('--targets'): + targets[t['name']] = t['filename'][0] if isinstance(t['filename'], list) else t['filename'] + self.assertEqual(self._get_darwin_versions(targets['some']), ('7.0.0', '7.0.0')) + self.assertEqual(self._get_darwin_versions(targets['noversion']), ('0.0.0', '0.0.0')) + self.assertEqual(self._get_darwin_versions(targets['onlyversion']), ('1.0.0', '1.0.0')) + self.assertEqual(self._get_darwin_versions(targets['onlysoversion']), ('5.0.0', '5.0.0')) + self.assertEqual(self._get_darwin_versions(targets['intver']), ('2.0.0', '2.0.0')) + self.assertEqual(self._get_darwin_versions(targets['stringver']), ('2.3.0', '2.3.0')) + self.assertEqual(self._get_darwin_versions(targets['stringlistver']), ('2.4.0', '2.4.0')) + self.assertEqual(self._get_darwin_versions(targets['intstringver']), ('1111.0.0', '2.5.0')) + self.assertEqual(self._get_darwin_versions(targets['stringlistvers']), ('2.6.0', '2.6.1')) + + def test_duplicate_rpath(self): + testdir = os.path.join(self.unit_test_dir, '10 build_rpath') + # We purposely pass a duplicate rpath to Meson, in order + # to ascertain that Meson does not call install_name_tool + # with duplicate -delete_rpath arguments, which would + # lead to erroring out on installation + env = {"LDFLAGS": "-Wl,-rpath,/foo/bar"} + self.init(testdir, override_envvars=env) + self.build() + self.install() + + def test_removing_unused_linker_args(self): + testdir = os.path.join(self.common_test_dir, '104 has arg') + env = {'CFLAGS': '-L/tmp -L /var/tmp -headerpad_max_install_names -Wl,-export_dynamic -framework Foundation'} + self.init(testdir, override_envvars=env) + + def test_objc_versions(self): + # Objective-C always uses the C standard version. + # Objecttive-C++ always uses the C++ standard version. + # This is what most people seem to want and in addition + # it is the only setup supported by Xcode. + testdir = os.path.join(self.objc_test_dir, '1 simple') + self.init(testdir) + self.assertIn('-std=c99', self.get_compdb()[0]['command']) + self.wipe() + testdir = os.path.join(self.objcpp_test_dir, '1 simple') + self.init(testdir) + self.assertIn('-std=c++14', self.get_compdb()[0]['command']) diff -Nru meson-0.53.2/unittests/datatests.py meson-0.61.2/unittests/datatests.py --- meson-0.53.2/unittests/datatests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/datatests.py 2022-01-17 10:50:45.000000000 +0000 @@ -0,0 +1,272 @@ +# Copyright 2016-2021 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 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 +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.interpreter import Interpreter +from mesonbuild.ast import AstInterpreter +from mesonbuild.mesonlib import ( + MachineChoice, OptionKey +) +from mesonbuild.compilers import ( + detect_c_compiler, detect_cpp_compiler +) +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + FakeBuild, get_fake_env +) + +from .helpers import * + +@unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release') +class DataTests(unittest.TestCase): + + def test_snippets(self): + hashcounter = re.compile('^ *(#)+') + snippet_dir = Path('docs/markdown/snippets') + self.assertTrue(snippet_dir.is_dir()) + for f in snippet_dir.glob('*'): + self.assertTrue(f.is_file()) + if f.parts[-1].endswith('~'): + continue + if f.suffix == '.md': + in_code_block = False + with f.open(encoding='utf-8') as snippet: + for line in snippet: + if line.startswith(' '): + continue + if line.startswith('```'): + in_code_block = not in_code_block + if in_code_block: + continue + m = re.match(hashcounter, line) + if m: + self.assertEqual(len(m.group(0)), 2, 'All headings in snippets must have two hash symbols: ' + f.name) + self.assertFalse(in_code_block, 'Unclosed code block.') + else: + if f.name != 'add_release_note_snippets_here': + self.assertTrue(False, 'A file without .md suffix in snippets dir: ' + f.name) + + def test_compiler_options_documented(self): + ''' + Test that C and C++ compiler options and base options are documented in + Builtin-Options.md. Only tests the default compiler for the current + platform on the CI. + ''' + md = None + with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + env = get_fake_env() + # FIXME: Support other compilers + cc = detect_c_compiler(env, MachineChoice.HOST) + cpp = detect_cpp_compiler(env, MachineChoice.HOST) + for comp in (cc, cpp): + for opt in comp.get_options(): + self.assertIn(str(opt), md) + for opt in comp.base_options: + self.assertIn(str(opt), md) + self.assertNotIn('b_unknown', md) + + @staticmethod + def _get_section_content(name, sections, md): + for section in sections: + if section and section.group(1) == name: + try: + next_section = next(sections) + end = next_section.start() + except StopIteration: + end = len(md) + # Extract the content for this section + return md[section.end():end] + raise RuntimeError(f'Could not find "{name}" heading') + + def test_builtin_options_documented(self): + ''' + Test that universal options and base options are documented in + Builtin-Options.md. + ''' + from itertools import tee + md = None + with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + + found_entries = set() + sections = re.finditer(r"^## (.+)$", md, re.MULTILINE) + # Extract the content for this section + content = self._get_section_content("Universal options", sections, md) + subsections = tee(re.finditer(r"^### (.+)$", content, re.MULTILINE)) + subcontent1 = self._get_section_content("Directories", subsections[0], content) + subcontent2 = self._get_section_content("Core options", subsections[1], content) + subcontent3 = self._get_section_content("Module options", sections, md) + for subcontent in (subcontent1, subcontent2, subcontent3): + # Find the option names + options = set() + # Match either a table row or a table heading separator: | ------ | + rows = re.finditer(r"^\|(?: (\w+) .* | *-+ *)\|", subcontent, re.MULTILINE) + # Skip the header of the first table + next(rows) + # Skip the heading separator of the first table + next(rows) + for m in rows: + value = m.group(1) + # End when the `buildtype` table starts + if value is None: + break + options.add(value) + self.assertEqual(len(found_entries & options), 0) + found_entries |= options + + self.assertEqual(found_entries, { + *(str(k.evolve(module=None)) for k in mesonbuild.coredata.BUILTIN_OPTIONS), + *(str(k.evolve(module=None)) for k in mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE), + }) + + # Check that `buildtype` table inside `Core options` matches how + # setting of builtin options behaves + # + # Find all tables inside this subsection + tables = re.finditer(r"^\| (\w+) .* \|\n\| *[-|\s]+ *\|$", subcontent2, re.MULTILINE) + # Get the table we want using the header of the first column + table = self._get_section_content('buildtype', tables, subcontent2) + # Get table row data + rows = re.finditer(r"^\|(?: (\w+)\s+\| (\w+)\s+\| (\w+) .* | *-+ *)\|", table, re.MULTILINE) + env = get_fake_env() + for m in rows: + buildtype, debug, opt = m.groups() + if debug == 'true': + debug = True + elif debug == 'false': + debug = False + else: + raise RuntimeError(f'Invalid debug value {debug!r} in row:\n{m.group()}') + env.coredata.set_option(OptionKey('buildtype'), buildtype) + self.assertEqual(env.coredata.options[OptionKey('buildtype')].value, buildtype) + self.assertEqual(env.coredata.options[OptionKey('optimization')].value, opt) + self.assertEqual(env.coredata.options[OptionKey('debug')].value, debug) + + def test_cpu_families_documented(self): + with open("docs/markdown/Reference-tables.md", encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + + sections = re.finditer(r"^## (.+)$", md, re.MULTILINE) + content = self._get_section_content("CPU families", sections, md) + # Find the list entries + arches = [m.group(1) for m in re.finditer(r"^\| (\w+) +\|", content, re.MULTILINE)] + # Drop the header + arches = set(arches[1:]) + self.assertEqual(arches, set(mesonbuild.environment.known_cpu_families)) + + def test_markdown_files_in_sitemap(self): + ''' + Test that each markdown files in docs/markdown is referenced in sitemap.txt + ''' + with open("docs/sitemap.txt", encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + toc = list(m.group(1) for m in re.finditer(r"^\s*(\w.*)$", md, re.MULTILINE)) + markdownfiles = [f.name for f in Path("docs/markdown").iterdir() if f.is_file() and f.suffix == '.md'] + exceptions = ['_Sidebar.md'] + for f in markdownfiles: + if f not in exceptions and not f.startswith('_include'): + self.assertIn(f, toc) + + def test_modules_in_navbar(self): + ''' + Test that each module is referenced in navbar_links.html + ''' + with open("docs/theme/extra/templates/navbar_links.html", encoding='utf-8') as f: + html = f.read().lower() + self.assertIsNotNone(html) + for f in Path('mesonbuild/modules').glob('*.py'): + if f.name in {'modtest.py', 'qt.py', '__init__.py'}: + continue + name = f'{f.stem}-module.html' + name = name.replace('unstable_', '') + name = name.replace('python3', 'python-3') + name = name.replace('_', '-') + self.assertIn(name, html) + + def test_vim_syntax_highlighting(self): + ''' + Ensure that vim syntax highlighting files were updated for new + functions in the global namespace in build files. + ''' + env = get_fake_env() + interp = Interpreter(FakeBuild(env), mock=True) + with open('data/syntax-highlighting/vim/syntax/meson.vim', encoding='utf-8') as f: + res = re.search(r'syn keyword mesonBuiltin(\s+\\\s\w+)+', f.read(), re.MULTILINE) + defined = set([a.strip() for a in res.group().split('\\')][1:]) + self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys()))) + + def test_all_functions_defined_in_ast_interpreter(self): + ''' + Ensure that the all functions defined in the Interpreter are also defined + in the AstInterpreter (and vice versa). + ''' + env = get_fake_env() + 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 -Nru meson-0.53.2/unittests/failuretests.py meson-0.61.2/unittests/failuretests.py --- meson-0.53.2/unittests/failuretests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/failuretests.py 2021-11-25 22:00:46.000000000 +0000 @@ -0,0 +1,392 @@ +# Copyright 2016-2021 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 subprocess +import tempfile +import os +import shutil +import unittest +from contextlib import contextmanager + +from mesonbuild.mesonlib import ( + MachineChoice, is_windows, is_osx, windows_proof_rmtree, windows_proof_rm +) +from mesonbuild.compilers import ( + detect_objc_compiler, detect_objcpp_compiler +) +from mesonbuild.mesonlib import EnvironmentException, MesonException +from mesonbuild.programs import ExternalProgram + + +from run_tests import ( + get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@contextmanager +def no_pkgconfig(): + ''' + A context manager that overrides shutil.which and ExternalProgram to force + them to return None for pkg-config to simulate it not existing. + ''' + old_which = shutil.which + old_search = ExternalProgram._search + + def new_search(self, name, search_dir): + if name == 'pkg-config': + return [None] + return old_search(self, name, search_dir) + + def new_which(cmd, *kwargs): + if cmd == 'pkg-config': + return None + return old_which(cmd, *kwargs) + + shutil.which = new_which + ExternalProgram._search = new_search + try: + yield + finally: + shutil.which = old_which + ExternalProgram._search = old_search + +class FailureTests(BasePlatformTests): + ''' + Tests that test failure conditions. Build files here should be dynamically + generated and static tests should go into `test cases/failing*`. + This is useful because there can be many ways in which a particular + function can fail, and creating failing tests for all of them is tedious + and slows down testing. + ''' + dnf = "[Dd]ependency.*not found(:.*)?" + nopkg = '[Pp]kg-config.*not found' + + def setUp(self): + super().setUp() + self.srcdir = os.path.realpath(tempfile.mkdtemp()) + self.mbuild = os.path.join(self.srcdir, 'meson.build') + self.moptions = os.path.join(self.srcdir, 'meson_options.txt') + + def tearDown(self): + super().tearDown() + windows_proof_rmtree(self.srcdir) + + def assertMesonRaises(self, contents, match, *, + extra_args=None, + langs=None, + meson_version=None, + options=None, + override_envvars=None): + ''' + Assert that running meson configure on the specified @contents raises + a error message matching regex @match. + ''' + if langs is None: + langs = [] + with open(self.mbuild, 'w', encoding='utf-8') as f: + f.write("project('failure test', 'c', 'cpp'") + if meson_version: + f.write(f", meson_version: '{meson_version}'") + f.write(")\n") + for lang in langs: + f.write(f"add_languages('{lang}', required : false)\n") + f.write(contents) + if options is not None: + with open(self.moptions, 'w', encoding='utf-8') as f: + f.write(options) + o = {'MESON_FORCE_BACKTRACE': '1'} + if override_envvars is None: + override_envvars = o + else: + override_envvars.update(o) + # Force tracebacks so we can detect them properly + with self.assertRaisesRegex(MesonException, match, msg=contents): + # Must run in-process or we'll get a generic CalledProcessError + self.init(self.srcdir, extra_args=extra_args, + inprocess=True, + override_envvars = override_envvars) + + def obtainMesonOutput(self, contents, match, extra_args, langs, meson_version=None): + if langs is None: + langs = [] + with open(self.mbuild, 'w', encoding='utf-8') as f: + f.write("project('output test', 'c', 'cpp'") + if meson_version: + f.write(f", meson_version: '{meson_version}'") + f.write(")\n") + for lang in langs: + f.write(f"add_languages('{lang}', required : false)\n") + f.write(contents) + # Run in-process for speed and consistency with assertMesonRaises + return self.init(self.srcdir, extra_args=extra_args, inprocess=True) + + def assertMesonOutputs(self, contents, match, extra_args=None, langs=None, meson_version=None): + ''' + Assert that running meson configure on the specified @contents outputs + something that matches regex @match. + ''' + out = self.obtainMesonOutput(contents, match, extra_args, langs, meson_version) + self.assertRegex(out, match) + + def assertMesonDoesNotOutput(self, contents, match, extra_args=None, langs=None, meson_version=None): + ''' + Assert that running meson configure on the specified @contents does not output + something that matches regex @match. + ''' + out = self.obtainMesonOutput(contents, match, extra_args, langs, meson_version) + self.assertNotRegex(out, match) + + @skipIfNoPkgconfig + def test_dependency(self): + if subprocess.call(['pkg-config', '--exists', 'zlib']) != 0: + raise unittest.SkipTest('zlib not found with pkg-config') + a = (("dependency('zlib', method : 'fail')", "'fail' is invalid"), + ("dependency('zlib', static : '1')", "[Ss]tatic.*boolean"), + ("dependency('zlib', version : 1)", "Item must be a list or one of "), + ("dependency('zlib', required : 1)", "[Rr]equired.*boolean"), + ("dependency('zlib', method : 1)", "[Mm]ethod.*string"), + ("dependency('zlibfail')", self.dnf),) + for contents, match in a: + self.assertMesonRaises(contents, match) + + def test_apple_frameworks_dependency(self): + if not is_osx(): + raise unittest.SkipTest('only run on macOS') + self.assertMesonRaises("dependency('appleframeworks')", + "requires at least one module") + + def test_extraframework_dependency_method(self): + code = "dependency('metal', method : 'extraframework')" + if not is_osx(): + self.assertMesonRaises(code, self.dnf) + else: + # metal framework is always available on macOS + self.assertMesonOutputs(code, '[Dd]ependency.*metal.*found.*YES') + + def test_sdl2_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('sdl2-config'): + raise unittest.SkipTest('sdl2-config found') + self.assertMesonRaises("dependency('sdl2', method : 'sdlconfig')", self.dnf) + if shutil.which('pkg-config'): + self.assertMesonRaises("dependency('sdl2', method : 'pkg-config')", self.dnf) + with no_pkgconfig(): + # Look for pkg-config, cache it, then + # Use cached pkg-config without erroring out, then + # Use cached pkg-config to error out + code = "dependency('foobarrr', method : 'pkg-config', required : false)\n" \ + "dependency('foobarrr2', method : 'pkg-config', required : false)\n" \ + "dependency('sdl2', method : 'pkg-config')" + self.assertMesonRaises(code, self.nopkg) + + def test_gnustep_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('gnustep-config'): + raise unittest.SkipTest('gnustep-config found') + self.assertMesonRaises("dependency('gnustep')", + f"(requires a Objc compiler|{self.dnf})", + langs = ['objc']) + + def test_wx_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('wx-config-3.0') or shutil.which('wx-config') or shutil.which('wx-config-gtk3'): + raise unittest.SkipTest('wx-config, wx-config-3.0 or wx-config-gtk3 found') + self.assertMesonRaises("dependency('wxwidgets')", self.dnf) + self.assertMesonOutputs("dependency('wxwidgets', required : false)", + "Run-time dependency .*WxWidgets.* found: .*NO.*") + + def test_wx_dependency(self): + if not shutil.which('wx-config-3.0') and not shutil.which('wx-config') and not shutil.which('wx-config-gtk3'): + raise unittest.SkipTest('Neither wx-config, wx-config-3.0 nor wx-config-gtk3 found') + self.assertMesonRaises("dependency('wxwidgets', modules : 1)", + "module argument is not a string") + + def test_llvm_dependency(self): + self.assertMesonRaises("dependency('llvm', modules : 'fail')", + f"(required.*fail|{self.dnf})") + + def test_boost_notfound_dependency(self): + # Can be run even if Boost is found or not + self.assertMesonRaises("dependency('boost', modules : 1)", + "module.*not a string") + self.assertMesonRaises("dependency('boost', modules : 'fail')", + f"(fail.*not found|{self.dnf})") + + def test_boost_BOOST_ROOT_dependency(self): + # Test BOOST_ROOT; can be run even if Boost is found or not + self.assertMesonRaises("dependency('boost')", + f"(boost_root.*absolute|{self.dnf})", + override_envvars = {'BOOST_ROOT': 'relative/path'}) + + def test_dependency_invalid_method(self): + code = '''zlib_dep = dependency('zlib', required : false) + zlib_dep.get_configtool_variable('foo') + ''' + self.assertMesonRaises(code, ".* is not a config-tool dependency") + code = '''zlib_dep = dependency('zlib', required : false) + dep = declare_dependency(dependencies : zlib_dep) + dep.get_pkgconfig_variable('foo') + ''' + self.assertMesonRaises(code, "Method.*pkgconfig.*is invalid.*internal") + code = '''zlib_dep = dependency('zlib', required : false) + dep = declare_dependency(dependencies : zlib_dep) + dep.get_configtool_variable('foo') + ''' + self.assertMesonRaises(code, "Method.*configtool.*is invalid.*internal") + + def test_objc_cpp_detection(self): + ''' + Test that when we can't detect objc or objcpp, we fail gracefully. + ''' + env = get_fake_env() + try: + detect_objc_compiler(env, MachineChoice.HOST) + detect_objcpp_compiler(env, MachineChoice.HOST) + except EnvironmentException: + code = "add_languages('objc')\nadd_languages('objcpp')" + self.assertMesonRaises(code, "Unknown compiler") + return + raise unittest.SkipTest("objc and objcpp found, can't test detection failure") + + def test_subproject_variables(self): + ''' + Test that: + 1. The correct message is outputted when a not-required dep is not + found and the fallback subproject is also not found. + 2. A not-required fallback dependency is not found because the + subproject failed to parse. + 3. A not-found not-required dep with a fallback subproject outputs the + correct message when the fallback subproject is found but the + variable inside it is not. + 4. A fallback dependency is found from the subproject parsed in (3) + 5. A wrap file from a subproject is used but fails because it does not + contain required keys. + ''' + tdir = os.path.join(self.unit_test_dir, '20 subproj dep variables') + stray_file = os.path.join(tdir, 'subprojects/subsubproject.wrap') + if os.path.exists(stray_file): + windows_proof_rm(stray_file) + out = self.init(tdir, inprocess=True) + self.assertRegex(out, r"Neither a subproject directory nor a .*nosubproj.wrap.* file was found") + self.assertRegex(out, r'Function does not take positional arguments.') + self.assertRegex(out, r'Dependency .*somenotfounddep.* from subproject .*subprojects/somesubproj.* found: .*NO.*') + self.assertRegex(out, r'Dependency .*zlibproxy.* from subproject .*subprojects.*somesubproj.* found: .*YES.*') + self.assertRegex(out, r'Missing key .*source_filename.* in subsubproject.wrap') + windows_proof_rm(stray_file) + + def test_exception_exit_status(self): + ''' + Test exit status on python exception + ''' + tdir = os.path.join(self.unit_test_dir, '21 exit status') + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(tdir, inprocess=False, override_envvars = {'MESON_UNIT_TEST': '1', 'MESON_FORCE_BACKTRACE': ''}) + self.assertEqual(cm.exception.returncode, 2) + self.wipe() + + def test_dict_requires_key_value_pairs(self): + self.assertMesonRaises("dict = {3, 'foo': 'bar'}", + 'Only key:value pairs are valid in dict construction.') + self.assertMesonRaises("{'foo': 'bar', 3}", + 'Only key:value pairs are valid in dict construction.') + + def test_dict_forbids_duplicate_keys(self): + self.assertMesonRaises("dict = {'a': 41, 'a': 42}", + 'Duplicate dictionary key: a.*') + + def test_dict_forbids_integer_key(self): + self.assertMesonRaises("dict = {3: 'foo'}", + 'Key must be a string.*') + + def test_using_too_recent_feature(self): + # Here we use a dict, which was introduced in 0.47.0 + self.assertMesonOutputs("dict = {}", + ".*WARNING.*Project targeting.*but.*", + meson_version='>= 0.46.0') + + def test_using_recent_feature(self): + # Same as above, except the meson version is now appropriate + self.assertMesonDoesNotOutput("dict = {}", + ".*WARNING.*Project targeting.*but.*", + meson_version='>= 0.47') + + def test_using_too_recent_feature_dependency(self): + self.assertMesonOutputs("dependency('pcap', required: false)", + ".*WARNING.*Project targeting.*but.*", + meson_version='>= 0.41.0') + + def test_vcs_tag_featurenew_build_always_stale(self): + 'https://github.com/mesonbuild/meson/issues/3904' + vcs_tag = '''version_data = configuration_data() + version_data.set('PROJVER', '@VCS_TAG@') + vf = configure_file(output : 'version.h.in', configuration: version_data) + f = vcs_tag(input : vf, output : 'version.h') + ''' + msg = '.*WARNING:.*feature.*build_always_stale.*custom_target.*' + self.assertMesonDoesNotOutput(vcs_tag, msg, meson_version='>=0.43') + + def test_missing_subproject_not_required_and_required(self): + self.assertMesonRaises("sub1 = subproject('not-found-subproject', required: false)\n" + + "sub2 = subproject('not-found-subproject', required: true)", + """.*Subproject "subprojects/not-found-subproject" required but not found.*""") + + def test_get_variable_on_not_found_project(self): + self.assertMesonRaises("sub1 = subproject('not-found-subproject', required: false)\n" + + "sub1.get_variable('naaa')", + """Subproject "subprojects/not-found-subproject" disabled can't get_variable on it.""") + + def test_version_checked_before_parsing_options(self): + ''' + https://github.com/mesonbuild/meson/issues/5281 + ''' + options = "option('some-option', type: 'foo', value: '')" + match = 'Meson version is.*but project requires >=2000' + self.assertMesonRaises("", match, meson_version='>=2000', options=options) + + def test_assert_default_message(self): + self.assertMesonRaises("k1 = 'a'\n" + + "assert({\n" + + " k1: 1,\n" + + "}['a'] == 2)\n", + r"Assert failed: {k1 : 1}\['a'\] == 2") + + def test_wrap_nofallback(self): + self.assertMesonRaises("dependency('notfound', fallback : ['foo', 'foo_dep'])", + r"Dependency 'notfound' is required but not found.", + extra_args=['--wrap-mode=nofallback']) + + def test_message(self): + self.assertMesonOutputs("message('Array:', ['a', 'b'])", + r"Message:.* Array: \['a', 'b'\]") + + def test_warning(self): + self.assertMesonOutputs("warning('Array:', ['a', 'b'])", + r"WARNING:.* Array: \['a', 'b'\]") + + def test_override_dependency_twice(self): + self.assertMesonRaises("meson.override_dependency('foo', declare_dependency())\n" + + "meson.override_dependency('foo', declare_dependency())", + """Tried to override dependency 'foo' which has already been resolved or overridden""") + + @unittest.skipIf(is_windows(), 'zlib is not available on Windows') + def test_override_resolved_dependency(self): + self.assertMesonRaises("dependency('zlib')\n" + + "meson.override_dependency('zlib', declare_dependency())", + """Tried to override dependency 'zlib' which has already been resolved or overridden""") + + def test_error_func(self): + self.assertMesonRaises("error('a', 'b', ['c', ['d', {'e': 'f'}]], 'g')", + r"Problem encountered: a b \['c', \['d', {'e' : 'f'}\]\] g") diff -Nru meson-0.53.2/unittests/helpers.py meson-0.61.2/unittests/helpers.py --- meson-0.53.2/unittests/helpers.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/helpers.py 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,186 @@ +import subprocess +import os +import shutil +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, + OrderedSet +) +from run_tests import get_fake_env + + +def is_ci(): + if 'MESON_CI_JOBNAME' in os.environ: + return True + return False + +def skip_if_not_base_option(feature): + """Skip tests if The compiler does not support a given base option. + + for example, ICC doesn't currently support b_sanitize. + """ + def actual(f): + @functools.wraps(f) + def wrapped(*args, **kwargs): + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + key = OptionKey(feature) + if key not in cc.base_options: + raise unittest.SkipTest( + f'{feature} not available with {cc.id}') + return f(*args, **kwargs) + return wrapped + return actual + +def skipIfNoPkgconfig(f): + ''' + Skip this test if no pkg-config is found, unless we're on CI. + This allows users to run our test suite without having + pkg-config installed on, f.ex., macOS, while ensuring that our CI does not + silently skip the test because of misconfiguration. + + Note: Yes, we provide pkg-config even while running Windows CI + ''' + @functools.wraps(f) + def wrapped(*args, **kwargs): + if not is_ci() and shutil.which('pkg-config') is None: + raise unittest.SkipTest('pkg-config not found') + return f(*args, **kwargs) + return wrapped + +def skipIfNoPkgconfigDep(depname): + ''' + Skip this test if the given pkg-config dep is not found, unless we're on CI. + ''' + def wrapper(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + if not is_ci() and shutil.which('pkg-config') is None: + raise unittest.SkipTest('pkg-config not found') + if not is_ci() and subprocess.call(['pkg-config', '--exists', depname]) != 0: + raise unittest.SkipTest(f'pkg-config dependency {depname} not found.') + return func(*args, **kwargs) + return wrapped + return wrapper + +def skip_if_no_cmake(f): + ''' + Skip this test if no cmake is found, unless we're on CI. + This allows users to run our test suite without having + cmake installed on, f.ex., macOS, while ensuring that our CI does not + silently skip the test because of misconfiguration. + ''' + @functools.wraps(f) + def wrapped(*args, **kwargs): + if not is_ci() and shutil.which('cmake') is None: + raise unittest.SkipTest('cmake not found') + return f(*args, **kwargs) + return wrapped + +def skip_if_not_language(lang: str): + def wrapper(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + try: + compiler_from_language(get_fake_env(), lang, MachineChoice.HOST) + except EnvironmentException: + raise unittest.SkipTest(f'No {lang} compiler found.') + return func(*args, **kwargs) + return wrapped + return wrapper + +def skip_if_env_set(key): + ''' + Skip a test if a particular env is set, except when running under CI + ''' + def wrapper(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + old = None + if key in os.environ: + if not is_ci(): + raise unittest.SkipTest(f'Env var {key!r} set, skipping') + old = os.environ.pop(key) + try: + return func(*args, **kwargs) + finally: + if old is not None: + os.environ[key] = old + return wrapped + return wrapper + +def skipIfNoExecutable(exename): + ''' + Skip this test if the given executable is not found. + ''' + def wrapper(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + if shutil.which(exename) is None: + raise unittest.SkipTest(exename + ' not found') + return func(*args, **kwargs) + return wrapped + return wrapper + +def is_tarball(): + if not os.path.isdir('docs'): + return True + return False + +@contextmanager +def chdir(path: str): + curdir = os.getcwd() + os.chdir(path) + try: + yield + finally: + os.chdir(curdir) + +def get_dynamic_section_entry(fname: str, entry: str) -> T.Optional[str]: + if is_cygwin() or is_osx(): + raise unittest.SkipTest('Test only applicable to ELF platforms') + + try: + raw_out = subprocess.check_output(['readelf', '-d', fname], + universal_newlines=True) + except FileNotFoundError: + # FIXME: Try using depfixer.py:Elf() as a fallback + raise unittest.SkipTest('readelf not found') + pattern = re.compile(entry + r': \[(.*?)\]') + for line in raw_out.split('\n'): + m = pattern.search(line) + if m is not None: + return str(m.group(1)) + return None # The file did not contain the specified entry. + +def get_soname(fname: str) -> T.Optional[str]: + return get_dynamic_section_entry(fname, 'soname') + +def get_rpath(fname: str) -> T.Optional[str]: + raw = get_dynamic_section_entry(fname, r'(?:rpath|runpath)') + # Get both '' and None here + if not raw: + return None + # nix/nixos adds a bunch of stuff to the rpath out of necessity that we + # 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 -Nru meson-0.53.2/unittests/internaltests.py meson-0.61.2/unittests/internaltests.py --- meson-0.53.2/unittests/internaltests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/internaltests.py 2021-12-26 16:24:25.000000000 +0000 @@ -0,0 +1,1608 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from configparser import ConfigParser +from mesonbuild.mesonlib.universal import OptionType +from pathlib import Path +from unittest import mock +import contextlib +import io +import json +import operator +import os +import pickle +import stat +import subprocess +import tempfile +import typing as T +import unittest + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.compilers +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.modules.gnome +from mesonbuild import coredata +from mesonbuild.interpreterbase import typed_pos_args, InvalidArguments, ObjectHolder +from mesonbuild.interpreterbase import typed_pos_args, InvalidArguments, typed_kwargs, ContainerTypeInfo, KwargInfo +from mesonbuild.mesonlib import ( + LibType, MachineChoice, PerMachine, Version, is_windows, is_osx, + is_cygwin, is_openbsd, search_version, MesonException, OptionKey, +) +from mesonbuild.interpreter.type_checking import in_set_validator, NoneType +from mesonbuild.dependencies import PkgConfigDependency +from mesonbuild.programs import ExternalProgram +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + FakeCompilerOptions, get_fake_env, get_fake_options +) + +from .helpers import * + +class InternalTests(unittest.TestCase): + + def test_version_number(self): + self.assertEqual(search_version('foobar 1.2.3'), '1.2.3') + self.assertEqual(search_version('1.2.3'), '1.2.3') + self.assertEqual(search_version('foobar 2016.10.28 1.2.3'), '1.2.3') + self.assertEqual(search_version('2016.10.28 1.2.3'), '1.2.3') + self.assertEqual(search_version('foobar 2016.10.128'), '2016.10.128') + self.assertEqual(search_version('2016.10.128'), '2016.10.128') + self.assertEqual(search_version('2016.10'), '2016.10') + self.assertEqual(search_version('2016.10 1.2.3'), '1.2.3') + self.assertEqual(search_version('oops v1.2.3'), '1.2.3') + self.assertEqual(search_version('2016.oops 1.2.3'), '1.2.3') + self.assertEqual(search_version('2016.x'), 'unknown version') + self.assertEqual(search_version(r'something version is \033[32;2m1.2.0\033[0m.'), '1.2.0') + + # Literal output of mvn + self.assertEqual(search_version(r'''\ + \033[1mApache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)\033[0m + Maven home: /nix/store/g84a9wnid2h1d3z2wfydy16dky73wh7i-apache-maven-3.8.1/maven + Java version: 11.0.10, vendor: Oracle Corporation, runtime: /nix/store/afsnl4ahmm9svvl7s1a0cj41vw4nkmz4-openjdk-11.0.10+9/lib/openjdk + Default locale: en_US, platform encoding: UTF-8 + OS name: "linux", version: "5.12.17", arch: "amd64", family: "unix"'''), + '3.8.1') + + def test_mode_symbolic_to_bits(self): + modefunc = mesonbuild.mesonlib.FileMode.perms_s_to_bits + self.assertEqual(modefunc('---------'), 0) + self.assertEqual(modefunc('r--------'), stat.S_IRUSR) + self.assertEqual(modefunc('---r-----'), stat.S_IRGRP) + self.assertEqual(modefunc('------r--'), stat.S_IROTH) + self.assertEqual(modefunc('-w-------'), stat.S_IWUSR) + self.assertEqual(modefunc('----w----'), stat.S_IWGRP) + self.assertEqual(modefunc('-------w-'), stat.S_IWOTH) + self.assertEqual(modefunc('--x------'), stat.S_IXUSR) + self.assertEqual(modefunc('-----x---'), stat.S_IXGRP) + self.assertEqual(modefunc('--------x'), stat.S_IXOTH) + self.assertEqual(modefunc('--S------'), stat.S_ISUID) + self.assertEqual(modefunc('-----S---'), stat.S_ISGID) + self.assertEqual(modefunc('--------T'), stat.S_ISVTX) + self.assertEqual(modefunc('--s------'), stat.S_ISUID | stat.S_IXUSR) + self.assertEqual(modefunc('-----s---'), stat.S_ISGID | stat.S_IXGRP) + self.assertEqual(modefunc('--------t'), stat.S_ISVTX | stat.S_IXOTH) + self.assertEqual(modefunc('rwx------'), stat.S_IRWXU) + self.assertEqual(modefunc('---rwx---'), stat.S_IRWXG) + self.assertEqual(modefunc('------rwx'), stat.S_IRWXO) + # We could keep listing combinations exhaustively but that seems + # tedious and pointless. Just test a few more. + self.assertEqual(modefunc('rwxr-xr-x'), + stat.S_IRWXU | + stat.S_IRGRP | stat.S_IXGRP | + stat.S_IROTH | stat.S_IXOTH) + self.assertEqual(modefunc('rw-r--r--'), + stat.S_IRUSR | stat.S_IWUSR | + stat.S_IRGRP | + stat.S_IROTH) + self.assertEqual(modefunc('rwsr-x---'), + stat.S_IRWXU | stat.S_ISUID | + stat.S_IRGRP | stat.S_IXGRP) + + def test_compiler_args_class_none_flush(self): + cc = mesonbuild.compilers.ClangCCompiler([], 'fake', MachineChoice.HOST, False, mock.Mock()) + a = cc.compiler_args(['-I.']) + #first we are checking if the tree construction deduplicates the correct -I argument + a += ['-I..'] + a += ['-I./tests/'] + a += ['-I./tests2/'] + #think this here as assertion, we cannot apply it, otherwise the CompilerArgs would already flush the changes: + # assertEqual(a, ['-I.', '-I./tests2/', '-I./tests/', '-I..', '-I.']) + a += ['-I.'] + a += ['-I.', '-I./tests/'] + self.assertEqual(a, ['-I.', '-I./tests/', '-I./tests2/', '-I..']) + + #then we are checking that when CompilerArgs already have a build container list, that the deduplication is taking the correct one + a += ['-I.', '-I./tests2/'] + self.assertEqual(a, ['-I.', '-I./tests2/', '-I./tests/', '-I..']) + + def test_compiler_args_class_d(self): + d = mesonbuild.compilers.DmdDCompiler([], 'fake', MachineChoice.HOST, 'info', 'arch') + # check include order is kept when deduplicating + a = d.compiler_args(['-Ifirst', '-Isecond', '-Ithird']) + a += ['-Ifirst'] + self.assertEqual(a, ['-Ifirst', '-Isecond', '-Ithird']) + + def test_compiler_args_class_clike(self): + cc = mesonbuild.compilers.ClangCCompiler([], 'fake', MachineChoice.HOST, False, mock.Mock()) + # Test that empty initialization works + a = cc.compiler_args() + self.assertEqual(a, []) + # Test that list initialization works + a = cc.compiler_args(['-I.', '-I..']) + self.assertEqual(a, ['-I.', '-I..']) + # Test that there is no de-dup on initialization + self.assertEqual(cc.compiler_args(['-I.', '-I.']), ['-I.', '-I.']) + + ## Test that appending works + a.append('-I..') + self.assertEqual(a, ['-I..', '-I.']) + a.append('-O3') + self.assertEqual(a, ['-I..', '-I.', '-O3']) + + ## Test that in-place addition works + a += ['-O2', '-O2'] + self.assertEqual(a, ['-I..', '-I.', '-O3', '-O2', '-O2']) + # Test that removal works + a.remove('-O2') + self.assertEqual(a, ['-I..', '-I.', '-O3', '-O2']) + # Test that de-dup happens on addition + a += ['-Ifoo', '-Ifoo'] + self.assertEqual(a, ['-Ifoo', '-I..', '-I.', '-O3', '-O2']) + + # .extend() is just +=, so we don't test it + + ## Test that addition works + # Test that adding a list with just one old arg works and yields the same array + a = a + ['-Ifoo'] + self.assertEqual(a, ['-Ifoo', '-I..', '-I.', '-O3', '-O2']) + # Test that adding a list with one arg new and one old works + a = a + ['-Ifoo', '-Ibaz'] + self.assertEqual(a, ['-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2']) + # Test that adding args that must be prepended and appended works + a = a + ['-Ibar', '-Wall'] + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) + + ## Test that reflected addition works + # Test that adding to a list with just one old arg works and yields the same array + a = ['-Ifoo'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) + # Test that adding to a list with just one new arg that is not pre-pended works + a = ['-Werror'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Werror', '-O3', '-O2', '-Wall']) + # Test that adding to a list with two new args preserves the order + a = ['-Ldir', '-Lbah'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) + # Test that adding to a list with old args does nothing + a = ['-Ibar', '-Ibaz', '-Ifoo'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) + + ## Test that adding libraries works + l = cc.compiler_args(['-Lfoodir', '-lfoo']) + self.assertEqual(l, ['-Lfoodir', '-lfoo']) + # Adding a library and a libpath appends both correctly + l += ['-Lbardir', '-lbar'] + self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar']) + # Adding the same library again does nothing + l += ['-lbar'] + self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar']) + + ## Test that 'direct' append and extend works + l = cc.compiler_args(['-Lfoodir', '-lfoo']) + self.assertEqual(l, ['-Lfoodir', '-lfoo']) + # Direct-adding a library and a libpath appends both correctly + l.extend_direct(['-Lbardir', '-lbar']) + self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar']) + # Direct-adding the same library again still adds it + l.append_direct('-lbar') + self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar']) + # Direct-adding with absolute path deduplicates + l.append_direct('/libbaz.a') + self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a']) + # Adding libbaz again does nothing + l.append_direct('/libbaz.a') + self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a']) + + def test_compiler_args_class_gnuld(self): + ## Test --start/end-group + linker = mesonbuild.linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) + gcc = mesonbuild.compilers.GnuCCompiler([], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker) + ## Ensure that the fake compiler is never called by overriding the relevant function + gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] + ## Test that 'direct' append and extend works + l = gcc.compiler_args(['-Lfoodir', '-lfoo']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group']) + # Direct-adding a library and a libpath appends both correctly + l.extend_direct(['-Lbardir', '-lbar']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-Wl,--end-group']) + # Direct-adding the same library again still adds it + l.append_direct('-lbar') + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '-Wl,--end-group']) + # Direct-adding with absolute path deduplicates + l.append_direct('/libbaz.a') + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group']) + # Adding libbaz again does nothing + l.append_direct('/libbaz.a') + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group']) + # Adding a non-library argument doesn't include it in the group + l += ['-Lfoo', '-Wl,--export-dynamic'] + self.assertEqual(l.to_native(copy=True), ['-Lfoo', '-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group', '-Wl,--export-dynamic']) + # -Wl,-lfoo is detected as a library and gets added to the group + l.append('-Wl,-ldl') + self.assertEqual(l.to_native(copy=True), ['-Lfoo', '-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--export-dynamic', '-Wl,-ldl', '-Wl,--end-group']) + + def test_compiler_args_remove_system(self): + ## Test --start/end-group + linker = mesonbuild.linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) + gcc = mesonbuild.compilers.GnuCCompiler([], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker) + ## Ensure that the fake compiler is never called by overriding the relevant function + gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] + ## Test that 'direct' append and extend works + l = gcc.compiler_args(['-Lfoodir', '-lfoo']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group']) + ## Test that to_native removes all system includes + l += ['-isystem/usr/include', '-isystem=/usr/share/include', '-DSOMETHING_IMPORTANT=1', '-isystem', '/usr/local/include'] + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group', '-DSOMETHING_IMPORTANT=1']) + + def test_string_templates_substitution(self): + dictfunc = mesonbuild.mesonlib.get_filenames_templates_dict + substfunc = mesonbuild.mesonlib.substitute_values + ME = mesonbuild.mesonlib.MesonException + + # Identity + self.assertEqual(dictfunc([], []), {}) + + # One input, no outputs + inputs = ['bar/foo.c.in'] + outputs = [] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c'} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@INPUT@.out', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out'] + cmd[1:]) + cmd = ['@INPUT0@.out', '@PLAINNAME@.ok', 'strings'] + self.assertEqual(substfunc(cmd, d), + [inputs[0] + '.out'] + [d['@PLAINNAME@'] + '.ok'] + cmd[2:]) + cmd = ['@INPUT@', '@BASENAME@.hah', 'strings'] + self.assertEqual(substfunc(cmd, d), + inputs + [d['@BASENAME@'] + '.hah'] + cmd[2:]) + cmd = ['@OUTPUT@'] + self.assertRaises(ME, substfunc, cmd, d) + + # One input, one output + inputs = ['bar/foo.c.in'] + outputs = ['out.c'] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c', + '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': '.'} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@INPUT@.out', '@OUTPUT@', 'strings'] + self.assertEqual(substfunc(cmd, d), + [inputs[0] + '.out'] + outputs + cmd[2:]) + cmd = ['@INPUT0@.out', '@PLAINNAME@.ok', '@OUTPUT0@'] + self.assertEqual(substfunc(cmd, d), + [inputs[0] + '.out', d['@PLAINNAME@'] + '.ok'] + outputs) + cmd = ['@INPUT@', '@BASENAME@.hah', 'strings'] + self.assertEqual(substfunc(cmd, d), + inputs + [d['@BASENAME@'] + '.hah'] + cmd[2:]) + + # One input, one output with a subdir + outputs = ['dir/out.c'] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c', + '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'} + # Check dictionary + self.assertEqual(ret, d) + + # Two inputs, no outputs + inputs = ['bar/foo.c.in', 'baz/foo.c.in'] + outputs = [] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1]} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@INPUT@', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), inputs + cmd[1:]) + cmd = ['@INPUT0@.out', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out'] + cmd[1:]) + cmd = ['@INPUT0@.out', '@INPUT1@.ok', 'strings'] + self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out', inputs[1] + '.ok'] + cmd[2:]) + cmd = ['@INPUT0@', '@INPUT1@', 'strings'] + self.assertEqual(substfunc(cmd, d), inputs + cmd[2:]) + # Many inputs, can't use @INPUT@ like this + cmd = ['@INPUT@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough inputs + cmd = ['@INPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Too many inputs + cmd = ['@PLAINNAME@'] + self.assertRaises(ME, substfunc, cmd, d) + cmd = ['@BASENAME@'] + self.assertRaises(ME, substfunc, cmd, d) + # No outputs + cmd = ['@OUTPUT@'] + self.assertRaises(ME, substfunc, cmd, d) + cmd = ['@OUTPUT0@'] + self.assertRaises(ME, substfunc, cmd, d) + cmd = ['@OUTDIR@'] + self.assertRaises(ME, substfunc, cmd, d) + + # Two inputs, one output + outputs = ['dir/out.c'] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], + '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@OUTPUT@', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), outputs + cmd[1:]) + cmd = ['@OUTPUT@.out', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out'] + cmd[1:]) + cmd = ['@OUTPUT0@.out', '@INPUT1@.ok', 'strings'] + self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out', inputs[1] + '.ok'] + cmd[2:]) + # Many inputs, can't use @INPUT@ like this + cmd = ['@INPUT@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough inputs + cmd = ['@INPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough outputs + cmd = ['@OUTPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + + # Two inputs, two outputs + outputs = ['dir/out.c', 'dir/out2.c'] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], + '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTPUT1@': outputs[1], + '@OUTDIR@': 'dir'} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@OUTPUT@', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), outputs + cmd[1:]) + cmd = ['@OUTPUT0@', '@OUTPUT1@', 'strings'] + self.assertEqual(substfunc(cmd, d), outputs + cmd[2:]) + cmd = ['@OUTPUT0@.out', '@INPUT1@.ok', '@OUTDIR@'] + self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out', inputs[1] + '.ok', 'dir']) + # Many inputs, can't use @INPUT@ like this + cmd = ['@INPUT@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough inputs + cmd = ['@INPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough outputs + cmd = ['@OUTPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Many outputs, can't use @OUTPUT@ like this + cmd = ['@OUTPUT@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + + def test_needs_exe_wrapper_override(self): + config = ConfigParser() + config['binaries'] = { + 'c': '\'/usr/bin/gcc\'', + } + config['host_machine'] = { + 'system': '\'linux\'', + 'cpu_family': '\'arm\'', + 'cpu': '\'armv7\'', + 'endian': '\'little\'', + } + # Can not be used as context manager because we need to + # open it a second time and this is not possible on + # Windows. + configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False) + configfilename = configfile.name + config.write(configfile) + configfile.flush() + configfile.close() + opts = get_fake_options() + opts.cross_file = (configfilename,) + env = get_fake_env(opts=opts) + detected_value = env.need_exe_wrapper() + os.unlink(configfilename) + + desired_value = not detected_value + config['properties'] = { + 'needs_exe_wrapper': 'true' if desired_value else 'false' + } + + configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False) + configfilename = configfile.name + config.write(configfile) + configfile.close() + opts = get_fake_options() + opts.cross_file = (configfilename,) + env = get_fake_env(opts=opts) + forced_value = env.need_exe_wrapper() + os.unlink(configfilename) + + self.assertEqual(forced_value, desired_value) + + def test_listify(self): + listify = mesonbuild.mesonlib.listify + # Test sanity + self.assertEqual([1], listify(1)) + self.assertEqual([], listify([])) + self.assertEqual([1], listify([1])) + # Test flattening + self.assertEqual([1, 2, 3], listify([1, [2, 3]])) + self.assertEqual([1, 2, 3], listify([1, [2, [3]]])) + self.assertEqual([1, [2, [3]]], listify([1, [2, [3]]], flatten=False)) + # Test flattening and unholdering + class TestHeldObj(mesonbuild.mesonlib.HoldableObject): + def __init__(self, val: int) -> None: + self._val = val + class MockInterpreter: + def __init__(self) -> None: + self.subproject = '' + self.environment = None + heldObj1 = TestHeldObj(1) + holder1 = ObjectHolder(heldObj1, MockInterpreter()) + self.assertEqual([holder1], listify(holder1)) + self.assertEqual([holder1], listify([holder1])) + self.assertEqual([holder1, 2], listify([holder1, 2])) + self.assertEqual([holder1, 2, 3], listify([holder1, 2, [3]])) + + def test_extract_as_list(self): + extract = mesonbuild.mesonlib.extract_as_list + # Test sanity + kwargs = {'sources': [1, 2, 3]} + self.assertEqual([1, 2, 3], extract(kwargs, 'sources')) + self.assertEqual(kwargs, {'sources': [1, 2, 3]}) + self.assertEqual([1, 2, 3], extract(kwargs, 'sources', pop=True)) + self.assertEqual(kwargs, {}) + + class TestHeldObj(mesonbuild.mesonlib.HoldableObject): + pass + class MockInterpreter: + def __init__(self) -> None: + self.subproject = '' + self.environment = None + heldObj = TestHeldObj() + + # Test unholding + holder3 = ObjectHolder(heldObj, MockInterpreter()) + kwargs = {'sources': [1, 2, holder3]} + self.assertEqual(kwargs, {'sources': [1, 2, holder3]}) + + # flatten nested lists + kwargs = {'sources': [1, [2, [3]]]} + self.assertEqual([1, 2, 3], extract(kwargs, 'sources')) + + def _test_all_naming(self, cc, env, patterns, platform): + shr = patterns[platform]['shared'] + stc = patterns[platform]['static'] + shrstc = shr + tuple(x for x in stc if x not in shr) + stcshr = stc + tuple(x for x in shr if x not in stc) + p = cc.get_library_naming(env, LibType.SHARED) + self.assertEqual(p, shr) + p = cc.get_library_naming(env, LibType.STATIC) + self.assertEqual(p, stc) + p = cc.get_library_naming(env, LibType.PREFER_STATIC) + self.assertEqual(p, stcshr) + p = cc.get_library_naming(env, LibType.PREFER_SHARED) + self.assertEqual(p, shrstc) + # Test find library by mocking up openbsd + if platform != 'openbsd': + return + with tempfile.TemporaryDirectory() as tmpdir: + for i in ['libfoo.so.6.0', 'libfoo.so.5.0', 'libfoo.so.54.0', 'libfoo.so.66a.0b', 'libfoo.so.70.0.so.1']: + libpath = Path(tmpdir) / i + libpath.write_text('', encoding='utf-8') + found = cc._find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED) + self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0') + + def test_find_library_patterns(self): + ''' + Unit test for the library search patterns used by find_library() + ''' + unix_static = ('lib{}.a', '{}.a') + msvc_static = ('lib{}.a', 'lib{}.lib', '{}.a', '{}.lib') + # This is the priority list of pattern matching for library searching + patterns = {'openbsd': {'shared': ('lib{}.so', '{}.so', 'lib{}.so.[0-9]*.[0-9]*', '{}.so.[0-9]*.[0-9]*'), + 'static': unix_static}, + 'linux': {'shared': ('lib{}.so', '{}.so'), + 'static': unix_static}, + 'darwin': {'shared': ('lib{}.dylib', 'lib{}.so', '{}.dylib', '{}.so'), + 'static': unix_static}, + 'cygwin': {'shared': ('cyg{}.dll', 'cyg{}.dll.a', 'lib{}.dll', + 'lib{}.dll.a', '{}.dll', '{}.dll.a'), + 'static': ('cyg{}.a',) + unix_static}, + 'windows-msvc': {'shared': ('lib{}.lib', '{}.lib'), + 'static': msvc_static}, + 'windows-mingw': {'shared': ('lib{}.dll.a', 'lib{}.lib', 'lib{}.dll', + '{}.dll.a', '{}.lib', '{}.dll'), + 'static': msvc_static}} + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if is_osx(): + self._test_all_naming(cc, env, patterns, 'darwin') + elif is_cygwin(): + self._test_all_naming(cc, env, patterns, 'cygwin') + elif is_windows(): + if cc.get_argument_syntax() == 'msvc': + self._test_all_naming(cc, env, patterns, 'windows-msvc') + else: + self._test_all_naming(cc, env, patterns, 'windows-mingw') + elif is_openbsd(): + self._test_all_naming(cc, env, patterns, 'openbsd') + else: + self._test_all_naming(cc, env, patterns, 'linux') + env.machines.host.system = 'openbsd' + self._test_all_naming(cc, env, patterns, 'openbsd') + env.machines.host.system = 'darwin' + self._test_all_naming(cc, env, patterns, 'darwin') + env.machines.host.system = 'cygwin' + self._test_all_naming(cc, env, patterns, 'cygwin') + env.machines.host.system = 'windows' + self._test_all_naming(cc, env, patterns, 'windows-mingw') + + @skipIfNoPkgconfig + def test_pkgconfig_parse_libs(self): + ''' + Unit test for parsing of pkg-config output to search for libraries + + https://github.com/mesonbuild/meson/issues/3951 + ''' + def create_static_lib(name): + if not is_osx(): + name.open('w', encoding='utf-8').close() + return + src = name.with_suffix('.c') + out = name.with_suffix('.o') + with src.open('w', encoding='utf-8') as f: + f.write('int meson_foobar (void) { return 0; }') + subprocess.check_call(['clang', '-c', str(src), '-o', str(out)]) + subprocess.check_call(['ar', 'csr', str(name), str(out)]) + + with tempfile.TemporaryDirectory() as tmpdir: + pkgbin = ExternalProgram('pkg-config', command=['pkg-config'], silent=True) + env = get_fake_env() + compiler = detect_c_compiler(env, MachineChoice.HOST) + env.coredata.compilers.host = {'c': compiler} + env.coredata.options[OptionKey('link_args', lang='c')] = FakeCompilerOptions() + p1 = Path(tmpdir) / '1' + p2 = Path(tmpdir) / '2' + p1.mkdir() + p2.mkdir() + # libfoo.a is in one prefix + create_static_lib(p1 / 'libfoo.a') + # libbar.a is in both prefixes + create_static_lib(p1 / 'libbar.a') + create_static_lib(p2 / 'libbar.a') + # Ensure that we never statically link to these + create_static_lib(p1 / 'libpthread.a') + create_static_lib(p1 / 'libm.a') + create_static_lib(p1 / 'libc.a') + create_static_lib(p1 / 'libdl.a') + create_static_lib(p1 / 'librt.a') + + def fake_call_pkgbin(self, args, env=None): + if '--libs' not in args: + return 0, '', '' + if args[-1] == 'foo': + return 0, f'-L{p2.as_posix()} -lfoo -L{p1.as_posix()} -lbar', '' + if args[-1] == 'bar': + return 0, f'-L{p2.as_posix()} -lbar', '' + if args[-1] == 'internal': + return 0, f'-L{p1.as_posix()} -lpthread -lm -lc -lrt -ldl', '' + + old_call = PkgConfigDependency._call_pkgbin + old_check = PkgConfigDependency.check_pkgconfig + PkgConfigDependency._call_pkgbin = fake_call_pkgbin + PkgConfigDependency.check_pkgconfig = lambda x, _: pkgbin + # Test begins + try: + kwargs = {'required': True, 'silent': True} + foo_dep = PkgConfigDependency('foo', env, kwargs) + self.assertEqual(foo_dep.get_link_args(), + [(p1 / 'libfoo.a').as_posix(), (p2 / 'libbar.a').as_posix()]) + bar_dep = PkgConfigDependency('bar', env, kwargs) + self.assertEqual(bar_dep.get_link_args(), [(p2 / 'libbar.a').as_posix()]) + internal_dep = PkgConfigDependency('internal', env, kwargs) + if compiler.get_argument_syntax() == 'msvc': + self.assertEqual(internal_dep.get_link_args(), []) + else: + link_args = internal_dep.get_link_args() + for link_arg in link_args: + for lib in ('pthread', 'm', 'c', 'dl', 'rt'): + self.assertNotIn(f'lib{lib}.a', link_arg, msg=link_args) + finally: + # Test ends + PkgConfigDependency._call_pkgbin = old_call + PkgConfigDependency.check_pkgconfig = old_check + # Reset dependency class to ensure that in-process configure doesn't mess up + PkgConfigDependency.pkgbin_cache = {} + PkgConfigDependency.class_pkgbin = PerMachine(None, None) + + def test_version_compare(self): + comparefunc = mesonbuild.mesonlib.version_compare_many + for (a, b, result) in [ + ('0.99.beta19', '>= 0.99.beta14', True), + ]: + self.assertEqual(comparefunc(a, b)[0], result) + + for (a, b, op) in [ + # examples from https://fedoraproject.org/wiki/Archive:Tools/RPM/VersionComparison + ("1.0010", "1.9", operator.gt), + ("1.05", "1.5", operator.eq), + ("1.0", "1", operator.gt), + ("2.50", "2.5", operator.gt), + ("fc4", "fc.4", operator.eq), + ("FC5", "fc4", operator.lt), + ("2a", "2.0", operator.lt), + ("1.0", "1.fc4", operator.gt), + ("3.0.0_fc", "3.0.0.fc", operator.eq), + # from RPM tests + ("1.0", "1.0", operator.eq), + ("1.0", "2.0", operator.lt), + ("2.0", "1.0", operator.gt), + ("2.0.1", "2.0.1", operator.eq), + ("2.0", "2.0.1", operator.lt), + ("2.0.1", "2.0", operator.gt), + ("2.0.1a", "2.0.1a", operator.eq), + ("2.0.1a", "2.0.1", operator.gt), + ("2.0.1", "2.0.1a", operator.lt), + ("5.5p1", "5.5p1", operator.eq), + ("5.5p1", "5.5p2", operator.lt), + ("5.5p2", "5.5p1", operator.gt), + ("5.5p10", "5.5p10", operator.eq), + ("5.5p1", "5.5p10", operator.lt), + ("5.5p10", "5.5p1", operator.gt), + ("10xyz", "10.1xyz", operator.lt), + ("10.1xyz", "10xyz", operator.gt), + ("xyz10", "xyz10", operator.eq), + ("xyz10", "xyz10.1", operator.lt), + ("xyz10.1", "xyz10", operator.gt), + ("xyz.4", "xyz.4", operator.eq), + ("xyz.4", "8", operator.lt), + ("8", "xyz.4", operator.gt), + ("xyz.4", "2", operator.lt), + ("2", "xyz.4", operator.gt), + ("5.5p2", "5.6p1", operator.lt), + ("5.6p1", "5.5p2", operator.gt), + ("5.6p1", "6.5p1", operator.lt), + ("6.5p1", "5.6p1", operator.gt), + ("6.0.rc1", "6.0", operator.gt), + ("6.0", "6.0.rc1", operator.lt), + ("10b2", "10a1", operator.gt), + ("10a2", "10b2", operator.lt), + ("1.0aa", "1.0aa", operator.eq), + ("1.0a", "1.0aa", operator.lt), + ("1.0aa", "1.0a", operator.gt), + ("10.0001", "10.0001", operator.eq), + ("10.0001", "10.1", operator.eq), + ("10.1", "10.0001", operator.eq), + ("10.0001", "10.0039", operator.lt), + ("10.0039", "10.0001", operator.gt), + ("4.999.9", "5.0", operator.lt), + ("5.0", "4.999.9", operator.gt), + ("20101121", "20101121", operator.eq), + ("20101121", "20101122", operator.lt), + ("20101122", "20101121", operator.gt), + ("2_0", "2_0", operator.eq), + ("2.0", "2_0", operator.eq), + ("2_0", "2.0", operator.eq), + ("a", "a", operator.eq), + ("a+", "a+", operator.eq), + ("a+", "a_", operator.eq), + ("a_", "a+", operator.eq), + ("+a", "+a", operator.eq), + ("+a", "_a", operator.eq), + ("_a", "+a", operator.eq), + ("+_", "+_", operator.eq), + ("_+", "+_", operator.eq), + ("_+", "_+", operator.eq), + ("+", "_", operator.eq), + ("_", "+", operator.eq), + # other tests + ('0.99.beta19', '0.99.beta14', operator.gt), + ("1.0.0", "2.0.0", operator.lt), + (".0.0", "2.0.0", operator.lt), + ("alpha", "beta", operator.lt), + ("1.0", "1.0.0", operator.lt), + ("2.456", "2.1000", operator.lt), + ("2.1000", "3.111", operator.lt), + ("2.001", "2.1", operator.eq), + ("2.34", "2.34", operator.eq), + ("6.1.2", "6.3.8", operator.lt), + ("1.7.3.0", "2.0.0", operator.lt), + ("2.24.51", "2.25", operator.lt), + ("2.1.5+20120813+gitdcbe778", "2.1.5", operator.gt), + ("3.4.1", "3.4b1", operator.gt), + ("041206", "200090325", operator.lt), + ("0.6.2+git20130413", "0.6.2", operator.gt), + ("2.6.0+bzr6602", "2.6.0", operator.gt), + ("2.6.0", "2.6b2", operator.gt), + ("2.6.0+bzr6602", "2.6b2x", operator.gt), + ("0.6.7+20150214+git3a710f9", "0.6.7", operator.gt), + ("15.8b", "15.8.0.1", operator.lt), + ("1.2rc1", "1.2.0", operator.lt), + ]: + ver_a = Version(a) + ver_b = Version(b) + if op is operator.eq: + for o, name in [(op, 'eq'), (operator.ge, 'ge'), (operator.le, 'le')]: + self.assertTrue(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + if op is operator.lt: + for o, name in [(op, 'lt'), (operator.le, 'le'), (operator.ne, 'ne')]: + self.assertTrue(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + for o, name in [(operator.gt, 'gt'), (operator.ge, 'ge'), (operator.eq, 'eq')]: + self.assertFalse(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + if op is operator.gt: + for o, name in [(op, 'gt'), (operator.ge, 'ge'), (operator.ne, 'ne')]: + self.assertTrue(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + for o, name in [(operator.lt, 'lt'), (operator.le, 'le'), (operator.eq, 'eq')]: + self.assertFalse(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + + def test_msvc_toolset_version(self): + ''' + Ensure that the toolset version returns the correct value for this MSVC + ''' + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise unittest.SkipTest('Test only applies to MSVC-like compilers') + toolset_ver = cc.get_toolset_version() + self.assertIsNotNone(toolset_ver) + # Visual Studio 2015 and older versions do not define VCToolsVersion + # TODO: ICL doesn't set this in the VSC2015 profile either + if cc.id == 'msvc' and int(''.join(cc.version.split('.')[0:2])) < 1910: + return + if 'VCToolsVersion' in os.environ: + vctools_ver = os.environ['VCToolsVersion'] + else: + self.assertIn('VCINSTALLDIR', os.environ) + # See https://devblogs.microsoft.com/cppblog/finding-the-visual-c-compiler-tools-in-visual-studio-2017/ + vctools_ver = (Path(os.environ['VCINSTALLDIR']) / 'Auxiliary' / 'Build' / 'Microsoft.VCToolsVersion.default.txt').read_text(encoding='utf-8') + self.assertTrue(vctools_ver.startswith(toolset_ver), + msg=f'{vctools_ver!r} does not start with {toolset_ver!r}') + + def test_split_args(self): + split_args = mesonbuild.mesonlib.split_args + join_args = mesonbuild.mesonlib.join_args + if is_windows(): + test_data = [ + # examples from https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments + (r'"a b c" d e', ['a b c', 'd', 'e'], True), + (r'"ab\"c" "\\" d', ['ab"c', '\\', 'd'], False), + (r'a\\\b d"e f"g h', [r'a\\\b', 'de fg', 'h'], False), + (r'a\\\"b c d', [r'a\"b', 'c', 'd'], False), + (r'a\\\\"b c" d e', [r'a\\b c', 'd', 'e'], False), + # other basics + (r'""', [''], True), + (r'a b c d "" e', ['a', 'b', 'c', 'd', '', 'e'], True), + (r"'a b c' d e", ["'a", 'b', "c'", 'd', 'e'], True), + (r"'a&b&c' d e", ["'a&b&c'", 'd', 'e'], True), + (r"a & b & c d e", ['a', '&', 'b', '&', 'c', 'd', 'e'], True), + (r"'a & b & c d e'", ["'a", '&', 'b', '&', 'c', 'd', "e'"], True), + ('a b\nc\rd \n\re', ['a', 'b', 'c', 'd', 'e'], False), + # more illustrative tests + (r'cl test.cpp /O1 /Fe:test.exe', ['cl', 'test.cpp', '/O1', '/Fe:test.exe'], True), + (r'cl "test.cpp /O1 /Fe:test.exe"', ['cl', 'test.cpp /O1 /Fe:test.exe'], True), + (r'cl /DNAME=\"Bob\" test.cpp', ['cl', '/DNAME="Bob"', 'test.cpp'], False), + (r'cl "/DNAME=\"Bob\"" test.cpp', ['cl', '/DNAME="Bob"', 'test.cpp'], True), + (r'cl /DNAME=\"Bob, Alice\" test.cpp', ['cl', '/DNAME="Bob,', 'Alice"', 'test.cpp'], False), + (r'cl "/DNAME=\"Bob, Alice\"" test.cpp', ['cl', '/DNAME="Bob, Alice"', 'test.cpp'], True), + (r'cl C:\path\with\backslashes.cpp', ['cl', r'C:\path\with\backslashes.cpp'], True), + (r'cl C:\\path\\with\\double\\backslashes.cpp', ['cl', r'C:\\path\\with\\double\\backslashes.cpp'], True), + (r'cl "C:\\path\\with\\double\\backslashes.cpp"', ['cl', r'C:\\path\\with\\double\\backslashes.cpp'], False), + (r'cl C:\path with spaces\test.cpp', ['cl', r'C:\path', 'with', r'spaces\test.cpp'], False), + (r'cl "C:\path with spaces\test.cpp"', ['cl', r'C:\path with spaces\test.cpp'], True), + (r'cl /DPATH="C:\path\with\backslashes test.cpp', ['cl', r'/DPATH=C:\path\with\backslashes test.cpp'], False), + (r'cl /DPATH=\"C:\\ends\\with\\backslashes\\\" test.cpp', ['cl', r'/DPATH="C:\\ends\\with\\backslashes\"', 'test.cpp'], False), + (r'cl /DPATH="C:\\ends\\with\\backslashes\\" test.cpp', ['cl', '/DPATH=C:\\\\ends\\\\with\\\\backslashes\\', 'test.cpp'], False), + (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\"', 'test.cpp'], True), + (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\\ test.cpp'], False), + (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\\"', 'test.cpp'], True), + ] + else: + test_data = [ + (r"'a b c' d e", ['a b c', 'd', 'e'], True), + (r"a/b/c d e", ['a/b/c', 'd', 'e'], True), + (r"a\b\c d e", [r'abc', 'd', 'e'], False), + (r"a\\b\\c d e", [r'a\b\c', 'd', 'e'], False), + (r'"a b c" d e', ['a b c', 'd', 'e'], False), + (r'"a\\b\\c\\" d e', ['a\\b\\c\\', 'd', 'e'], False), + (r"'a\b\c\' d e", ['a\\b\\c\\', 'd', 'e'], True), + (r"'a&b&c' d e", ['a&b&c', 'd', 'e'], True), + (r"a & b & c d e", ['a', '&', 'b', '&', 'c', 'd', 'e'], False), + (r"'a & b & c d e'", ['a & b & c d e'], True), + (r"abd'e f'g h", [r'abde fg', 'h'], False), + ('a b\nc\rd \n\re', ['a', 'b', 'c', 'd', 'e'], False), + + ('g++ -DNAME="Bob" test.cpp', ['g++', '-DNAME=Bob', 'test.cpp'], False), + ("g++ '-DNAME=\"Bob\"' test.cpp", ['g++', '-DNAME="Bob"', 'test.cpp'], True), + ('g++ -DNAME="Bob, Alice" test.cpp', ['g++', '-DNAME=Bob, Alice', 'test.cpp'], False), + ("g++ '-DNAME=\"Bob, Alice\"' test.cpp", ['g++', '-DNAME="Bob, Alice"', 'test.cpp'], True), + ] + + for (cmd, expected, roundtrip) in test_data: + self.assertEqual(split_args(cmd), expected) + if roundtrip: + self.assertEqual(join_args(expected), cmd) + + def test_quote_arg(self): + split_args = mesonbuild.mesonlib.split_args + quote_arg = mesonbuild.mesonlib.quote_arg + if is_windows(): + test_data = [ + ('', '""'), + ('arg1', 'arg1'), + ('/option1', '/option1'), + ('/Ovalue', '/Ovalue'), + ('/OBob&Alice', '/OBob&Alice'), + ('/Ovalue with spaces', r'"/Ovalue with spaces"'), + (r'/O"value with spaces"', r'"/O\"value with spaces\""'), + (r'/OC:\path with spaces\test.exe', r'"/OC:\path with spaces\test.exe"'), + ('/LIBPATH:C:\\path with spaces\\ends\\with\\backslashes\\', r'"/LIBPATH:C:\path with spaces\ends\with\backslashes\\"'), + ('/LIBPATH:"C:\\path with spaces\\ends\\with\\backslashes\\\\"', r'"/LIBPATH:\"C:\path with spaces\ends\with\backslashes\\\\\""'), + (r'/DMSG="Alice said: \"Let\'s go\""', r'"/DMSG=\"Alice said: \\\"Let\'s go\\\"\""'), + ] + else: + test_data = [ + ('arg1', 'arg1'), + ('--option1', '--option1'), + ('-O=value', '-O=value'), + ('-O=Bob&Alice', "'-O=Bob&Alice'"), + ('-O=value with spaces', "'-O=value with spaces'"), + ('-O="value with spaces"', '\'-O=\"value with spaces\"\''), + ('-O=/path with spaces/test', '\'-O=/path with spaces/test\''), + ('-DMSG="Alice said: \\"Let\'s go\\""', "'-DMSG=\"Alice said: \\\"Let'\"'\"'s go\\\"\"'"), + ] + + for (arg, expected) in test_data: + self.assertEqual(quote_arg(arg), expected) + self.assertEqual(split_args(expected)[0], arg) + + def test_depfile(self): + for (f, target, expdeps) in [ + # empty, unknown target + ([''], 'unknown', set()), + # simple target & deps + (['meson/foo.o : foo.c foo.h'], 'meson/foo.o', set({'foo.c', 'foo.h'})), + (['meson/foo.o: foo.c foo.h'], 'foo.c', set()), + # get all deps + (['meson/foo.o: foo.c foo.h', + 'foo.c: gen.py'], 'meson/foo.o', set({'foo.c', 'foo.h', 'gen.py'})), + (['meson/foo.o: foo.c foo.h', + 'foo.c: gen.py'], 'foo.c', set({'gen.py'})), + # linue continuation, multiple targets + (['foo.o \\', 'foo.h: bar'], 'foo.h', set({'bar'})), + (['foo.o \\', 'foo.h: bar'], 'foo.o', set({'bar'})), + # \\ handling + (['foo: Program\\ F\\iles\\\\X'], 'foo', set({'Program Files\\X'})), + # $ handling + (['f$o.o: c/b'], 'f$o.o', set({'c/b'})), + (['f$$o.o: c/b'], 'f$o.o', set({'c/b'})), + # cycles + (['a: b', 'b: a'], 'a', set({'a', 'b'})), + (['a: b', 'b: a'], 'b', set({'a', 'b'})), + ]: + d = mesonbuild.depfile.DepFile(f) + deps = d.get_all_dependencies(target) + self.assertEqual(sorted(deps), sorted(expdeps)) + + def test_log_once(self): + f = io.StringIO() + with mock.patch('mesonbuild.mlog.log_file', f), \ + mock.patch('mesonbuild.mlog._logged_once', set()): + mesonbuild.mlog.log_once('foo') + mesonbuild.mlog.log_once('foo') + actual = f.getvalue().strip() + self.assertEqual(actual, 'foo', actual) + + def test_log_once_ansi(self): + f = io.StringIO() + with mock.patch('mesonbuild.mlog.log_file', f), \ + mock.patch('mesonbuild.mlog._logged_once', set()): + mesonbuild.mlog.log_once(mesonbuild.mlog.bold('foo')) + mesonbuild.mlog.log_once(mesonbuild.mlog.bold('foo')) + actual = f.getvalue().strip() + self.assertEqual(actual.count('foo'), 1, actual) + + mesonbuild.mlog.log_once('foo') + actual = f.getvalue().strip() + self.assertEqual(actual.count('foo'), 1, actual) + + f.truncate() + + mesonbuild.mlog.warning('bar', once=True) + mesonbuild.mlog.warning('bar', once=True) + actual = f.getvalue().strip() + self.assertEqual(actual.count('bar'), 1, actual) + + def test_sort_libpaths(self): + sort_libpaths = mesonbuild.dependencies.base.sort_libpaths + self.assertEqual(sort_libpaths( + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib'], + ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) + self.assertEqual(sort_libpaths( + ['/usr/local/lib', '/home/mesonuser/.local/lib', '/usr/lib'], + ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) + self.assertEqual(sort_libpaths( + ['/usr/lib', '/usr/local/lib', '/home/mesonuser/.local/lib'], + ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) + self.assertEqual(sort_libpaths( + ['/usr/lib', '/usr/local/lib', '/home/mesonuser/.local/lib'], + ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/libdata/pkgconfig']), + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) + + def test_dependency_factory_order(self): + b = mesonbuild.dependencies.base + F = mesonbuild.dependencies.factory + with tempfile.TemporaryDirectory() as tmpdir: + with chdir(tmpdir): + env = get_fake_env() + env.scratch_dir = tmpdir + + f = F.DependencyFactory( + 'test_dep', + methods=[b.DependencyMethods.PKGCONFIG, b.DependencyMethods.CMAKE] + ) + actual = [m() for m in f(env, MachineChoice.HOST, {'required': False})] + self.assertListEqual([m.type_name for m in actual], ['pkgconfig', 'cmake']) + + f = F.DependencyFactory( + 'test_dep', + methods=[b.DependencyMethods.CMAKE, b.DependencyMethods.PKGCONFIG] + ) + actual = [m() for m in f(env, MachineChoice.HOST, {'required': False})] + self.assertListEqual([m.type_name for m in actual], ['cmake', 'pkgconfig']) + + def test_validate_json(self) -> None: + """Validate the json schema for the test cases.""" + try: + from jsonschema import validate, ValidationError + except ImportError: + if is_ci(): + raise + raise unittest.SkipTest('Python jsonschema module not found.') + + schema = json.loads(Path('data/test.schema.json').read_text(encoding='utf-8')) + + errors = [] # type: T.Tuple[str, Exception] + for p in Path('test cases').glob('**/test.json'): + try: + validate(json.loads(p.read_text(encoding='utf-8')), schema=schema) + except ValidationError as e: + errors.append((p.resolve(), e)) + + for f, e in errors: + print(f'Failed to validate: "{f}"') + print(str(e)) + + self.assertFalse(errors) + + def test_typed_pos_args_types(self) -> None: + @typed_pos_args('foo', str, int, bool) + def _(obj, node, args: T.Tuple[str, int, bool], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], str) + self.assertIsInstance(args[1], int) + self.assertIsInstance(args[2], bool) + + _(None, mock.Mock(), ['string', 1, False], None) + + def test_typed_pos_args_types_invalid(self) -> None: + @typed_pos_args('foo', str, int, bool) + def _(obj, node, args: T.Tuple[str, int, bool], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 1.0, False], None) + self.assertEqual(str(cm.exception), 'foo argument 2 was of type "float" but should have been "int"') + + def test_typed_pos_args_types_wrong_number(self) -> None: + @typed_pos_args('foo', str, int, bool) + def _(obj, node, args: T.Tuple[str, int, bool], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 1], None) + self.assertEqual(str(cm.exception), 'foo takes exactly 3 arguments, but got 2.') + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 1, True, True], None) + self.assertEqual(str(cm.exception), 'foo takes exactly 3 arguments, but got 4.') + + def test_typed_pos_args_varargs(self) -> None: + @typed_pos_args('foo', str, varargs=str) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], str) + self.assertIsInstance(args[1], list) + self.assertIsInstance(args[1][0], str) + self.assertIsInstance(args[1][1], str) + + _(None, mock.Mock(), ['string', 'var', 'args'], None) + + def test_typed_pos_args_varargs_not_given(self) -> None: + @typed_pos_args('foo', str, varargs=str) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], str) + self.assertIsInstance(args[1], list) + self.assertEqual(args[1], []) + + _(None, mock.Mock(), ['string'], None) + + def test_typed_pos_args_varargs_invalid(self) -> None: + @typed_pos_args('foo', str, varargs=str) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 'var', 'args', 0], None) + self.assertEqual(str(cm.exception), 'foo argument 4 was of type "int" but should have been "str"') + + def test_typed_pos_args_varargs_invalid_mulitple_types(self) -> None: + @typed_pos_args('foo', str, varargs=(str, list)) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 'var', 'args', 0], None) + self.assertEqual(str(cm.exception), 'foo argument 4 was of type "int" but should have been one of: "str", "list"') + + def test_typed_pos_args_max_varargs(self) -> None: + @typed_pos_args('foo', str, varargs=str, max_varargs=5) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], str) + self.assertIsInstance(args[1], list) + self.assertIsInstance(args[1][0], str) + self.assertIsInstance(args[1][1], str) + + _(None, mock.Mock(), ['string', 'var', 'args'], None) + + def test_typed_pos_args_max_varargs_exceeded(self) -> None: + @typed_pos_args('foo', str, varargs=str, max_varargs=1) + def _(obj, node, args: T.Tuple[str, T.Tuple[str, ...]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 'var', 'args'], None) + self.assertEqual(str(cm.exception), 'foo takes between 1 and 2 arguments, but got 3.') + + def test_typed_pos_args_min_varargs(self) -> None: + @typed_pos_args('foo', varargs=str, max_varargs=2, min_varargs=1) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], list) + self.assertIsInstance(args[0][0], str) + self.assertIsInstance(args[0][1], str) + + _(None, mock.Mock(), ['string', 'var'], None) + + def test_typed_pos_args_min_varargs_not_met(self) -> None: + @typed_pos_args('foo', str, varargs=str, min_varargs=1) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string'], None) + self.assertEqual(str(cm.exception), 'foo takes at least 2 arguments, but got 1.') + + def test_typed_pos_args_min_and_max_varargs_exceeded(self) -> None: + @typed_pos_args('foo', str, varargs=str, min_varargs=1, max_varargs=2) + def _(obj, node, args: T.Tuple[str, T.Tuple[str, ...]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 'var', 'args', 'bar'], None) + self.assertEqual(str(cm.exception), 'foo takes between 2 and 3 arguments, but got 4.') + + def test_typed_pos_args_min_and_max_varargs_not_met(self) -> None: + @typed_pos_args('foo', str, varargs=str, min_varargs=1, max_varargs=2) + def _(obj, node, args: T.Tuple[str, T.Tuple[str, ...]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string'], None) + self.assertEqual(str(cm.exception), 'foo takes between 2 and 3 arguments, but got 1.') + + def test_typed_pos_args_variadic_and_optional(self) -> None: + @typed_pos_args('foo', str, optargs=[str], varargs=str, min_varargs=0) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(AssertionError) as cm: + _(None, mock.Mock(), ['string'], None) + self.assertEqual( + str(cm.exception), + 'varargs and optargs not supported together as this would be ambiguous') + + def test_typed_pos_args_min_optargs_not_met(self) -> None: + @typed_pos_args('foo', str, str, optargs=[str]) + def _(obj, node, args: T.Tuple[str, T.Optional[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string'], None) + self.assertEqual(str(cm.exception), 'foo takes at least 2 arguments, but got 1.') + + def test_typed_pos_args_min_optargs_max_exceeded(self) -> None: + @typed_pos_args('foo', str, optargs=[str]) + def _(obj, node, args: T.Tuple[str, T.Optional[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', '1', '2'], None) + self.assertEqual(str(cm.exception), 'foo takes at most 2 arguments, but got 3.') + + def test_typed_pos_args_optargs_not_given(self) -> None: + @typed_pos_args('foo', str, optargs=[str]) + def _(obj, node, args: T.Tuple[str, T.Optional[str]], kwargs) -> None: + self.assertEqual(len(args), 2) + self.assertIsInstance(args[0], str) + self.assertEqual(args[0], 'string') + self.assertIsNone(args[1]) + + _(None, mock.Mock(), ['string'], None) + + def test_typed_pos_args_optargs_some_given(self) -> None: + @typed_pos_args('foo', str, optargs=[str, int]) + def _(obj, node, args: T.Tuple[str, T.Optional[str], T.Optional[int]], kwargs) -> None: + self.assertEqual(len(args), 3) + self.assertIsInstance(args[0], str) + self.assertEqual(args[0], 'string') + self.assertIsInstance(args[1], str) + self.assertEqual(args[1], '1') + self.assertIsNone(args[2]) + + _(None, mock.Mock(), ['string', '1'], None) + + def test_typed_pos_args_optargs_all_given(self) -> None: + @typed_pos_args('foo', str, optargs=[str]) + def _(obj, node, args: T.Tuple[str, T.Optional[str]], kwargs) -> None: + self.assertEqual(len(args), 2) + self.assertIsInstance(args[0], str) + self.assertEqual(args[0], 'string') + self.assertIsInstance(args[1], str) + + _(None, mock.Mock(), ['string', '1'], None) + + def test_typed_kwarg_basic(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, default='') + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertIsInstance(kwargs['input'], str) + self.assertEqual(kwargs['input'], 'foo') + + _(None, mock.Mock(), [], {'input': 'foo'}) + + def test_typed_kwarg_missing_required(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, required=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertTrue(False) # should be unreachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), [], {}) + self.assertEqual(str(cm.exception), 'testfunc is missing required keyword argument "input"') + + def test_typed_kwarg_missing_optional(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', (str, type(None))), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.Optional[str]]) -> None: + self.assertIsNone(kwargs['input']) + + _(None, mock.Mock(), [], {}) + + def test_typed_kwarg_default(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, default='default'), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertEqual(kwargs['input'], 'default') + + _(None, mock.Mock(), [], {}) + + def test_typed_kwarg_container_valid(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), default=[], required=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertEqual(kwargs['input'], ['str']) + + _(None, mock.Mock(), [], {'input': ['str']}) + + def test_typed_kwarg_container_invalid(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), required=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertTrue(False) # should be unreachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), [], {'input': {}}) + self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type dict[] but should have been array[str]") + + def test_typed_kwarg_contained_invalid(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(dict, str), required=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.Dict[str, str]]) -> None: + self.assertTrue(False) # should be unreachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), [], {'input': {'key': 1, 'bar': 2}}) + self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type dict[int] but should have been dict[str]") + + def test_typed_kwarg_container_listify(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), default=[], listify=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertEqual(kwargs['input'], ['str']) + + _(None, mock.Mock(), [], {'input': 'str'}) + + def test_typed_kwarg_container_default_copy(self) -> None: + default: T.List[str] = [] + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), listify=True, default=default), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertIsNot(kwargs['input'], default) + + _(None, mock.Mock(), [], {}) + + def test_typed_kwarg_container_pairs(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str, pairs=True), listify=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertEqual(kwargs['input'], ['a', 'b']) + + _(None, mock.Mock(), [], {'input': ['a', 'b']}) + + with self.assertRaises(MesonException) as cm: + _(None, mock.Mock(), [], {'input': ['a']}) + self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type array[str] but should have been array[str] that has even size") + + def test_typed_kwarg_since(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, since='1.0', since_message='Its awesome, use it', + deprecated='2.0', deprecated_message='Its terrible, dont use it') + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertIsInstance(kwargs['input'], str) + self.assertEqual(kwargs['input'], 'foo') + + with self.subTest('use before available'), \ + mock.patch('sys.stdout', io.StringIO()) as out, \ + mock.patch('mesonbuild.mesonlib.project_meson_versions', {'': '0.1'}): + # With Meson 0.1 it should trigger the "introduced" warning but not the "deprecated" warning + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertRegex(out.getvalue(), r'WARNING:.*introduced.*input arg in testfunc. Its awesome, use it') + self.assertNotRegex(out.getvalue(), r'WARNING:.*deprecated.*input arg in testfunc. Its terrible, dont use it') + + with self.subTest('no warnings should be triggered'), \ + mock.patch('sys.stdout', io.StringIO()) as out, \ + mock.patch('mesonbuild.mesonlib.project_meson_versions', {'': '1.5'}): + # With Meson 1.5 it shouldn't trigger any warning + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertNotRegex(out.getvalue(), r'WARNING:.*') + + with self.subTest('use after deprecated'), \ + mock.patch('sys.stdout', io.StringIO()) as out, \ + mock.patch('mesonbuild.mesonlib.project_meson_versions', {'': '2.0'}): + # With Meson 2.0 it should trigger the "deprecated" warning but not the "introduced" warning + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertRegex(out.getvalue(), r'WARNING:.*deprecated.*input arg in testfunc. Its terrible, dont use it') + self.assertNotRegex(out.getvalue(), r'WARNING:.*introduced.*input arg in testfunc. Its awesome, use it') + + def test_typed_kwarg_validator(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, default='', validator=lambda x: 'invalid!' if x != 'foo' else None) + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + pass + + # Should be valid + _(None, mock.Mock(), tuple(), dict(input='foo')) + + with self.assertRaises(MesonException) as cm: + _(None, mock.Mock(), tuple(), dict(input='bar')) + self.assertEqual(str(cm.exception), "testfunc keyword argument \"input\" invalid!") + + def test_typed_kwarg_convertor(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('native', bool, default=False, convertor=lambda n: MachineChoice.BUILD if n else MachineChoice.HOST) + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, MachineChoice]) -> None: + assert isinstance(kwargs['native'], MachineChoice) + + _(None, mock.Mock(), tuple(), dict(native=True)) + + @mock.patch('mesonbuild.mesonlib.project_meson_versions', {'': '1.0'}) + def test_typed_kwarg_since_values(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), listify=True, default=[], deprecated_values={'foo': '0.9'}, since_values={'bar': '1.1'}), + KwargInfo('output', ContainerTypeInfo(dict, str), default={}, deprecated_values={'foo': '0.9', 'foo2': ('0.9', 'dont use it')}, since_values={'bar': '1.1', 'bar2': ('1.1', 'use this')}), + KwargInfo('install_dir', (bool, str, NoneType), deprecated_values={False: '0.9'}), + KwargInfo( + 'mode', + (str, type(None)), + validator=in_set_validator({'clean', 'build', 'rebuild', 'deprecated', 'since'}), + deprecated_values={'deprecated': '1.0'}, + since_values={'since': '1.1'}), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + pass + + with self.subTest('deprecated array string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'input': ['foo']}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*deprecated since '0.9': "testfunc" keyword argument "input" value "foo".*""") + + with self.subTest('new array string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'input': ['bar']}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*introduced in '1.1': "testfunc" keyword argument "input" value "bar".*""") + + with self.subTest('deprecated dict string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'output': {'foo': 'a'}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*deprecated since '0.9': "testfunc" keyword argument "output" value "foo".*""") + + with self.subTest('deprecated dict string value with msg'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'output': {'foo2': 'a'}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*deprecated since '0.9': "testfunc" keyword argument "output" value "foo2". dont use it.*""") + + with self.subTest('new dict string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'output': {'bar': 'b'}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*introduced in '1.1': "testfunc" keyword argument "output" value "bar".*""") + + with self.subTest('new dict string value with msg'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'output': {'bar2': 'a'}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*introduced in '1.1': "testfunc" keyword argument "output" value "bar2". use this.*""") + + with self.subTest('non string union'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'install_dir': False}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*deprecated since '0.9': "testfunc" keyword argument "install_dir" value "False".*""") + + with self.subTest('deprecated string union'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'mode': 'deprecated'}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*deprecated since '1.0': "testfunc" keyword argument "mode" value "deprecated".*""") + + with self.subTest('new string union'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'mode': 'since'}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*introduced in '1.1': "testfunc" keyword argument "mode" value "since".*""") + + def test_typed_kwarg_evolve(self) -> None: + k = KwargInfo('foo', str, required=True, default='foo') + v = k.evolve(default='bar') + self.assertEqual(k.name, 'foo') + self.assertEqual(k.name, v.name) + self.assertEqual(k.types, str) + self.assertEqual(k.types, v.types) + self.assertEqual(k.required, True) + self.assertEqual(k.required, v.required) + self.assertEqual(k.default, 'foo') + self.assertEqual(v.default, 'bar') + + def test_typed_kwarg_default_type(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('no_default', (str, ContainerTypeInfo(list, str), NoneType)), + KwargInfo('str_default', (str, ContainerTypeInfo(list, str)), default=''), + KwargInfo('list_default', (str, ContainerTypeInfo(list, str)), default=['']), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertEqual(kwargs['no_default'], None) + self.assertEqual(kwargs['str_default'], '') + self.assertEqual(kwargs['list_default'], ['']) + _(None, mock.Mock(), [], {}) + + def test_typed_kwarg_invalid_default_type(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('invalid_default', (str, ContainerTypeInfo(list, str), NoneType), default=42), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + pass + self.assertRaises(AssertionError, _, None, mock.Mock(), [], {}) + + def test_typed_kwarg_container_in_tuple(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', (str, ContainerTypeInfo(list, str))), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertEqual(kwargs['input'], args[0]) + _(None, mock.Mock(), [''], {'input': ''}) + _(None, mock.Mock(), [['']], {'input': ['']}) + self.assertRaises(InvalidArguments, _, None, mock.Mock(), [], {'input': 42}) + + def test_detect_cpu_family(self) -> None: + """Test the various cpu families that we detect and normalize. + + This is particularly useful as both documentation, and to keep testing + platforms that are less common. + """ + + @contextlib.contextmanager + def mock_trial(value: str) -> T.Iterable[None]: + """Mock all of the ways we could get the trial at once.""" + mocked = mock.Mock(return_value=value) + + with mock.patch('mesonbuild.environment.detect_windows_arch', mocked), \ + mock.patch('mesonbuild.environment.platform.processor', mocked), \ + mock.patch('mesonbuild.environment.platform.machine', mocked): + yield + + cases = [ + ('x86', 'x86'), + ('i386', 'x86'), + ('bepc', 'x86'), # Haiku + ('earm', 'arm'), # NetBSD + ('arm', 'arm'), + ('ppc64', 'ppc64'), + ('powerpc64', 'ppc64'), + ('powerpc', 'ppc'), + ('ppc', 'ppc'), + ('macppc', 'ppc'), + ('power macintosh', 'ppc'), + ('mips64el', 'mips64'), + ('mips64', 'mips64'), + ('mips', 'mips'), + ('mipsel', 'mips'), + ('ip30', 'mips64'), + ('ip35', 'mips64'), + ('parisc64', 'parisc'), + ('sun4u', 'sparc64'), + ('sun4v', 'sparc64'), + ('amd64', 'x86_64'), + ('x64', 'x86_64'), + ('i86pc', 'x86_64'), # Solaris + ('aarch64', 'aarch64'), + ('aarch64_be', 'aarch64'), + ] + + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)): + for test, expected in cases: + with self.subTest(test, has_define=False), mock_trial(test): + actual = mesonbuild.environment.detect_cpu_family({}) + self.assertEqual(actual, expected) + + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)): + for test, expected in [('x86_64', 'x86'), ('aarch64', 'arm'), ('ppc', 'ppc64')]: + with self.subTest(test, has_define=True), mock_trial(test): + actual = mesonbuild.environment.detect_cpu_family({}) + self.assertEqual(actual, expected) + + def test_detect_cpu(self) -> None: + + @contextlib.contextmanager + def mock_trial(value: str) -> T.Iterable[None]: + """Mock all of the ways we could get the trial at once.""" + mocked = mock.Mock(return_value=value) + + with mock.patch('mesonbuild.environment.detect_windows_arch', mocked), \ + mock.patch('mesonbuild.environment.platform.processor', mocked), \ + mock.patch('mesonbuild.environment.platform.machine', mocked): + yield + + cases = [ + ('amd64', 'x86_64'), + ('x64', 'x86_64'), + ('i86pc', 'x86_64'), + ('earm', 'arm'), + ('mips64el', 'mips64'), + ('mips64', 'mips64'), + ('mips', 'mips'), + ('mipsel', 'mips'), + ('aarch64', 'aarch64'), + ('aarch64_be', 'aarch64'), + ] + + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)): + for test, expected in cases: + with self.subTest(test, has_define=False), mock_trial(test): + actual = mesonbuild.environment.detect_cpu({}) + self.assertEqual(actual, expected) + + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)): + for test, expected in [('x86_64', 'i686'), ('aarch64', 'arm'), ('ppc', 'ppc64')]: + with self.subTest(test, has_define=True), mock_trial(test): + actual = mesonbuild.environment.detect_cpu({}) + self.assertEqual(actual, expected) + + def test_interpreter_unpicklable(self) -> None: + build = mock.Mock() + build.environment = mock.Mock() + build.environment.get_source_dir = mock.Mock(return_value='') + with mock.patch('mesonbuild.interpreter.Interpreter._redetect_machines', mock.Mock()), \ + self.assertRaises(mesonbuild.mesonlib.MesonBugException): + i = mesonbuild.interpreter.Interpreter(build, mock=True) + pickle.dumps(i) + + def test_major_versions_differ(self) -> None: + # Return True when going to next major release, when going to dev cycle, + # when going to rc cycle or when going out of rc cycle. + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.60.0')) + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.59.99')) + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.60.0.rc1')) + self.assertTrue(coredata.major_versions_differ('0.59.99', '0.60.0.rc1')) + self.assertTrue(coredata.major_versions_differ('0.60.0.rc1', '0.60.0')) + # Return False when going to next point release or when staying in dev/rc cycle. + self.assertFalse(coredata.major_versions_differ('0.60.0', '0.60.0')) + self.assertFalse(coredata.major_versions_differ('0.60.0', '0.60.1')) + self.assertFalse(coredata.major_versions_differ('0.59.99', '0.59.99')) + self.assertFalse(coredata.major_versions_differ('0.60.0.rc1', '0.60.0.rc2')) + + def test_option_key_from_string(self) -> None: + cases = [ + ('c_args', OptionKey('args', lang='c', _type=OptionType.COMPILER)), + ('build.cpp_args', OptionKey('args', machine=MachineChoice.BUILD, lang='cpp', _type=OptionType.COMPILER)), + ('prefix', OptionKey('prefix', _type=OptionType.BUILTIN)), + ('made_up', OptionKey('made_up', _type=OptionType.PROJECT)), + + # TODO: the from_String method should be splitting the prefix off of + # these, as we have the type already, but it doesn't. For now have a + # test so that we don't change the behavior un-intentionally + ('b_lto', OptionKey('b_lto', _type=OptionType.BASE)), + ('backend_startup_project', OptionKey('backend_startup_project', _type=OptionType.BACKEND)), + ] + + for raw, expected in cases: + with self.subTest(raw): + self.assertEqual(OptionKey.from_string(raw), expected) diff -Nru meson-0.53.2/unittests/linuxcrosstests.py meson-0.61.2/unittests/linuxcrosstests.py --- meson-0.53.2/unittests/linuxcrosstests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/linuxcrosstests.py 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,192 @@ +# Copyright 2016-2021 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 shutil +import unittest +import platform + +from mesonbuild.mesonlib import ( + is_windows, is_cygwin +) +from mesonbuild.mesonlib import MesonException + + + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +class BaseLinuxCrossTests(BasePlatformTests): + # Don't pass --libdir when cross-compiling. We have tests that + # check whether meson auto-detects it correctly. + libdir = None + + +def should_run_cross_arm_tests(): + return shutil.which('arm-linux-gnueabihf-gcc') and not platform.machine().lower().startswith('arm') + +@unittest.skipUnless(not is_windows() and should_run_cross_arm_tests(), "requires ability to cross compile to ARM") +class LinuxCrossArmTests(BaseLinuxCrossTests): + ''' + Tests that cross-compilation to Linux/ARM works + ''' + + def setUp(self): + super().setUp() + self.meson_cross_files = [os.path.join(self.src_root, 'cross', 'ubuntu-armhf.txt')] + + def test_cflags_cross_environment_pollution(self): + ''' + Test that the CFLAGS environment variable does not pollute the cross + environment. This can't be an ordinary test case because we need to + inspect the compiler database. + ''' + testdir = os.path.join(self.common_test_dir, '3 static') + self.init(testdir, override_envvars={'CFLAGS': '-DBUILD_ENVIRONMENT_ONLY'}) + compdb = self.get_compdb() + self.assertNotIn('-DBUILD_ENVIRONMENT_ONLY', compdb[0]['command']) + + def test_cross_file_overrides_always_args(self): + ''' + Test that $lang_args in cross files always override get_always_args(). + Needed for overriding the default -D_FILE_OFFSET_BITS=64 on some + architectures such as some Android versions and Raspbian. + https://github.com/mesonbuild/meson/issues/3049 + https://github.com/mesonbuild/meson/issues/3089 + ''' + testdir = os.path.join(self.unit_test_dir, '33 cross file overrides always args') + self.meson_cross_files = [os.path.join(testdir, 'ubuntu-armhf-overrides.txt')] + self.init(testdir) + compdb = self.get_compdb() + self.assertRegex(compdb[0]['command'], '-D_FILE_OFFSET_BITS=64.*-U_FILE_OFFSET_BITS') + self.build() + + def test_cross_libdir(self): + # When cross compiling "libdir" should default to "lib" + # rather than "lib/x86_64-linux-gnu" or something like that. + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + for i in self.introspect('--buildoptions'): + if i['name'] == 'libdir': + self.assertEqual(i['value'], 'lib') + return + self.assertTrue(False, 'Option libdir not in introspect data.') + + def test_cross_libdir_subproject(self): + # Guard against a regression where calling "subproject" + # would reset the value of libdir to its default value. + testdir = os.path.join(self.unit_test_dir, '76 subdir libdir') + self.init(testdir, extra_args=['--libdir=fuf']) + for i in self.introspect('--buildoptions'): + if i['name'] == 'libdir': + self.assertEqual(i['value'], 'fuf') + return + self.assertTrue(False, 'Libdir specified on command line gets reset.') + + def test_std_remains(self): + # C_std defined in project options must be in effect also when cross compiling. + testdir = os.path.join(self.unit_test_dir, '51 noncross options') + self.init(testdir) + compdb = self.get_compdb() + self.assertRegex(compdb[0]['command'], '-std=c99') + self.build() + + @skipIfNoPkgconfig + def test_pkg_config_option(self): + if not shutil.which('arm-linux-gnueabihf-pkg-config'): + raise unittest.SkipTest('Cross-pkgconfig not found.') + testdir = os.path.join(self.unit_test_dir, '58 pkg_config_path option') + self.init(testdir, extra_args=[ + '-Dbuild.pkg_config_path=' + os.path.join(testdir, 'build_extra_path'), + '-Dpkg_config_path=' + os.path.join(testdir, 'host_extra_path'), + ]) + + def test_run_native_test(self): + ''' + https://github.com/mesonbuild/meson/issues/7997 + check run native test in crossbuild without exe wrapper + ''' + testdir = os.path.join(self.unit_test_dir, '88 run native test') + stamp_file = os.path.join(self.builddir, 'native_test_has_run.stamp') + self.init(testdir) + self.build() + self.assertPathDoesNotExist(stamp_file) + self.run_tests() + self.assertPathExists(stamp_file) + + +def should_run_cross_mingw_tests(): + return shutil.which('x86_64-w64-mingw32-gcc') and not (is_windows() or is_cygwin()) + +@unittest.skipUnless(not is_windows() and should_run_cross_mingw_tests(), "requires ability to cross compile with MinGW") +class LinuxCrossMingwTests(BaseLinuxCrossTests): + ''' + Tests that cross-compilation to Windows/MinGW works + ''' + + def setUp(self): + super().setUp() + self.meson_cross_files = [os.path.join(self.src_root, 'cross', 'linux-mingw-w64-64bit.txt')] + + def test_exe_wrapper_behaviour(self): + ''' + Test that an exe wrapper that isn't found doesn't cause compiler sanity + checks and compiler checks to fail, but causes configure to fail if it + requires running a cross-built executable (custom_target or run_target) + and causes the tests to be skipped if they are run. + ''' + testdir = os.path.join(self.unit_test_dir, '36 exe_wrapper behaviour') + # Configures, builds, and tests fine by default + self.init(testdir) + self.build() + self.run_tests() + self.wipe() + os.mkdir(self.builddir) + # Change cross file to use a non-existing exe_wrapper and it should fail + self.meson_cross_files = [os.path.join(testdir, 'broken-cross.txt')] + # Force tracebacks so we can detect them properly + env = {'MESON_FORCE_BACKTRACE': '1'} + error_message = "An exe_wrapper is needed but was not found. Please define one in cross file and check the command and/or add it to PATH." + + with self.assertRaises(MesonException) as cm: + # Must run in-process or we'll get a generic CalledProcessError + self.init(testdir, extra_args='-Drun-target=false', + inprocess=True, + override_envvars=env) + self.assertEqual(str(cm.exception), error_message) + + with self.assertRaises(MesonException) as cm: + # Must run in-process or we'll get a generic CalledProcessError + self.init(testdir, extra_args='-Dcustom-target=false', + inprocess=True, + override_envvars=env) + self.assertEqual(str(cm.exception), error_message) + + self.init(testdir, extra_args=['-Dcustom-target=false', '-Drun-target=false'], + override_envvars=env) + self.build() + + with self.assertRaises(MesonException) as cm: + # Must run in-process or we'll get a generic CalledProcessError + self.run_tests(inprocess=True, override_envvars=env) + self.assertEqual(str(cm.exception), + "The exe_wrapper defined in the cross file 'broken' was not found. Please check the command and/or add it to PATH.") + + @skipIfNoPkgconfig + def test_cross_pkg_config_option(self): + testdir = os.path.join(self.unit_test_dir, '58 pkg_config_path option') + self.init(testdir, extra_args=[ + '-Dbuild.pkg_config_path=' + os.path.join(testdir, 'build_extra_path'), + '-Dpkg_config_path=' + os.path.join(testdir, 'host_extra_path'), + ]) diff -Nru meson-0.53.2/unittests/linuxliketests.py meson-0.61.2/unittests/linuxliketests.py --- meson-0.53.2/unittests/linuxliketests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/linuxliketests.py 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,1762 @@ +# Copyright 2016-2021 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 stat +import subprocess +import re +import tempfile +import textwrap +import os +import shutil +import hashlib +from unittest import mock, skipUnless, SkipTest +from glob import glob +from pathlib import Path +import typing as T + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + MachineChoice, is_windows, is_osx, is_cygwin, is_openbsd, is_haiku, + is_sunos, windows_proof_rmtree, version_compare, is_linux, + OptionKey, EnvironmentException +) +from mesonbuild.compilers import ( + detect_c_compiler, detect_cpp_compiler, compiler_from_language, + AppleClangCCompiler, AppleClangCPPCompiler, AppleClangObjCCompiler, + AppleClangObjCPPCompiler +) +from mesonbuild.dependencies import PkgConfigDependency +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +def _clang_at_least(compiler: 'Compiler', minver: str, apple_minver: T.Optional[str]) -> bool: + """ + check that Clang compiler is at least a specified version, whether AppleClang or regular Clang + + Parameters + ---------- + compiler: + Meson compiler object + minver: str + Clang minimum version + apple_minver: str + AppleCLang minimum version + + Returns + ------- + at_least: bool + Clang is at least the specified version + """ + if isinstance(compiler, (AppleClangCCompiler, AppleClangCPPCompiler)): + if apple_minver is None: + return False + return version_compare(compiler.version, apple_minver) + return version_compare(compiler.version, minver) + +@skipUnless(not is_windows(), "requires something Unix-like") +class LinuxlikeTests(BasePlatformTests): + ''' + Tests that should run on Linux, macOS, and *BSD + ''' + + def test_basic_soname(self): + ''' + Test that the soname is set correctly for shared libraries. This can't + be an ordinary test case because we need to run `readelf` and actually + check the soname. + https://github.com/mesonbuild/meson/issues/785 + ''' + testdir = os.path.join(self.common_test_dir, '4 shared') + self.init(testdir) + self.build() + lib1 = os.path.join(self.builddir, 'libmylib.so') + soname = get_soname(lib1) + self.assertEqual(soname, 'libmylib.so') + + def test_custom_soname(self): + ''' + Test that the soname is set correctly for shared libraries when + a custom prefix and/or suffix is used. This can't be an ordinary test + case because we need to run `readelf` and actually check the soname. + https://github.com/mesonbuild/meson/issues/785 + ''' + testdir = os.path.join(self.common_test_dir, '24 library versions') + self.init(testdir) + self.build() + lib1 = os.path.join(self.builddir, 'prefixsomelib.suffix') + soname = get_soname(lib1) + self.assertEqual(soname, 'prefixsomelib.suffix') + + def test_pic(self): + ''' + Test that -fPIC is correctly added to static libraries when b_staticpic + is true and not when it is false. This can't be an ordinary test case + because we need to inspect the compiler database. + ''' + if is_windows() or is_cygwin() or is_osx(): + raise SkipTest('PIC not relevant') + + testdir = os.path.join(self.common_test_dir, '3 static') + self.init(testdir) + compdb = self.get_compdb() + self.assertIn('-fPIC', compdb[0]['command']) + self.setconf('-Db_staticpic=false') + # Regenerate build + self.build() + compdb = self.get_compdb() + self.assertNotIn('-fPIC', compdb[0]['command']) + + @mock.patch.dict(os.environ) + def test_pkgconfig_gen(self): + ''' + Test that generated pkg-config files can be found and have the correct + version and link args. This can't be an ordinary test case because we + need to run pkg-config outside of a Meson build file. + https://github.com/mesonbuild/meson/issues/889 + ''' + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir) + env = get_fake_env(testdir, self.builddir, self.prefix) + kwargs = {'required': True, 'silent': True} + os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir + foo_dep = PkgConfigDependency('libfoo', env, kwargs) + 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') + + 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) + 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') + + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() in {'gcc', 'clang'}: + for name in {'ct', 'ct0'}: + ct_dep = PkgConfigDependency(name, env, kwargs) + self.assertTrue(ct_dep.found()) + self.assertIn('-lct', ct_dep.get_link_args()) + + def test_pkgconfig_gen_deps(self): + ''' + Test that generated pkg-config files correctly handle dependencies + ''' + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir) + privatedir1 = self.privatedir + + self.new_builddir() + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen', 'dependencies') + self.init(testdir, override_envvars={'PKG_CONFIG_LIBDIR': privatedir1}) + privatedir2 = self.privatedir + + env = { + 'PKG_CONFIG_LIBDIR': os.pathsep.join([privatedir1, privatedir2]), + 'PKG_CONFIG_SYSTEM_LIBRARY_PATH': '/usr/lib', + } + self._run(['pkg-config', 'dependency-test', '--validate'], override_envvars=env) + + # pkg-config strips some duplicated flags so we have to parse the + # generated file ourself. + expected = { + 'Requires': 'libexposed', + 'Requires.private': 'libfoo >= 1.0', + 'Libs': '-L${libdir} -llibmain -pthread -lcustom', + 'Libs.private': '-lcustom2 -L${libdir} -llibinternal', + 'Cflags': '-I${includedir} -pthread -DCUSTOM', + } + if is_osx() or is_haiku(): + expected['Cflags'] = expected['Cflags'].replace('-pthread ', '') + with open(os.path.join(privatedir2, 'dependency-test.pc'), encoding='utf-8') as f: + matched_lines = 0 + for line in f: + parts = line.split(':', 1) + if parts[0] in expected: + key = parts[0] + val = parts[1].strip() + expected_val = expected[key] + self.assertEqual(expected_val, val) + matched_lines += 1 + self.assertEqual(len(expected), matched_lines) + + cmd = ['pkg-config', 'requires-test'] + out = self._run(cmd + ['--print-requires'], override_envvars=env).strip().split('\n') + if not is_openbsd(): + self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello'])) + else: + self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello'])) + + cmd = ['pkg-config', 'requires-private-test'] + out = self._run(cmd + ['--print-requires-private'], override_envvars=env).strip().split('\n') + if not is_openbsd(): + self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello'])) + else: + self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello'])) + + cmd = ['pkg-config', 'pub-lib-order'] + out = self._run(cmd + ['--libs'], override_envvars=env).strip().split() + self.assertEqual(out, ['-llibmain2', '-llibinternal']) + + # See common/44 pkgconfig-gen/meson.build for description of the case this test + with open(os.path.join(privatedir1, 'simple2.pc'), encoding='utf-8') as f: + content = f.read() + self.assertIn('Libs: -L${libdir} -lsimple2 -lsimple1', content) + self.assertIn('Libs.private: -lz', content) + + with open(os.path.join(privatedir1, 'simple3.pc'), encoding='utf-8') as f: + content = f.read() + self.assertEqual(1, content.count('-lsimple3')) + + with open(os.path.join(privatedir1, 'simple5.pc'), encoding='utf-8') as f: + content = f.read() + self.assertNotIn('-lstat2', content) + + @mock.patch.dict(os.environ) + def test_pkgconfig_uninstalled(self): + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir) + self.build() + + os.environ['PKG_CONFIG_LIBDIR'] = os.path.join(self.builddir, 'meson-uninstalled') + if is_cygwin(): + os.environ['PATH'] += os.pathsep + self.builddir + + self.new_builddir() + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen', 'dependencies') + self.init(testdir) + self.build() + self.run_tests() + + def test_pkg_unfound(self): + testdir = os.path.join(self.unit_test_dir, '23 unfound pkgconfig') + self.init(testdir) + with open(os.path.join(self.privatedir, 'somename.pc'), encoding='utf-8') as f: + pcfile = f.read() + self.assertNotIn('blub_blob_blib', pcfile) + + def test_symlink_builddir(self) -> None: + ''' + Test using a symlink as either the builddir for "setup" or + the argument for "-C". + ''' + testdir = os.path.join(self.common_test_dir, '1 trivial') + + symdir = f'{self.builddir}-symlink' + os.symlink(self.builddir, symdir) + self.addCleanup(os.unlink, symdir) + self.change_builddir(symdir) + + self.init(testdir) + self.build() + self._run(self.mtest_command) + + def test_vala_c_warnings(self): + ''' + Test that no warnings are emitted for C code generated by Vala. This + can't be an ordinary test case because we need to inspect the compiler + database. + https://github.com/mesonbuild/meson/issues/864 + ''' + if not shutil.which('valac'): + raise SkipTest('valac not installed.') + testdir = os.path.join(self.vala_test_dir, '5 target glib') + self.init(testdir) + compdb = self.get_compdb() + vala_command = None + c_command = None + for each in compdb: + if each['file'].endswith('GLib.Thread.c'): + vala_command = each['command'] + elif each['file'].endswith('GLib.Thread.vala'): + continue + elif each['file'].endswith('retcode.c'): + c_command = each['command'] + else: + m = 'Unknown file {!r} in vala_c_warnings test'.format(each['file']) + raise AssertionError(m) + self.assertIsNotNone(vala_command) + self.assertIsNotNone(c_command) + # -w suppresses all warnings, should be there in Vala but not in C + self.assertIn(" -w ", vala_command) + self.assertNotIn(" -w ", c_command) + # -Wall enables all warnings, should be there in C but not in Vala + self.assertNotIn(" -Wall ", vala_command) + self.assertIn(" -Wall ", c_command) + # -Werror converts warnings to errors, should always be there since it's + # injected by an unrelated piece of code and the project has werror=true + self.assertIn(" -Werror ", vala_command) + self.assertIn(" -Werror ", c_command) + + @skipIfNoPkgconfig + def test_qtdependency_pkgconfig_detection(self): + ''' + Test that qt4 and qt5 detection with pkgconfig works. + ''' + # Verify Qt4 or Qt5 can be found with pkg-config + qt4 = subprocess.call(['pkg-config', '--exists', 'QtCore']) + qt5 = subprocess.call(['pkg-config', '--exists', 'Qt5Core']) + testdir = os.path.join(self.framework_test_dir, '4 qt') + self.init(testdir, extra_args=['-Dmethod=pkg-config']) + # Confirm that the dependency was found with pkg-config + mesonlog = self.get_meson_log() + if qt4 == 0: + self.assertRegex('\n'.join(mesonlog), + r'Run-time dependency qt4 \(modules: Core\) found: YES 4.* \(pkg-config\)') + if qt5 == 0: + self.assertRegex('\n'.join(mesonlog), + r'Run-time dependency qt5 \(modules: Core\) found: YES 5.* \(pkg-config\)') + + @skip_if_not_base_option('b_sanitize') + def test_generate_gir_with_address_sanitizer(self): + if is_cygwin(): + raise SkipTest('asan not available on Cygwin') + if is_openbsd(): + raise SkipTest('-fsanitize=address is not supported on OpenBSD') + + testdir = os.path.join(self.framework_test_dir, '7 gnome') + self.init(testdir, extra_args=['-Db_sanitize=address', '-Db_lundef=false']) + self.build() + + def test_qt5dependency_qmake_detection(self): + ''' + Test that qt5 detection with qmake works. This can't be an ordinary + test case because it involves setting the environment. + ''' + # Verify that qmake is for Qt5 + if not shutil.which('qmake-qt5'): + if not shutil.which('qmake'): + raise SkipTest('QMake not found') + output = subprocess.getoutput('qmake --version') + if 'Qt version 5' not in output: + raise SkipTest('Qmake found, but it is not for Qt 5.') + # Disable pkg-config codepath and force searching with qmake/qmake-qt5 + testdir = os.path.join(self.framework_test_dir, '4 qt') + self.init(testdir, extra_args=['-Dmethod=qmake']) + # Confirm that the dependency was found with qmake + mesonlog = self.get_meson_log() + self.assertRegex('\n'.join(mesonlog), + r'Run-time dependency qt5 \(modules: Core\) found: YES .* \(qmake\)\n') + + def test_qt6dependency_qmake_detection(self): + ''' + Test that qt6 detection with qmake works. This can't be an ordinary + test case because it involves setting the environment. + ''' + # Verify that qmake is for Qt5 + if not shutil.which('qmake-qt6'): + if not shutil.which('qmake'): + raise SkipTest('QMake not found') + output = subprocess.getoutput('qmake --version') + if 'Qt version 6' not in output: + raise SkipTest('Qmake found, but it is not for Qt 6.') + # Disable pkg-config codepath and force searching with qmake/qmake-qt6 + testdir = os.path.join(self.framework_test_dir, '4 qt') + self.init(testdir, extra_args=['-Dmethod=qmake']) + # Confirm that the dependency was found with qmake + mesonlog = self.get_meson_log() + self.assertRegex('\n'.join(mesonlog), + r'Run-time dependency qt6 \(modules: Core\) found: YES .* \(qmake\)\n') + + def glob_sofiles_without_privdir(self, g): + files = glob(g) + return [f for f in files if not f.endswith('.p')] + + def _test_soname_impl(self, libpath, install): + if is_cygwin() or is_osx(): + raise SkipTest('Test only applicable to ELF and linuxlike sonames') + + testdir = os.path.join(self.unit_test_dir, '1 soname') + self.init(testdir) + self.build() + if install: + self.install() + + # File without aliases set. + nover = os.path.join(libpath, 'libnover.so') + self.assertPathExists(nover) + self.assertFalse(os.path.islink(nover)) + self.assertEqual(get_soname(nover), 'libnover.so') + self.assertEqual(len(self.glob_sofiles_without_privdir(nover[:-3] + '*')), 1) + + # File with version set + verset = os.path.join(libpath, 'libverset.so') + self.assertPathExists(verset + '.4.5.6') + self.assertEqual(os.readlink(verset), 'libverset.so.4') + self.assertEqual(get_soname(verset), 'libverset.so.4') + self.assertEqual(len(self.glob_sofiles_without_privdir(verset[:-3] + '*')), 3) + + # File with soversion set + soverset = os.path.join(libpath, 'libsoverset.so') + self.assertPathExists(soverset + '.1.2.3') + self.assertEqual(os.readlink(soverset), 'libsoverset.so.1.2.3') + self.assertEqual(get_soname(soverset), 'libsoverset.so.1.2.3') + self.assertEqual(len(self.glob_sofiles_without_privdir(soverset[:-3] + '*')), 2) + + # File with version and soversion set to same values + settosame = os.path.join(libpath, 'libsettosame.so') + self.assertPathExists(settosame + '.7.8.9') + self.assertEqual(os.readlink(settosame), 'libsettosame.so.7.8.9') + self.assertEqual(get_soname(settosame), 'libsettosame.so.7.8.9') + self.assertEqual(len(self.glob_sofiles_without_privdir(settosame[:-3] + '*')), 2) + + # File with version and soversion set to different values + bothset = os.path.join(libpath, 'libbothset.so') + self.assertPathExists(bothset + '.1.2.3') + self.assertEqual(os.readlink(bothset), 'libbothset.so.1.2.3') + self.assertEqual(os.readlink(bothset + '.1.2.3'), 'libbothset.so.4.5.6') + self.assertEqual(get_soname(bothset), 'libbothset.so.1.2.3') + self.assertEqual(len(self.glob_sofiles_without_privdir(bothset[:-3] + '*')), 3) + + # A shared_module that is not linked to anything + module = os.path.join(libpath, 'libsome_module.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), None) + + # A shared_module that is not linked to an executable with link_with: + module = os.path.join(libpath, 'liblinked_module1.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), 'liblinked_module1.so') + + # A shared_module that is not linked to an executable with dependencies: + module = os.path.join(libpath, 'liblinked_module2.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), 'liblinked_module2.so') + + def test_soname(self): + self._test_soname_impl(self.builddir, False) + + def test_installed_soname(self): + libdir = self.installdir + os.path.join(self.prefix, self.libdir) + self._test_soname_impl(libdir, True) + + def test_compiler_check_flags_order(self): + ''' + Test that compiler check flags override all other flags. This can't be + an ordinary test case because it needs the environment to be set. + ''' + testdir = os.path.join(self.common_test_dir, '36 has function') + env = get_fake_env(testdir, self.builddir, self.prefix) + cpp = detect_cpp_compiler(env, MachineChoice.HOST) + Oflag = '-O3' + OflagCPP = Oflag + if cpp.get_id() in ('clang', 'gcc'): + # prevent developers from adding "int main(int argc, char **argv)" + # to small Meson checks unless these parameters are actually used + OflagCPP += ' -Werror=unused-parameter' + env = {'CFLAGS': Oflag, + 'CXXFLAGS': OflagCPP} + self.init(testdir, override_envvars=env) + cmds = self.get_meson_log_compiler_checks() + for cmd in cmds: + if cmd[0] == 'ccache': + cmd = cmd[1:] + # Verify that -I flags from the `args` kwarg are first + # This is set in the '36 has function' test case + self.assertEqual(cmd[1], '-I/tmp') + # Verify that -O3 set via the environment is overridden by -O0 + Oargs = [arg for arg in cmd if arg.startswith('-O')] + self.assertEqual(Oargs, [Oflag, '-O0']) + + def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None: + has_cpp17 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=5.0.0', '>=9.1') or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=5.0.0')) + has_cpp2a_c17 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=6.0.0', '>=10.0') or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=8.0.0')) + has_cpp20 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=10.0.0', None) or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=10.0.0')) + has_c18 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=8.0.0', '>=11.0') or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=8.0.0')) + # Check that all the listed -std=xxx options for this compiler work just fine when used + # https://en.wikipedia.org/wiki/Xcode#Latest_versions + # https://www.gnu.org/software/gcc/projects/cxx-status.html + key = OptionKey('std', lang=compiler.language) + for v in compiler.get_options()[key].choices: + # we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly + # thus, C++ first + if '++17' in v and not has_cpp17: + continue + elif '++2a' in v and not has_cpp2a_c17: # https://en.cppreference.com/w/cpp/compiler_support + continue + elif '++20' in v and not has_cpp20: + continue + # now C + elif '17' in v and not has_cpp2a_c17: + continue + elif '18' in v and not has_c18: + continue + self.init(testdir, extra_args=[f'-D{key!s}={v}']) + cmd = self.get_compdb()[0]['command'] + # c++03 and gnu++03 are not understood by ICC, don't try to look for them + skiplist = frozenset([ + ('intel', 'c++03'), + ('intel', 'gnu++03')]) + if v != 'none' and not (compiler.get_id(), v) in skiplist: + cmd_std = f" -std={v} " + self.assertIn(cmd_std, cmd) + try: + self.build() + except Exception: + print(f'{key!s} was {v!r}') + raise + self.wipe() + # Check that an invalid std option in CFLAGS/CPPFLAGS fails + # Needed because by default ICC ignores invalid options + cmd_std = '-std=FAIL' + if compiler.language == 'c': + env_flag_name = 'CFLAGS' + elif compiler.language == 'cpp': + env_flag_name = 'CXXFLAGS' + else: + raise NotImplementedError(f'Language {compiler.language} not defined.') + env = {} + env[env_flag_name] = cmd_std + with self.assertRaises((subprocess.CalledProcessError, EnvironmentException), + msg='C compiler should have failed with -std=FAIL'): + self.init(testdir, override_envvars = env) + # ICC won't fail in the above because additional flags are needed to + # make unknown -std=... options errors. + self.build() + + def test_compiler_c_stds(self): + ''' + Test that C stds specified for this compiler can all be used. Can't be + an ordinary test because it requires passing options to meson. + ''' + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + self._test_stds_impl(testdir, cc) + + def test_compiler_cpp_stds(self): + ''' + Test that C++ stds specified for this compiler can all be used. Can't + be an ordinary test because it requires passing options to meson. + ''' + testdir = os.path.join(self.common_test_dir, '2 cpp') + env = get_fake_env(testdir, self.builddir, self.prefix) + cpp = detect_cpp_compiler(env, MachineChoice.HOST) + self._test_stds_impl(testdir, cpp) + + def test_unity_subproj(self): + testdir = os.path.join(self.common_test_dir, '42 subproject') + self.init(testdir, extra_args='--unity=subprojects') + pdirs = glob(os.path.join(self.builddir, 'subprojects/sublib/simpletest*.p')) + self.assertEqual(len(pdirs), 1) + self.assertPathExists(os.path.join(pdirs[0], 'simpletest-unity0.c')) + sdirs = glob(os.path.join(self.builddir, 'subprojects/sublib/*sublib*.p')) + self.assertEqual(len(sdirs), 1) + self.assertPathExists(os.path.join(sdirs[0], 'sublib-unity0.c')) + self.assertPathDoesNotExist(os.path.join(self.builddir, 'user@exe/user-unity.c')) + self.build() + + def test_installed_modes(self): + ''' + Test that files installed by these tests have the correct permissions. + Can't be an ordinary test because our installed_files.txt is very basic. + ''' + if is_cygwin(): + self.new_builddir_in_tempdir() + # Test file modes + testdir = os.path.join(self.common_test_dir, '12 data') + self.init(testdir) + self.install() + + f = os.path.join(self.installdir, 'etc', 'etcfile.dat') + found_mode = stat.filemode(os.stat(f).st_mode) + want_mode = 'rw------T' + self.assertEqual(want_mode, found_mode[1:]) + + f = os.path.join(self.installdir, 'usr', 'bin', 'runscript.sh') + statf = os.stat(f) + found_mode = stat.filemode(statf.st_mode) + want_mode = 'rwxr-sr-x' + self.assertEqual(want_mode, found_mode[1:]) + if os.getuid() == 0: + # The chown failed nonfatally if we're not root + self.assertEqual(0, statf.st_uid) + self.assertEqual(0, statf.st_gid) + + f = os.path.join(self.installdir, 'usr', 'share', 'progname', + 'fileobject_datafile.dat') + orig = os.path.join(testdir, 'fileobject_datafile.dat') + statf = os.stat(f) + statorig = os.stat(orig) + found_mode = stat.filemode(statf.st_mode) + orig_mode = stat.filemode(statorig.st_mode) + self.assertEqual(orig_mode[1:], found_mode[1:]) + self.assertEqual(os.getuid(), statf.st_uid) + if os.getuid() == 0: + # The chown failed nonfatally if we're not root + self.assertEqual(0, statf.st_gid) + + self.wipe() + # Test directory modes + testdir = os.path.join(self.common_test_dir, '59 install subdir') + self.init(testdir) + self.install() + + f = os.path.join(self.installdir, 'usr', 'share', 'sub1', 'second.dat') + statf = os.stat(f) + found_mode = stat.filemode(statf.st_mode) + want_mode = 'rwxr-x--t' + self.assertEqual(want_mode, found_mode[1:]) + if os.getuid() == 0: + # The chown failed nonfatally if we're not root + self.assertEqual(0, statf.st_uid) + + def test_installed_modes_extended(self): + ''' + Test that files are installed with correct permissions using install_mode. + ''' + if is_cygwin(): + self.new_builddir_in_tempdir() + testdir = os.path.join(self.common_test_dir, '190 install_mode') + self.init(testdir) + self.build() + self.install() + + for fsobj, want_mode in [ + ('bin', 'drwxr-x---'), + ('bin/runscript.sh', '-rwxr-sr-x'), + ('bin/trivialprog', '-rwxr-sr-x'), + ('include', 'drwxr-x---'), + ('include/config.h', '-rw-rwSr--'), + ('include/rootdir.h', '-r--r--r-T'), + ('lib', 'drwxr-x---'), + ('lib/libstat.a', '-rw---Sr--'), + ('share', 'drwxr-x---'), + ('share/man', 'drwxr-x---'), + ('share/man/man1', 'drwxr-x---'), + ('share/man/man1/foo.1', '-r--r--r-T'), + ('share/sub1', 'drwxr-x---'), + ('share/sub1/second.dat', '-rwxr-x--t'), + ('subdir', 'drwxr-x---'), + ('subdir/data.dat', '-rw-rwSr--'), + ]: + f = os.path.join(self.installdir, 'usr', *fsobj.split('/')) + found_mode = stat.filemode(os.stat(f).st_mode) + self.assertEqual(want_mode, found_mode, + msg=('Expected file %s to have mode %s but found %s instead.' % + (fsobj, want_mode, found_mode))) + # Ensure that introspect --installed works on all types of files + # FIXME: also verify the files list + self.introspect('--installed') + + def test_install_umask(self): + ''' + Test that files are installed with correct permissions using default + install umask of 022, regardless of the umask at time the worktree + was checked out or the build was executed. + ''' + if is_cygwin(): + self.new_builddir_in_tempdir() + # Copy source tree to a temporary directory and change permissions + # there to simulate a checkout with umask 002. + orig_testdir = os.path.join(self.unit_test_dir, '26 install umask') + # Create a new testdir under tmpdir. + tmpdir = os.path.realpath(tempfile.mkdtemp()) + self.addCleanup(windows_proof_rmtree, tmpdir) + testdir = os.path.join(tmpdir, '26 install umask') + # Copy the tree using shutil.copyfile, which will use the current umask + # instead of preserving permissions of the old tree. + save_umask = os.umask(0o002) + self.addCleanup(os.umask, save_umask) + shutil.copytree(orig_testdir, testdir, copy_function=shutil.copyfile) + # Preserve the executable status of subdir/sayhello though. + os.chmod(os.path.join(testdir, 'subdir', 'sayhello'), 0o775) + self.init(testdir) + # Run the build under a 027 umask now. + os.umask(0o027) + self.build() + # And keep umask 027 for the install step too. + self.install() + + for executable in [ + 'bin/prog', + 'share/subdir/sayhello', + ]: + f = os.path.join(self.installdir, 'usr', *executable.split('/')) + found_mode = stat.filemode(os.stat(f).st_mode) + want_mode = '-rwxr-xr-x' + self.assertEqual(want_mode, found_mode, + msg=('Expected file %s to have mode %s but found %s instead.' % + (executable, want_mode, found_mode))) + + for directory in [ + 'usr', + 'usr/bin', + 'usr/include', + 'usr/share', + 'usr/share/man', + 'usr/share/man/man1', + 'usr/share/subdir', + ]: + f = os.path.join(self.installdir, *directory.split('/')) + found_mode = stat.filemode(os.stat(f).st_mode) + want_mode = 'drwxr-xr-x' + self.assertEqual(want_mode, found_mode, + msg=('Expected directory %s to have mode %s but found %s instead.' % + (directory, want_mode, found_mode))) + + for datafile in [ + 'include/sample.h', + 'share/datafile.cat', + 'share/file.dat', + 'share/man/man1/prog.1', + 'share/subdir/datafile.dog', + ]: + f = os.path.join(self.installdir, 'usr', *datafile.split('/')) + found_mode = stat.filemode(os.stat(f).st_mode) + want_mode = '-rw-r--r--' + self.assertEqual(want_mode, found_mode, + msg=('Expected file %s to have mode %s but found %s instead.' % + (datafile, want_mode, found_mode))) + + def test_cpp_std_override(self): + testdir = os.path.join(self.unit_test_dir, '6 std override') + self.init(testdir) + compdb = self.get_compdb() + # Don't try to use -std=c++03 as a check for the + # presence of a compiler flag, as ICC does not + # support it. + for i in compdb: + if 'prog98' in i['file']: + c98_comp = i['command'] + if 'prog11' in i['file']: + c11_comp = i['command'] + if 'progp' in i['file']: + plain_comp = i['command'] + self.assertNotEqual(len(plain_comp), 0) + self.assertIn('-std=c++98', c98_comp) + self.assertNotIn('-std=c++11', c98_comp) + self.assertIn('-std=c++11', c11_comp) + self.assertNotIn('-std=c++98', c11_comp) + self.assertNotIn('-std=c++98', plain_comp) + self.assertNotIn('-std=c++11', plain_comp) + # Now werror + self.assertIn('-Werror', plain_comp) + self.assertNotIn('-Werror', c98_comp) + + def test_run_installed(self): + if is_cygwin() or is_osx(): + raise SkipTest('LD_LIBRARY_PATH and RPATH not applicable') + + testdir = os.path.join(self.unit_test_dir, '7 run installed') + self.init(testdir) + self.build() + self.install() + installed_exe = os.path.join(self.installdir, 'usr/bin/prog') + installed_libdir = os.path.join(self.installdir, 'usr/foo') + installed_lib = os.path.join(installed_libdir, 'libfoo.so') + self.assertTrue(os.path.isfile(installed_exe)) + self.assertTrue(os.path.isdir(installed_libdir)) + self.assertTrue(os.path.isfile(installed_lib)) + # Must fail when run without LD_LIBRARY_PATH to ensure that + # rpath has been properly stripped rather than pointing to the builddir. + self.assertNotEqual(subprocess.call(installed_exe, stderr=subprocess.DEVNULL), 0) + # When LD_LIBRARY_PATH is set it should start working. + # For some reason setting LD_LIBRARY_PATH in os.environ fails + # when all tests are run (but works when only this test is run), + # but doing this explicitly works. + env = os.environ.copy() + env['LD_LIBRARY_PATH'] = ':'.join([installed_libdir, env.get('LD_LIBRARY_PATH', '')]) + self.assertEqual(subprocess.call(installed_exe, env=env), 0) + # Ensure that introspect --installed works + installed = self.introspect('--installed') + for v in installed.values(): + self.assertTrue('prog' in v or 'foo' in v) + + @skipIfNoPkgconfig + def test_order_of_l_arguments(self): + testdir = os.path.join(self.unit_test_dir, '8 -L -l order') + self.init(testdir, override_envvars={'PKG_CONFIG_PATH': testdir}) + # NOTE: .pc file has -Lfoo -lfoo -Lbar -lbar but pkg-config reorders + # the flags before returning them to -Lfoo -Lbar -lfoo -lbar + # but pkgconf seems to not do that. Sigh. Support both. + expected_order = [('-L/me/first', '-lfoo1'), + ('-L/me/second', '-lfoo2'), + ('-L/me/first', '-L/me/second'), + ('-lfoo1', '-lfoo2'), + ('-L/me/second', '-L/me/third'), + ('-L/me/third', '-L/me/fourth',), + ('-L/me/third', '-lfoo3'), + ('-L/me/fourth', '-lfoo4'), + ('-lfoo3', '-lfoo4'), + ] + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as ifile: + for line in ifile: + if expected_order[0][0] in line: + for first, second in expected_order: + self.assertLess(line.index(first), line.index(second)) + return + raise RuntimeError('Linker entries not found in the Ninja file.') + + def test_introspect_dependencies(self): + ''' + Tests that mesonintrospect --dependencies returns expected output. + ''' + testdir = os.path.join(self.framework_test_dir, '7 gnome') + self.init(testdir) + glib_found = False + gobject_found = False + deps = self.introspect('--dependencies') + self.assertIsInstance(deps, list) + for dep in deps: + self.assertIsInstance(dep, dict) + self.assertIn('name', dep) + self.assertIn('compile_args', dep) + self.assertIn('link_args', dep) + if dep['name'] == 'glib-2.0': + glib_found = True + elif dep['name'] == 'gobject-2.0': + gobject_found = True + self.assertTrue(glib_found) + self.assertTrue(gobject_found) + if subprocess.call(['pkg-config', '--exists', 'glib-2.0 >= 2.56.2']) != 0: + raise SkipTest('glib >= 2.56.2 needed for the rest') + targets = self.introspect('--targets') + docbook_target = None + for t in targets: + if t['name'] == 'generated-gdbus-docbook': + docbook_target = t + break + self.assertIsInstance(docbook_target, dict) + self.assertEqual(os.path.basename(t['filename'][0]), 'generated-gdbus-doc-' + os.path.basename(t['target_sources'][0]['sources'][0])) + + def test_introspect_installed(self): + testdir = os.path.join(self.linuxlike_test_dir, '7 library versions') + self.init(testdir) + + install = self.introspect('--installed') + install = {os.path.basename(k): v for k, v in install.items()} + print(install) + if is_osx(): + the_truth = { + 'libmodule.dylib': '/usr/lib/libmodule.dylib', + 'libnoversion.dylib': '/usr/lib/libnoversion.dylib', + 'libonlysoversion.5.dylib': '/usr/lib/libonlysoversion.5.dylib', + 'libonlysoversion.dylib': '/usr/lib/libonlysoversion.dylib', + 'libonlyversion.1.dylib': '/usr/lib/libonlyversion.1.dylib', + 'libonlyversion.dylib': '/usr/lib/libonlyversion.dylib', + 'libsome.0.dylib': '/usr/lib/libsome.0.dylib', + 'libsome.dylib': '/usr/lib/libsome.dylib', + } + the_truth_2 = {'/usr/lib/libsome.dylib', + '/usr/lib/libsome.0.dylib', + } + else: + the_truth = { + 'libmodule.so': '/usr/lib/libmodule.so', + 'libnoversion.so': '/usr/lib/libnoversion.so', + 'libonlysoversion.so': '/usr/lib/libonlysoversion.so', + 'libonlysoversion.so.5': '/usr/lib/libonlysoversion.so.5', + 'libonlyversion.so': '/usr/lib/libonlyversion.so', + 'libonlyversion.so.1': '/usr/lib/libonlyversion.so.1', + 'libonlyversion.so.1.4.5': '/usr/lib/libonlyversion.so.1.4.5', + 'libsome.so': '/usr/lib/libsome.so', + 'libsome.so.0': '/usr/lib/libsome.so.0', + 'libsome.so.1.2.3': '/usr/lib/libsome.so.1.2.3', + } + the_truth_2 = {'/usr/lib/libsome.so', + '/usr/lib/libsome.so.0', + '/usr/lib/libsome.so.1.2.3'} + self.assertDictEqual(install, the_truth) + + targets = self.introspect('--targets') + for t in targets: + if t['name'] != 'some': + continue + self.assertSetEqual(the_truth_2, set(t['install_filename'])) + + def test_build_rpath(self): + if is_cygwin(): + raise SkipTest('Windows PE/COFF binaries do not use RPATH') + testdir = os.path.join(self.unit_test_dir, '10 build_rpath') + self.init(testdir) + self.build() + build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') + build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') + self.install() + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog')) + self.assertEqual(install_rpath, '/baz') + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx')) + self.assertEqual(install_rpath, 'baz') + + @skipIfNoPkgconfig + def test_build_rpath_pkgconfig(self): + ''' + Test that current build artefacts (libs) are found first on the rpath, + manually specified rpath comes second and additional rpath elements (from + pkg-config files) come last + ''' + if is_cygwin(): + raise SkipTest('Windows PE/COFF binaries do not use RPATH') + testdir = os.path.join(self.unit_test_dir, '90 pkgconfig build rpath order') + self.init(testdir, override_envvars={'PKG_CONFIG_PATH': testdir}) + self.build() + build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar:/foo/dummy') + build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar:/foo/dummy') + self.install() + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog')) + self.assertEqual(install_rpath, '/baz:/foo/dummy') + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx')) + self.assertEqual(install_rpath, 'baz:/foo/dummy') + + def test_global_rpath(self): + if is_cygwin(): + raise SkipTest('Windows PE/COFF binaries do not use RPATH') + if is_osx(): + raise SkipTest('Global RPATHs via LDFLAGS not yet supported on MacOS (does anybody need it?)') + + testdir = os.path.join(self.unit_test_dir, '80 global-rpath') + oldinstalldir = self.installdir + + # Build and install an external library without DESTDIR. + # The external library generates a .pc file without an rpath. + yonder_dir = os.path.join(testdir, 'yonder') + yonder_prefix = os.path.join(oldinstalldir, 'yonder') + yonder_libdir = os.path.join(yonder_prefix, self.libdir) + self.prefix = yonder_prefix + self.installdir = yonder_prefix + self.init(yonder_dir) + self.build() + self.install(use_destdir=False) + + # Since rpath has multiple valid formats we need to + # test that they are all properly used. + rpath_formats = [ + ('-Wl,-rpath=', False), + ('-Wl,-rpath,', False), + ('-Wl,--just-symbols=', True), + ('-Wl,--just-symbols,', True), + ('-Wl,-R', False), + ('-Wl,-R,', False) + ] + for rpath_format, exception in rpath_formats: + # Build an app that uses that installed library. + # Supply the rpath to the installed library via LDFLAGS + # (as systems like buildroot and guix are wont to do) + # and verify install preserves that rpath. + self.new_builddir() + env = {'LDFLAGS': rpath_format + yonder_libdir, + 'PKG_CONFIG_PATH': os.path.join(yonder_libdir, 'pkgconfig')} + if exception: + with self.assertRaises(subprocess.CalledProcessError): + self.init(testdir, override_envvars=env) + continue + self.init(testdir, override_envvars=env) + self.build() + self.install(use_destdir=False) + got_rpath = get_rpath(os.path.join(yonder_prefix, 'bin/rpathified')) + self.assertEqual(got_rpath, yonder_libdir, rpath_format) + + @skip_if_not_base_option('b_sanitize') + def test_pch_with_address_sanitizer(self): + if is_cygwin(): + raise SkipTest('asan not available on Cygwin') + if is_openbsd(): + raise SkipTest('-fsanitize=address is not supported on OpenBSD') + + testdir = os.path.join(self.common_test_dir, '13 pch') + self.init(testdir, extra_args=['-Db_sanitize=address', '-Db_lundef=false']) + self.build() + compdb = self.get_compdb() + for i in compdb: + self.assertIn("-fsanitize=address", i["command"]) + + def test_cross_find_program(self): + testdir = os.path.join(self.unit_test_dir, '11 cross prog') + crossfile = tempfile.NamedTemporaryFile(mode='w') + print(os.path.join(testdir, 'some_cross_tool.py')) + + tool_path = os.path.join(testdir, 'some_cross_tool.py') + + crossfile.write(textwrap.dedent(f'''\ + [binaries] + c = '{shutil.which('gcc' if is_sunos() else 'cc')}' + ar = '{shutil.which('ar')}' + strip = '{shutil.which('strip')}' + sometool.py = ['{tool_path}'] + someothertool.py = '{tool_path}' + + [properties] + + [host_machine] + system = 'linux' + cpu_family = 'arm' + cpu = 'armv7' # Not sure if correct. + endian = 'little' + ''')) + crossfile.flush() + self.meson_cross_files = [crossfile.name] + self.init(testdir) + + def test_reconfigure(self): + testdir = os.path.join(self.unit_test_dir, '13 reconfigure') + self.init(testdir, extra_args=['-Db_coverage=true'], default_args=False) + self.build('reconfigure') + + def test_vala_generated_source_buildir_inside_source_tree(self): + ''' + Test that valac outputs generated C files in the expected location when + the builddir is a subdir of the source tree. + ''' + if not shutil.which('valac'): + raise SkipTest('valac not installed.') + + testdir = os.path.join(self.vala_test_dir, '8 generated sources') + newdir = os.path.join(self.builddir, 'srctree') + shutil.copytree(testdir, newdir) + testdir = newdir + # New builddir + builddir = os.path.join(testdir, 'subdir/_build') + os.makedirs(builddir, exist_ok=True) + self.change_builddir(builddir) + self.init(testdir) + self.build() + + def test_old_gnome_module_codepaths(self): + ''' + A lot of code in the GNOME module is conditional on the version of the + glib tools that are installed, and breakages in the old code can slip + by once the CI has a newer glib version. So we force the GNOME module + to pretend that it's running on an ancient glib so the fallback code is + also tested. + ''' + testdir = os.path.join(self.framework_test_dir, '7 gnome') + mesonbuild.modules.gnome.native_glib_version = '2.20' + env = {'MESON_UNIT_TEST_PRETEND_GLIB_OLD': "1"} + try: + self.init(testdir, + inprocess=True, + override_envvars=env) + self.build(override_envvars=env) + finally: + mesonbuild.modules.gnome.native_glib_version = None + + @skipIfNoPkgconfig + def test_pkgconfig_usage(self): + testdir1 = os.path.join(self.unit_test_dir, '27 pkgconfig usage/dependency') + testdir2 = os.path.join(self.unit_test_dir, '27 pkgconfig usage/dependee') + if subprocess.call(['pkg-config', '--cflags', 'glib-2.0'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) != 0: + raise SkipTest('Glib 2.0 dependency not available.') + with tempfile.TemporaryDirectory() as tempdirname: + self.init(testdir1, extra_args=['--prefix=' + tempdirname, '--libdir=lib'], default_args=False) + self.install(use_destdir=False) + shutil.rmtree(self.builddir) + os.mkdir(self.builddir) + pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig') + self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'libpkgdep.pc'))) + lib_dir = os.path.join(tempdirname, 'lib') + myenv = os.environ.copy() + myenv['PKG_CONFIG_PATH'] = pkg_dir + # Private internal libraries must not leak out. + pkg_out = subprocess.check_output(['pkg-config', '--static', '--libs', 'libpkgdep'], env=myenv) + self.assertNotIn(b'libpkgdep-int', pkg_out, 'Internal library leaked out.') + # Dependencies must not leak to cflags when building only a shared library. + pkg_out = subprocess.check_output(['pkg-config', '--cflags', 'libpkgdep'], env=myenv) + self.assertNotIn(b'glib', pkg_out, 'Internal dependency leaked to headers.') + # Test that the result is usable. + self.init(testdir2, override_envvars=myenv) + self.build(override_envvars=myenv) + myenv = os.environ.copy() + myenv['LD_LIBRARY_PATH'] = ':'.join([lib_dir, myenv.get('LD_LIBRARY_PATH', '')]) + if is_cygwin(): + bin_dir = os.path.join(tempdirname, 'bin') + myenv['PATH'] = bin_dir + os.pathsep + myenv['PATH'] + self.assertTrue(os.path.isdir(lib_dir)) + test_exe = os.path.join(self.builddir, 'pkguser') + self.assertTrue(os.path.isfile(test_exe)) + subprocess.check_call(test_exe, env=myenv) + + @skipIfNoPkgconfig + def test_pkgconfig_relative_paths(self): + testdir = os.path.join(self.unit_test_dir, '62 pkgconfig relative paths') + pkg_dir = os.path.join(testdir, 'pkgconfig') + self.assertPathExists(os.path.join(pkg_dir, 'librelativepath.pc')) + + env = get_fake_env(testdir, self.builddir, self.prefix) + env.coredata.set_options({OptionKey('pkg_config_path'): pkg_dir}, subproject='') + kwargs = {'required': True, 'silent': True} + relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs) + self.assertTrue(relative_path_dep.found()) + + # Ensure link_args are properly quoted + libpath = Path(self.builddir) / '../relativepath/lib' + link_args = ['-L' + libpath.as_posix(), '-lrelativepath'] + self.assertEqual(relative_path_dep.get_link_args(), link_args) + + @skipIfNoPkgconfig + def test_pkgconfig_duplicate_path_entries(self): + testdir = os.path.join(self.unit_test_dir, '111 pkgconfig duplicate path entries') + pkg_dir = os.path.join(testdir, 'pkgconfig') + + env = get_fake_env(testdir, self.builddir, self.prefix) + env.coredata.set_options({OptionKey('pkg_config_path'): pkg_dir}, subproject='') + + PkgConfigDependency.setup_env({}, env, MachineChoice.HOST, pkg_dir) + pkg_config_path = env.coredata.options[OptionKey('pkg_config_path')].value + self.assertEqual(len(pkg_config_path), 1) + + @skipIfNoPkgconfig + def test_pkgconfig_internal_libraries(self): + ''' + ''' + with tempfile.TemporaryDirectory() as tempdirname: + # build library + testdirbase = os.path.join(self.unit_test_dir, '32 pkgconfig use libraries') + testdirlib = os.path.join(testdirbase, 'lib') + self.init(testdirlib, extra_args=['--prefix=' + tempdirname, + '--libdir=lib', + '--default-library=static'], default_args=False) + self.build() + self.install(use_destdir=False) + + # build user of library + pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig') + self.new_builddir() + self.init(os.path.join(testdirbase, 'app'), + override_envvars={'PKG_CONFIG_PATH': pkg_dir}) + self.build() + + @skipIfNoPkgconfig + def test_static_archive_stripping(self): + ''' + Check that Meson produces valid static archives with --strip enabled + ''' + with tempfile.TemporaryDirectory() as tempdirname: + testdirbase = os.path.join(self.unit_test_dir, '66 static archive stripping') + + # build lib + self.new_builddir() + testdirlib = os.path.join(testdirbase, 'lib') + testlibprefix = os.path.join(tempdirname, 'libprefix') + self.init(testdirlib, extra_args=['--prefix=' + testlibprefix, + '--libdir=lib', + '--default-library=static', + '--buildtype=debug', + '--strip'], default_args=False) + self.build() + self.install(use_destdir=False) + + # build executable (uses lib, fails if static archive has been stripped incorrectly) + pkg_dir = os.path.join(testlibprefix, 'lib/pkgconfig') + self.new_builddir() + self.init(os.path.join(testdirbase, 'app'), + override_envvars={'PKG_CONFIG_PATH': pkg_dir}) + self.build() + + @skipIfNoPkgconfig + def test_pkgconfig_formatting(self): + testdir = os.path.join(self.unit_test_dir, '38 pkgconfig format') + self.init(testdir) + myenv = os.environ.copy() + myenv['PKG_CONFIG_PATH'] = self.privatedir + stdo = subprocess.check_output(['pkg-config', '--libs-only-l', 'libsomething'], env=myenv) + deps = [b'-lgobject-2.0', b'-lgio-2.0', b'-lglib-2.0', b'-lsomething'] + if is_windows() or is_cygwin() or is_osx() or is_openbsd(): + # On Windows, libintl is a separate library + deps.append(b'-lintl') + self.assertEqual(set(deps), set(stdo.split())) + + @skipIfNoPkgconfig + @skip_if_not_language('cs') + def test_pkgconfig_csharp_library(self): + testdir = os.path.join(self.unit_test_dir, '50 pkgconfig csharp library') + self.init(testdir) + myenv = os.environ.copy() + myenv['PKG_CONFIG_PATH'] = self.privatedir + stdo = subprocess.check_output(['pkg-config', '--libs', 'libsomething'], env=myenv) + + self.assertEqual("-r/usr/lib/libsomething.dll", str(stdo.decode('ascii')).strip()) + + @skipIfNoPkgconfig + def test_pkgconfig_link_order(self): + ''' + Test that libraries are listed before their dependencies. + ''' + testdir = os.path.join(self.unit_test_dir, '53 pkgconfig static link order') + self.init(testdir) + myenv = os.environ.copy() + myenv['PKG_CONFIG_PATH'] = self.privatedir + stdo = subprocess.check_output(['pkg-config', '--libs', 'libsomething'], env=myenv) + deps = stdo.split() + self.assertLess(deps.index(b'-lsomething'), deps.index(b'-ldependency')) + + def test_deterministic_dep_order(self): + ''' + Test that the dependencies are always listed in a deterministic order. + ''' + testdir = os.path.join(self.unit_test_dir, '43 dep order') + self.init(testdir) + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile: + for line in bfile: + if 'build myexe:' in line or 'build myexe.exe:' in line: + self.assertIn('liblib1.a liblib2.a', line) + return + raise RuntimeError('Could not find the build rule') + + def test_deterministic_rpath_order(self): + ''' + Test that the rpaths are always listed in a deterministic order. + ''' + if is_cygwin(): + raise SkipTest('rpath are not used on Cygwin') + testdir = os.path.join(self.unit_test_dir, '42 rpath order') + self.init(testdir) + if is_osx(): + rpathre = re.compile(r'-rpath,.*/subprojects/sub1.*-rpath,.*/subprojects/sub2') + else: + rpathre = re.compile(r'-rpath,\$\$ORIGIN/subprojects/sub1:\$\$ORIGIN/subprojects/sub2') + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile: + for line in bfile: + if '-rpath' in line: + self.assertRegex(line, rpathre) + return + raise RuntimeError('Could not find the rpath') + + def test_override_with_exe_dep(self): + ''' + Test that we produce the correct dependencies when a program is overridden with an executable. + ''' + testdir = os.path.join(self.src_root, 'test cases', 'native', '9 override with exe') + self.init(testdir) + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile: + for line in bfile: + if 'main1.c:' in line or 'main2.c:' in line: + self.assertIn('| subprojects/sub/foobar', line) + + @skipIfNoPkgconfig + def test_usage_external_library(self): + ''' + Test that uninstalled usage of an external library (from the system or + PkgConfigDependency) works. On macOS, this workflow works out of the + box. On Linux, BSDs, Windows, etc, you need to set extra arguments such + as LD_LIBRARY_PATH, etc, so this test is skipped. + + The system library is found with cc.find_library() and pkg-config deps. + ''' + oldprefix = self.prefix + # Install external library so we can find it + testdir = os.path.join(self.unit_test_dir, '40 external, internal library rpath', 'external library') + # install into installdir without using DESTDIR + installdir = self.installdir + self.prefix = installdir + self.init(testdir) + self.prefix = oldprefix + self.build() + self.install(use_destdir=False) + ## New builddir for the consumer + 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, '40 external, internal library rpath', 'built library') + # install into installdir without using DESTDIR + self.prefix = self.installdir + self.init(testdir, override_envvars=env) + self.prefix = oldprefix + self.build(override_envvars=env) + # test uninstalled + self.run_tests(override_envvars=env) + if not (is_osx() or is_linux()): + return + # test running after installation + self.install(use_destdir=False) + prog = os.path.join(self.installdir, 'bin', 'prog') + self._run([prog]) + if not is_osx(): + # Rest of the workflow only works on macOS + return + out = self._run(['otool', '-L', prog]) + self.assertNotIn('@rpath', out) + ## New builddir for testing that DESTDIR is not added to install_name + self.new_builddir() + # install into installdir with DESTDIR + self.init(testdir, override_envvars=env) + self.build(override_envvars=env) + # test running after installation + self.install(override_envvars=env) + prog = self.installdir + os.path.join(self.prefix, 'bin', 'prog') + lib = self.installdir + os.path.join(self.prefix, 'lib', 'libbar_built.dylib') + for f in prog, lib: + out = self._run(['otool', '-L', f]) + # Ensure that the otool output does not contain self.installdir + self.assertNotRegex(out, self.installdir + '.*dylib ') + + @skipIfNoPkgconfig + def test_link_arg_fullname(self): + ''' + Test for support of -l:libfullname.a + 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, '98 link full name','libtestprovider') + oldprefix = self.prefix + # install into installdir without using DESTDIR + installdir = self.installdir + self.prefix = installdir + self.init(testdir) + self.prefix=oldprefix + self.build() + self.install(use_destdir=False) + + 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, '98 link full name','proguser') + self.init(testdir,override_envvars=env) + + # test for link with full path + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile: + for line in bfile: + if 'build dprovidertest:' in line: + self.assertIn('/libtestprovider.a', line) + + if is_osx(): + # macOS's ld do not supports `--whole-archive`, skip build & run + return + + self.build(override_envvars=env) + + # skip test if pkg-config is too old. + # before v0.28, Libs flags like -Wl will not kept in context order with -l flags. + # see https://gitlab.freedesktop.org/pkg-config/pkg-config/-/blob/master/NEWS + pkgconfigver = subprocess.check_output(['pkg-config', '--version']) + if b'0.28' > pkgconfigver: + raise SkipTest('pkg-config is too old to be correctly done this.') + self.run_tests() + + @skipIfNoPkgconfig + def test_usage_pkgconfig_prefixes(self): + ''' + Build and install two external libraries, to different prefixes, + then build and install a client program that finds them via pkgconfig, + and verify the installed client program runs. + ''' + oldinstalldir = self.installdir + + # Build and install both external libraries without DESTDIR + val1dir = os.path.join(self.unit_test_dir, '75 pkgconfig prefixes', 'val1') + val1prefix = os.path.join(oldinstalldir, 'val1') + self.prefix = val1prefix + self.installdir = val1prefix + self.init(val1dir) + self.build() + self.install(use_destdir=False) + self.new_builddir() + + env1 = {} + env1['PKG_CONFIG_PATH'] = os.path.join(val1prefix, self.libdir, 'pkgconfig') + val2dir = os.path.join(self.unit_test_dir, '75 pkgconfig prefixes', 'val2') + val2prefix = os.path.join(oldinstalldir, 'val2') + self.prefix = val2prefix + self.installdir = val2prefix + self.init(val2dir, override_envvars=env1) + self.build() + self.install(use_destdir=False) + self.new_builddir() + + # Build, install, and run the client program + env2 = {} + env2['PKG_CONFIG_PATH'] = os.path.join(val2prefix, self.libdir, 'pkgconfig') + testdir = os.path.join(self.unit_test_dir, '75 pkgconfig prefixes', 'client') + testprefix = os.path.join(oldinstalldir, 'client') + self.prefix = testprefix + self.installdir = testprefix + self.init(testdir, override_envvars=env2) + self.build() + self.install(use_destdir=False) + prog = os.path.join(self.installdir, 'bin', 'client') + env3 = {} + if is_cygwin(): + env3['PATH'] = os.path.join(val1prefix, 'bin') + \ + os.pathsep + \ + os.path.join(val2prefix, 'bin') + \ + os.pathsep + os.environ['PATH'] + out = self._run([prog], override_envvars=env3).strip() + # Expected output is val1 + val2 = 3 + self.assertEqual(out, '3') + + def install_subdir_invalid_symlinks(self, testdir, subdir_path): + ''' + Test that installation of broken symlinks works fine. + https://github.com/mesonbuild/meson/issues/3914 + ''' + testdir = os.path.join(self.common_test_dir, testdir) + subdir = os.path.join(testdir, subdir_path) + with chdir(subdir): + # Can't distribute broken symlinks in the source tree because it breaks + # the creation of zipapps. Create it dynamically and run the test by + # hand. + src = '../../nonexistent.txt' + os.symlink(src, 'invalid-symlink.txt') + try: + self.init(testdir) + self.build() + self.install() + install_path = subdir_path.split(os.path.sep)[-1] + link = os.path.join(self.installdir, 'usr', 'share', install_path, 'invalid-symlink.txt') + self.assertTrue(os.path.islink(link), msg=link) + self.assertEqual(src, os.readlink(link)) + self.assertFalse(os.path.isfile(link), msg=link) + finally: + os.remove(os.path.join(subdir, 'invalid-symlink.txt')) + + def test_install_subdir_symlinks(self): + self.install_subdir_invalid_symlinks('59 install subdir', os.path.join('sub', 'sub1')) + + def test_install_subdir_symlinks_with_default_umask(self): + self.install_subdir_invalid_symlinks('190 install_mode', 'sub2') + + def test_install_subdir_symlinks_with_default_umask_and_mode(self): + self.install_subdir_invalid_symlinks('190 install_mode', 'sub1') + + @skipIfNoPkgconfigDep('gmodule-2.0') + def test_ldflag_dedup(self): + testdir = os.path.join(self.unit_test_dir, '52 ldflagdedup') + if is_cygwin() or is_osx(): + raise SkipTest('Not applicable on Cygwin or OSX.') + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + linker = cc.linker + if not linker.export_dynamic_args(env): + raise SkipTest('Not applicable for linkers without --export-dynamic') + self.init(testdir) + build_ninja = os.path.join(self.builddir, 'build.ninja') + max_count = 0 + search_term = '-Wl,--export-dynamic' + with open(build_ninja, encoding='utf-8') as f: + for line in f: + max_count = max(max_count, line.count(search_term)) + self.assertEqual(max_count, 1, 'Export dynamic incorrectly deduplicated.') + + def test_compiler_libs_static_dedup(self): + testdir = os.path.join(self.unit_test_dir, '56 dedup compiler libs') + self.init(testdir) + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + lines = f.readlines() + for lib in ('-ldl', '-lm', '-lc', '-lrt'): + for line in lines: + if lib not in line: + continue + # Assert that + self.assertEqual(len(line.split(lib)), 2, msg=(lib, line)) + + @skipIfNoPkgconfig + def test_noncross_options(self): + # C_std defined in project options must be in effect also when native compiling. + testdir = os.path.join(self.unit_test_dir, '51 noncross options') + self.init(testdir, extra_args=['-Dpkg_config_path=' + testdir]) + compdb = self.get_compdb() + self.assertEqual(len(compdb), 2) + self.assertRegex(compdb[0]['command'], '-std=c99') + self.assertRegex(compdb[1]['command'], '-std=c99') + self.build() + + def test_identity_cross(self): + testdir = os.path.join(self.unit_test_dir, '61 identity cross') + + constantsfile = tempfile.NamedTemporaryFile(mode='w') + constantsfile.write(textwrap.dedent('''\ + [constants] + py_ext = '.py' + ''')) + constantsfile.flush() + + nativefile = tempfile.NamedTemporaryFile(mode='w') + nativefile.write(textwrap.dedent('''\ + [binaries] + c = ['{}' + py_ext] + '''.format(os.path.join(testdir, 'build_wrapper')))) + nativefile.flush() + self.meson_native_files = [constantsfile.name, nativefile.name] + + crossfile = tempfile.NamedTemporaryFile(mode='w') + crossfile.write(textwrap.dedent('''\ + [binaries] + c = ['{}' + py_ext] + '''.format(os.path.join(testdir, 'host_wrapper')))) + crossfile.flush() + self.meson_cross_files = [constantsfile.name, crossfile.name] + + # TODO should someday be explicit about build platform only here + self.init(testdir) + + def test_identity_cross_env(self): + testdir = os.path.join(self.unit_test_dir, '61 identity cross') + env = { + 'CC_FOR_BUILD': '"' + os.path.join(testdir, 'build_wrapper.py') + '"', + } + crossfile = tempfile.NamedTemporaryFile(mode='w') + crossfile.write(textwrap.dedent('''\ + [binaries] + c = ['{}'] + '''.format(os.path.join(testdir, 'host_wrapper.py')))) + crossfile.flush() + self.meson_cross_files = [crossfile.name] + # TODO should someday be explicit about build platform only here + self.init(testdir, override_envvars=env) + + @skipIfNoPkgconfig + def test_static_link(self): + if is_cygwin(): + raise SkipTest("Cygwin doesn't support LD_LIBRARY_PATH.") + + # Build some libraries and install them + testdir = os.path.join(self.unit_test_dir, '67 static link/lib') + libdir = os.path.join(self.installdir, self.libdir) + oldprefix = self.prefix + self.prefix = self.installdir + self.init(testdir) + self.install(use_destdir=False) + + # Test that installed libraries works + self.new_builddir() + self.prefix = oldprefix + meson_args = [f'-Dc_link_args=-L{libdir}', + '--fatal-meson-warnings'] + testdir = os.path.join(self.unit_test_dir, '67 static link') + env = {'PKG_CONFIG_LIBDIR': os.path.join(libdir, 'pkgconfig')} + self.init(testdir, extra_args=meson_args, override_envvars=env) + self.build() + self.run_tests() + + def _check_ld(self, check: str, name: str, lang: str, expected: str) -> None: + if is_sunos(): + raise SkipTest('Solaris currently cannot override the linker.') + if not shutil.which(check): + raise SkipTest(f'Could not find {check}.') + envvars = [mesonbuild.envconfig.ENV_VAR_PROG_MAP[f'{lang}_ld']] + + # Also test a deprecated variable if there is one. + if f'{lang}_ld' in mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP: + envvars.append( + mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP[f'{lang}_ld']) + + for envvar in envvars: + with mock.patch.dict(os.environ, {envvar: name}): + env = get_fake_env() + comp = compiler_from_language(env, lang, MachineChoice.HOST) + if isinstance(comp, (AppleClangCCompiler, AppleClangCPPCompiler, + AppleClangObjCCompiler, AppleClangObjCPPCompiler)): + raise SkipTest('AppleClang is currently only supported with ld64') + if lang != 'rust' and comp.use_linker_args('bfd') == []: + raise SkipTest( + f'Compiler {comp.id} does not support using alternative linkers') + self.assertEqual(comp.linker.id, expected) + + def test_ld_environment_variable_bfd(self): + self._check_ld('ld.bfd', 'bfd', 'c', 'ld.bfd') + + def test_ld_environment_variable_gold(self): + self._check_ld('ld.gold', 'gold', 'c', 'ld.gold') + + def test_ld_environment_variable_lld(self): + self._check_ld('ld.lld', 'lld', 'c', 'ld.lld') + + @skip_if_not_language('rust') + @skipIfNoExecutable('ld.gold') # need an additional check here because _check_ld checks for gcc + def test_ld_environment_variable_rust(self): + self._check_ld('gcc', 'gcc -fuse-ld=gold', 'rust', 'ld.gold') + + def test_ld_environment_variable_cpp(self): + self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold') + + @skip_if_not_language('objc') + def test_ld_environment_variable_objc(self): + self._check_ld('ld.gold', 'gold', 'objc', 'ld.gold') + + @skip_if_not_language('objcpp') + def test_ld_environment_variable_objcpp(self): + self._check_ld('ld.gold', 'gold', 'objcpp', 'ld.gold') + + @skip_if_not_language('fortran') + def test_ld_environment_variable_fortran(self): + self._check_ld('ld.gold', 'gold', 'fortran', 'ld.gold') + + @skip_if_not_language('d') + def test_ld_environment_variable_d(self): + # At least for me, ldc defaults to gold, and gdc defaults to bfd, so + # let's pick lld, which isn't the default for either (currently) + if is_osx(): + expected = 'ld64' + else: + expected = 'ld.lld' + self._check_ld('ld.lld', 'lld', 'd', expected) + + def compute_sha256(self, filename): + with open(filename, 'rb') as f: + return hashlib.sha256(f.read()).hexdigest() + + def test_wrap_with_file_url(self): + testdir = os.path.join(self.unit_test_dir, '73 wrap file url') + source_filename = os.path.join(testdir, 'subprojects', 'foo.tar.xz') + patch_filename = os.path.join(testdir, 'subprojects', 'foo-patch.tar.xz') + wrap_filename = os.path.join(testdir, 'subprojects', 'foo.wrap') + source_hash = self.compute_sha256(source_filename) + patch_hash = self.compute_sha256(patch_filename) + wrap = textwrap.dedent("""\ + [wrap-file] + directory = foo + + source_url = http://server.invalid/foo + source_fallback_url = file://{} + source_filename = foo.tar.xz + source_hash = {} + + patch_url = http://server.invalid/foo + patch_fallback_url = file://{} + patch_filename = foo-patch.tar.xz + patch_hash = {} + """.format(source_filename, source_hash, patch_filename, patch_hash)) + with open(wrap_filename, 'w', encoding='utf-8') as f: + f.write(wrap) + self.init(testdir) + self.build() + self.run_tests() + + windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'packagecache')) + windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'foo')) + os.unlink(wrap_filename) + + def test_no_rpath_for_static(self): + testdir = os.path.join(self.common_test_dir, '5 linkstatic') + self.init(testdir) + self.build() + build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) + self.assertIsNone(build_rpath) + + def test_lookup_system_after_broken_fallback(self): + # Just to generate libfoo.pc so we can test system dependency lookup. + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir) + privatedir = self.privatedir + + # Write test project where the first dependency() returns not-found + # because 'broken' subproject does not exit, but that should not prevent + # the 2nd dependency() to lookup on system. + self.new_builddir() + with tempfile.TemporaryDirectory() as d: + with open(os.path.join(d, 'meson.build'), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + project('test') + dependency('notfound', fallback: 'broken', required: false) + dependency('libfoo', fallback: 'broken', required: true) + ''')) + self.init(d, override_envvars={'PKG_CONFIG_LIBDIR': privatedir}) + + def test_as_link_whole(self): + testdir = os.path.join(self.unit_test_dir, '77 as link whole') + self.init(testdir) + with open(os.path.join(self.privatedir, 'bar1.pc'), encoding='utf-8') as f: + content = f.read() + self.assertIn('-lfoo', content) + with open(os.path.join(self.privatedir, 'bar2.pc'), encoding='utf-8') as f: + content = f.read() + self.assertNotIn('-lfoo', content) + + def test_prelinking(self): + # Prelinking currently only works on recently new GNU toolchains. + # Skip everything else. When support for other toolchains is added, + # remove limitations as necessary. + if is_osx(): + raise SkipTest('Prelinking not supported on Darwin.') + if 'clang' in os.environ.get('CC', 'dummy'): + raise SkipTest('Prelinking not supported with Clang.') + testdir = os.path.join(self.unit_test_dir, '87 prelinking') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.id == "gcc": + gccver = subprocess.check_output(['gcc', '--version']) + if b'7.5.0' in gccver: + raise SkipTest('GCC on Bionic is too old to be supported.') + self.init(testdir) + self.build() + outlib = os.path.join(self.builddir, 'libprelinked.a') + ar = shutil.which('ar') + self.assertPathExists(outlib) + self.assertIsNotNone(ar) + p = subprocess.run([ar, 't', outlib], + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + universal_newlines=True, timeout=1) + obj_files = p.stdout.strip().split('\n') + self.assertEqual(len(obj_files), 1) + self.assertTrue(obj_files[0].endswith('-prelink.o')) + + def do_one_test_with_nativefile(self, testdir, args): + testdir = os.path.join(self.common_test_dir, testdir) + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'nativefile' + with p.open('wt', encoding='utf-8') as f: + f.write(f'''[binaries] + c = {args} + ''') + self.init(testdir, extra_args=['--native-file=' + str(p)]) + self.build() + + def test_cmake_multilib(self): + ''' + Test that the cmake module handles multilib paths correctly. + ''' + # Verify that "gcc -m32" works + try: + self.do_one_test_with_nativefile('1 trivial', "['gcc', '-m32']") + except subprocess.CalledProcessError as e: + raise SkipTest('Not GCC, or GCC does not have the -m32 option') + self.wipe() + + # Verify that cmake works + try: + self.do_one_test_with_nativefile('../cmake/1 basic', "['gcc']") + except subprocess.CalledProcessError as e: + raise SkipTest('Could not build basic cmake project') + self.wipe() + + # If so, we can test that cmake works with "gcc -m32" + self.do_one_test_with_nativefile('../cmake/1 basic', "['gcc', '-m32']") diff -Nru meson-0.53.2/unittests/machinefiletests.py meson-0.61.2/unittests/machinefiletests.py --- meson-0.53.2/unittests/machinefiletests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/machinefiletests.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,935 @@ +# Copyright 2016-2021 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 subprocess +import tempfile +import textwrap +import os +import shutil +import functools +import threading +import sys +from itertools import chain +from unittest import mock, skipIf, SkipTest +from pathlib import Path +import typing as T + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + MachineChoice, is_windows, is_osx, is_cygwin, is_haiku, is_sunos +) +from mesonbuild.compilers import ( + detect_swift_compiler, compiler_from_language +) +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@functools.lru_cache() +def is_real_gnu_compiler(path): + ''' + Check if the gcc we have is a real gcc and not a macOS wrapper around clang + ''' + if not path: + return False + out = subprocess.check_output([path, '--version'], universal_newlines=True, stderr=subprocess.STDOUT) + return 'Free Software Foundation' in out + +class NativeFileTests(BasePlatformTests): + + def setUp(self): + super().setUp() + self.testcase = os.path.join(self.unit_test_dir, '47 native file binary') + self.current_config = 0 + self.current_wrapper = 0 + + def helper_create_native_file(self, values): + """Create a config file as a temporary file. + + values should be a nested dictionary structure of {section: {key: + value}} + """ + filename = os.path.join(self.builddir, f'generated{self.current_config}.config') + self.current_config += 1 + with open(filename, 'wt', encoding='utf-8') as f: + for section, entries in values.items(): + f.write(f'[{section}]\n') + for k, v in entries.items(): + if isinstance(v, (bool, int, float)): + f.write(f"{k}={v}\n") + elif isinstance(v, list): + f.write("{}=[{}]\n".format(k, ', '.join([f"'{w}'" for w in v]))) + else: + f.write(f"{k}='{v}'\n") + return filename + + def helper_create_binary_wrapper(self, binary, dir_=None, extra_args=None, **kwargs): + """Creates a wrapper around a binary that overrides specific values.""" + filename = os.path.join(dir_ or self.builddir, f'binary_wrapper{self.current_wrapper}.py') + extra_args = extra_args or {} + self.current_wrapper += 1 + if is_haiku(): + chbang = '#!/bin/env python3' + else: + chbang = '#!/usr/bin/env python3' + + with open(filename, 'wt', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + {} + import argparse + import subprocess + import sys + + def main(): + parser = argparse.ArgumentParser() + '''.format(chbang))) + for name in chain(extra_args, kwargs): + f.write(' parser.add_argument("-{0}", "--{0}", action="store_true")\n'.format(name)) + f.write(' args, extra_args = parser.parse_known_args()\n') + for name, value in chain(extra_args.items(), kwargs.items()): + f.write(f' if args.{name}:\n') + f.write(' print("{}", file=sys.{})\n'.format(value, kwargs.get('outfile', 'stdout'))) + f.write(' sys.exit(0)\n') + f.write(textwrap.dedent(''' + ret = subprocess.run( + ["{}"] + extra_args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + print(ret.stdout.decode('utf-8')) + print(ret.stderr.decode('utf-8'), file=sys.stderr) + sys.exit(ret.returncode) + + if __name__ == '__main__': + main() + '''.format(binary))) + + if not is_windows(): + os.chmod(filename, 0o755) + return filename + + # On windows we need yet another level of indirection, as cmd cannot + # invoke python files itself, so instead we generate a .bat file, which + # invokes our python wrapper + batfile = os.path.join(self.builddir, f'binary_wrapper{self.current_wrapper}.bat') + with open(batfile, 'wt', encoding='utf-8') as f: + f.write(fr'@{sys.executable} {filename} %*') + return batfile + + def helper_for_compiler(self, lang, cb, for_machine = MachineChoice.HOST): + """Helper for generating tests for overriding compilers for langaugages + with more than one implementation, such as C, C++, ObjC, ObjC++, and D. + """ + env = get_fake_env() + getter = lambda: compiler_from_language(env, lang, for_machine) + cc = getter() + binary, newid = cb(cc) + env.binaries[for_machine].binaries[lang] = binary + compiler = getter() + self.assertEqual(compiler.id, newid) + + def test_multiple_native_files_override(self): + wrapper = self.helper_create_binary_wrapper('bash', version='foo') + config = self.helper_create_native_file({'binaries': {'bash': wrapper}}) + wrapper = self.helper_create_binary_wrapper('bash', version='12345') + config2 = self.helper_create_native_file({'binaries': {'bash': wrapper}}) + self.init(self.testcase, extra_args=[ + '--native-file', config, '--native-file', config2, + '-Dcase=find_program']) + + # This test hangs on cygwin. + @skipIf(os.name != 'posix' or is_cygwin(), 'Uses fifos, which are not available on non Unix OSes.') + def test_native_file_is_pipe(self): + fifo = os.path.join(self.builddir, 'native.file') + os.mkfifo(fifo) + with tempfile.TemporaryDirectory() as d: + wrapper = self.helper_create_binary_wrapper('bash', d, version='12345') + + def filler(): + with open(fifo, 'w', encoding='utf-8') as f: + f.write('[binaries]\n') + f.write(f"bash = '{wrapper}'\n") + + thread = threading.Thread(target=filler) + thread.start() + + self.init(self.testcase, extra_args=['--native-file', fifo, '-Dcase=find_program']) + + thread.join() + os.unlink(fifo) + + self.init(self.testcase, extra_args=['--wipe']) + + def test_multiple_native_files(self): + wrapper = self.helper_create_binary_wrapper('bash', version='12345') + config = self.helper_create_native_file({'binaries': {'bash': wrapper}}) + wrapper = self.helper_create_binary_wrapper('python') + config2 = self.helper_create_native_file({'binaries': {'python': wrapper}}) + self.init(self.testcase, extra_args=[ + '--native-file', config, '--native-file', config2, + '-Dcase=find_program']) + + def _simple_test(self, case, binary, entry=None): + wrapper = self.helper_create_binary_wrapper(binary, version='12345') + config = self.helper_create_native_file({'binaries': {entry or binary: wrapper}}) + self.init(self.testcase, extra_args=['--native-file', config, f'-Dcase={case}']) + + def test_find_program(self): + self._simple_test('find_program', 'bash') + + def test_config_tool_dep(self): + # Do the skip at this level to avoid screwing up the cache + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with LLVM on MSYS2') + if not shutil.which('llvm-config'): + raise SkipTest('No llvm-installed, cannot test') + self._simple_test('config_dep', 'llvm-config') + + def test_python3_module(self): + self._simple_test('python3', 'python3') + + def test_python_module(self): + if is_windows(): + # Bat adds extra crap to stdout, so the version check logic in the + # python module breaks. This is fine on other OSes because they + # don't need the extra indirection. + raise SkipTest('bat indirection breaks internal sanity checks.') + elif is_osx(): + binary = 'python' + else: + binary = 'python2' + + # We not have python2, check for it + for v in ['2', '2.7', '-2.7']: + rc = subprocess.call(['pkg-config', '--cflags', f'python{v}'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + if rc == 0: + break + else: + raise SkipTest('Not running Python 2 tests because dev packages not installed.') + self._simple_test('python', binary, entry='python') + + @skipIf(is_windows(), 'Setting up multiple compilers on windows is hard') + @skip_if_env_set('CC') + def test_c_compiler(self): + def cb(comp): + if comp.id == 'gcc': + if not shutil.which('clang'): + raise SkipTest('Only one compiler found, cannot test.') + return 'clang', 'clang' + if not is_real_gnu_compiler(shutil.which('gcc')): + raise SkipTest('Only one compiler found, cannot test.') + return 'gcc', 'gcc' + self.helper_for_compiler('c', cb) + + @skipIf(is_windows(), 'Setting up multiple compilers on windows is hard') + @skip_if_env_set('CXX') + def test_cpp_compiler(self): + def cb(comp): + if comp.id == 'gcc': + if not shutil.which('clang++'): + raise SkipTest('Only one compiler found, cannot test.') + return 'clang++', 'clang' + if not is_real_gnu_compiler(shutil.which('g++')): + raise SkipTest('Only one compiler found, cannot test.') + return 'g++', 'gcc' + self.helper_for_compiler('cpp', cb) + + @skip_if_not_language('objc') + @skip_if_env_set('OBJC') + def test_objc_compiler(self): + def cb(comp): + if comp.id == 'gcc': + if not shutil.which('clang'): + raise SkipTest('Only one compiler found, cannot test.') + return 'clang', 'clang' + if not is_real_gnu_compiler(shutil.which('gcc')): + raise SkipTest('Only one compiler found, cannot test.') + return 'gcc', 'gcc' + self.helper_for_compiler('objc', cb) + + @skip_if_not_language('objcpp') + @skip_if_env_set('OBJCXX') + def test_objcpp_compiler(self): + def cb(comp): + if comp.id == 'gcc': + if not shutil.which('clang++'): + raise SkipTest('Only one compiler found, cannot test.') + return 'clang++', 'clang' + if not is_real_gnu_compiler(shutil.which('g++')): + raise SkipTest('Only one compiler found, cannot test.') + return 'g++', 'gcc' + self.helper_for_compiler('objcpp', cb) + + @skip_if_not_language('d') + @skip_if_env_set('DC') + def test_d_compiler(self): + def cb(comp): + if comp.id == 'dmd': + if shutil.which('ldc'): + return 'ldc', 'ldc' + elif shutil.which('gdc'): + return 'gdc', 'gdc' + else: + raise SkipTest('No alternative dlang compiler found.') + if shutil.which('dmd'): + return 'dmd', 'dmd' + raise SkipTest('No alternative dlang compiler found.') + self.helper_for_compiler('d', cb) + + @skip_if_not_language('cs') + @skip_if_env_set('CSC') + def test_cs_compiler(self): + def cb(comp): + if comp.id == 'csc': + if not shutil.which('mcs'): + raise SkipTest('No alternate C# implementation.') + return 'mcs', 'mcs' + if not shutil.which('csc'): + raise SkipTest('No alternate C# implementation.') + return 'csc', 'csc' + self.helper_for_compiler('cs', cb) + + @skip_if_not_language('fortran') + @skip_if_env_set('FC') + def test_fortran_compiler(self): + def cb(comp): + if comp.id == 'lcc': + if shutil.which('lfortran'): + return 'lfortran', 'lcc' + raise SkipTest('No alternate Fortran implementation.') + elif comp.id == 'gcc': + if shutil.which('ifort'): + # There is an ICC for windows (windows build, linux host), + # but we don't support that ATM so lets not worry about it. + if is_windows(): + return 'ifort', 'intel-cl' + return 'ifort', 'intel' + elif shutil.which('flang'): + return 'flang', 'flang' + elif shutil.which('pgfortran'): + return 'pgfortran', 'pgi' + # XXX: there are several other fortran compilers meson + # supports, but I don't have any of them to test with + raise SkipTest('No alternate Fortran implementation.') + if not shutil.which('gfortran'): + raise SkipTest('No alternate Fortran implementation.') + return 'gfortran', 'gcc' + self.helper_for_compiler('fortran', cb) + + def _single_implementation_compiler(self, lang: str, binary: str, version_str: str, version: str) -> None: + """Helper for languages with a single (supported) implementation. + + Builds a wrapper around the compiler to override the version. + """ + wrapper = self.helper_create_binary_wrapper(binary, version=version_str) + env = get_fake_env() + env.binaries.host.binaries[lang] = [wrapper] + compiler = compiler_from_language(env, lang, MachineChoice.HOST) + self.assertEqual(compiler.version, version) + + @skip_if_not_language('vala') + @skip_if_env_set('VALAC') + def test_vala_compiler(self): + self._single_implementation_compiler( + 'vala', 'valac', 'Vala 1.2345', '1.2345') + + @skip_if_not_language('rust') + @skip_if_env_set('RUSTC') + def test_rust_compiler(self): + self._single_implementation_compiler( + 'rust', 'rustc', 'rustc 1.2345', '1.2345') + + @skip_if_not_language('java') + def test_java_compiler(self): + self._single_implementation_compiler( + 'java', 'javac', 'javac 9.99.77', '9.99.77') + + @skip_if_not_language('swift') + def test_swift_compiler(self): + wrapper = self.helper_create_binary_wrapper( + 'swiftc', version='Swift 1.2345', outfile='stderr', + extra_args={'Xlinker': 'macosx_version. PROJECT:ld - 1.2.3'}) + env = get_fake_env() + env.binaries.host.binaries['swift'] = [wrapper] + compiler = detect_swift_compiler(env, MachineChoice.HOST) + self.assertEqual(compiler.version, '1.2345') + + def test_native_file_dirs(self): + testcase = os.path.join(self.unit_test_dir, '60 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile')]) + + def test_native_file_dirs_overridden(self): + testcase = os.path.join(self.unit_test_dir, '60 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '-Ddef_libdir=liblib', '-Dlibdir=liblib']) + + def test_compile_sys_path(self): + """Compiling with a native file stored in a system path works. + + There was a bug which caused the paths to be stored incorrectly and + would result in ninja invoking meson in an infinite loop. This tests + for that by actually invoking ninja. + """ + testcase = os.path.join(self.common_test_dir, '1 trivial') + + # It really doesn't matter what's in the native file, just that it exists + config = self.helper_create_native_file({'binaries': {'bash': 'false'}}) + + self.init(testcase, extra_args=['--native-file', config]) + self.build() + + def test_user_options(self): + testcase = os.path.join(self.common_test_dir, '40 options') + for opt, value in [('testoption', 'some other val'), ('other_one', True), + ('combo_opt', 'one'), ('array_opt', ['two']), + ('integer_opt', 0), + ('CaseSenSiTivE', 'SOME other Value'), + ('CASESENSITIVE', 'some other Value')]: + config = self.helper_create_native_file({'project options': {opt: value}}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--native-file', config]) + self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + def test_user_options_command_line_overrides(self): + testcase = os.path.join(self.common_test_dir, '40 options') + config = self.helper_create_native_file({'project options': {'other_one': True}}) + self.init(testcase, extra_args=['--native-file', config, '-Dother_one=false']) + + def test_user_options_subproject(self): + testcase = os.path.join(self.unit_test_dir, '79 user options for subproject') + + s = os.path.join(testcase, 'subprojects') + if not os.path.exists(s): + os.mkdir(s) + s = os.path.join(s, 'sub') + if not os.path.exists(s): + sub = os.path.join(self.common_test_dir, '40 options') + shutil.copytree(sub, s) + + for opt, value in [('testoption', 'some other val'), ('other_one', True), + ('combo_opt', 'one'), ('array_opt', ['two']), + ('integer_opt', 0)]: + config = self.helper_create_native_file({'sub:project options': {opt: value}}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--native-file', config]) + self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + def test_option_bool(self): + # Bools are allowed to be unquoted + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({'built-in options': {'werror': True}}) + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + # Test that no-per subproject options are inherited from the parent + if 'werror' in each['name']: + self.assertEqual(each['value'], True) + break + else: + self.fail('Did not find werror in build options?') + + def test_option_integer(self): + # Bools are allowed to be unquoted + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({'built-in options': {'unity_size': 100}}) + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + # Test that no-per subproject options are inherited from the parent + if 'unity_size' in each['name']: + self.assertEqual(each['value'], 100) + break + else: + self.fail('Did not find unity_size in build options?') + + def test_builtin_options(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_native_file({'built-in options': {'cpp_std': 'c++14'}}) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++14') + break + else: + self.fail('Did not find werror in build options?') + + def test_builtin_options_conf_overrides_env(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_native_file({'built-in options': {'pkg_config_path': '/foo'}}) + + self.init(testcase, extra_args=['--native-file', config], override_envvars={'PKG_CONFIG_PATH': '/bar'}) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/foo']) + break + else: + self.fail('Did not find pkg_config_path in build options?') + + def test_builtin_options_subprojects(self): + testcase = os.path.join(self.common_test_dir, '98 subproject subdir') + config = self.helper_create_native_file({'built-in options': {'default_library': 'both', 'c_args': ['-Dfoo']}, 'sub:built-in options': {'default_library': 'static'}}) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + # Test that no-per subproject options are inherited from the parent + if 'c_args' in each['name']: + # This path will be hit twice, once for build and once for host, + self.assertEqual(each['value'], ['-Dfoo']) + found += 1 + elif each['name'] == 'default_library': + self.assertEqual(each['value'], 'both') + found += 1 + elif each['name'] == 'sub:default_library': + self.assertEqual(each['value'], 'static') + found += 1 + self.assertEqual(found, 4, 'Did not find all three sections') + + def test_builtin_options_subprojects_overrides_buildfiles(self): + # If the buildfile says subproject(... default_library: shared), ensure that's overwritten + testcase = os.path.join(self.common_test_dir, '223 persubproject options') + config = self.helper_create_native_file({'sub2:built-in options': {'default_library': 'shared'}}) + + with self.assertRaises((RuntimeError, subprocess.CalledProcessError)) as cm: + self.init(testcase, extra_args=['--native-file', config]) + if isinstance(cm, RuntimeError): + check = str(cm.exception) + else: + check = cm.exception.stdout + self.assertIn(check, 'Parent should override default_library') + + def test_builtin_options_subprojects_dont_inherits_parent_override(self): + # If the buildfile says subproject(... default_library: shared), ensure that's overwritten + testcase = os.path.join(self.common_test_dir, '223 persubproject options') + config = self.helper_create_native_file({'built-in options': {'default_library': 'both'}}) + self.init(testcase, extra_args=['--native-file', config]) + + def test_builtin_options_compiler_properties(self): + # the properties section can have lang_args, and those need to be + # overwritten by the built-in options + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'c_args': ['-DFOO']}, + 'properties': {'c_args': ['-DBAR']}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'c_args': + self.assertEqual(each['value'], ['-DFOO']) + break + else: + self.fail('Did not find c_args in build options?') + + def test_builtin_options_compiler_properties_legacy(self): + # The legacy placement in properties is still valid if a 'built-in + # options' setting is present, but doesn't have the lang_args + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'default_library': 'static'}, + 'properties': {'c_args': ['-DBAR']}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'c_args': + self.assertEqual(each['value'], ['-DBAR']) + break + else: + self.fail('Did not find c_args in build options?') + + def test_builtin_options_paths(self): + # the properties section can have lang_args, and those need to be + # overwritten by the built-in options + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'bindir': 'foo'}, + 'paths': {'bindir': 'bar'}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'bindir': + self.assertEqual(each['value'], 'foo') + break + else: + self.fail('Did not find bindir in build options?') + + def test_builtin_options_paths_legacy(self): + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'default_library': 'static'}, + 'paths': {'bindir': 'bar'}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'bindir': + self.assertEqual(each['value'], 'bar') + break + else: + self.fail('Did not find bindir in build options?') + + +class CrossFileTests(BasePlatformTests): + + """Tests for cross file functionality not directly related to + cross compiling. + + This is mainly aimed to testing overrides from cross files. + """ + + def setUp(self): + super().setUp() + self.current_config = 0 + self.current_wrapper = 0 + + def _cross_file_generator(self, *, needs_exe_wrapper: bool = False, + exe_wrapper: T.Optional[T.List[str]] = None) -> str: + if is_windows(): + raise SkipTest('Cannot run this test on non-mingw/non-cygwin windows') + + return textwrap.dedent(f"""\ + [binaries] + c = '{shutil.which('gcc' if is_sunos() else 'cc')}' + ar = '{shutil.which('ar')}' + strip = '{shutil.which('strip')}' + exe_wrapper = {str(exe_wrapper) if exe_wrapper is not None else '[]'} + + [properties] + needs_exe_wrapper = {needs_exe_wrapper} + + [host_machine] + system = 'linux' + cpu_family = 'x86' + cpu = 'i686' + endian = 'little' + """) + + def _stub_exe_wrapper(self) -> str: + return textwrap.dedent('''\ + #!/usr/bin/env python3 + import subprocess + import sys + + sys.exit(subprocess.run(sys.argv[1:]).returncode) + ''') + + def test_needs_exe_wrapper_true(self): + testdir = os.path.join(self.unit_test_dir, '71 cross test passed') + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'crossfile' + with p.open('wt', encoding='utf-8') as f: + f.write(self._cross_file_generator(needs_exe_wrapper=True)) + self.init(testdir, extra_args=['--cross-file=' + str(p)]) + out = self.run_target('test') + self.assertRegex(out, r'Skipped:\s*1\s*\n') + + def test_needs_exe_wrapper_false(self): + testdir = os.path.join(self.unit_test_dir, '71 cross test passed') + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'crossfile' + with p.open('wt', encoding='utf-8') as f: + f.write(self._cross_file_generator(needs_exe_wrapper=False)) + self.init(testdir, extra_args=['--cross-file=' + str(p)]) + out = self.run_target('test') + self.assertNotRegex(out, r'Skipped:\s*1\n') + + def test_needs_exe_wrapper_true_wrapper(self): + testdir = os.path.join(self.unit_test_dir, '71 cross test passed') + with tempfile.TemporaryDirectory() as d: + s = Path(d) / 'wrapper.py' + with s.open('wt', encoding='utf-8') as f: + f.write(self._stub_exe_wrapper()) + s.chmod(0o774) + p = Path(d) / 'crossfile' + with p.open('wt', encoding='utf-8') as f: + f.write(self._cross_file_generator( + needs_exe_wrapper=True, + exe_wrapper=[str(s)])) + + self.init(testdir, extra_args=['--cross-file=' + str(p), '-Dexpect=true']) + out = self.run_target('test') + self.assertRegex(out, r'Ok:\s*3\s*\n') + + def test_cross_exe_passed_no_wrapper(self): + testdir = os.path.join(self.unit_test_dir, '71 cross test passed') + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'crossfile' + with p.open('wt', encoding='utf-8') as f: + f.write(self._cross_file_generator(needs_exe_wrapper=True)) + + self.init(testdir, extra_args=['--cross-file=' + str(p)]) + self.build() + out = self.run_target('test') + self.assertRegex(out, r'Skipped:\s*1\s*\n') + + # The test uses mocking and thus requires that the current process is the + # one to run the Meson steps. If we are using an external test executable + # (most commonly in Debian autopkgtests) then the mocking won't work. + @skipIf('MESON_EXE' in os.environ, 'MESON_EXE is defined, can not use mocking.') + def test_cross_file_system_paths(self): + if is_windows(): + raise SkipTest('system crossfile paths not defined for Windows (yet)') + + testdir = os.path.join(self.common_test_dir, '1 trivial') + cross_content = self._cross_file_generator() + with tempfile.TemporaryDirectory() as d: + dir_ = os.path.join(d, 'meson', 'cross') + os.makedirs(dir_) + with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f: + f.write(cross_content) + name = os.path.basename(f.name) + + with mock.patch.dict(os.environ, {'XDG_DATA_HOME': d}): + self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) + self.wipe() + + with mock.patch.dict(os.environ, {'XDG_DATA_DIRS': d}): + os.environ.pop('XDG_DATA_HOME', None) + self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) + self.wipe() + + with tempfile.TemporaryDirectory() as d: + dir_ = os.path.join(d, '.local', 'share', 'meson', 'cross') + os.makedirs(dir_) + with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f: + f.write(cross_content) + name = os.path.basename(f.name) + + # If XDG_DATA_HOME is set in the environment running the + # tests this test will fail, os mock the environment, pop + # it, then test + with mock.patch.dict(os.environ): + os.environ.pop('XDG_DATA_HOME', None) + with mock.patch('mesonbuild.coredata.os.path.expanduser', lambda x: x.replace('~', d)): + self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) + self.wipe() + + def helper_create_cross_file(self, values): + """Create a config file as a temporary file. + + values should be a nested dictionary structure of {section: {key: + value}} + """ + filename = os.path.join(self.builddir, f'generated{self.current_config}.config') + self.current_config += 1 + with open(filename, 'wt', encoding='utf-8') as f: + for section, entries in values.items(): + f.write(f'[{section}]\n') + for k, v in entries.items(): + f.write(f"{k}={v!r}\n") + return filename + + def test_cross_file_dirs(self): + testcase = os.path.join(self.unit_test_dir, '60 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '--cross-file', os.path.join(testcase, 'crossfile'), + '-Ddef_bindir=binbar', + '-Ddef_datadir=databar', + '-Ddef_includedir=includebar', + '-Ddef_infodir=infobar', + '-Ddef_libdir=libbar', + '-Ddef_libexecdir=libexecbar', + '-Ddef_localedir=localebar', + '-Ddef_localstatedir=localstatebar', + '-Ddef_mandir=manbar', + '-Ddef_sbindir=sbinbar', + '-Ddef_sharedstatedir=sharedstatebar', + '-Ddef_sysconfdir=sysconfbar']) + + def test_cross_file_dirs_overridden(self): + testcase = os.path.join(self.unit_test_dir, '60 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '--cross-file', os.path.join(testcase, 'crossfile'), + '-Ddef_libdir=liblib', '-Dlibdir=liblib', + '-Ddef_bindir=binbar', + '-Ddef_datadir=databar', + '-Ddef_includedir=includebar', + '-Ddef_infodir=infobar', + '-Ddef_libexecdir=libexecbar', + '-Ddef_localedir=localebar', + '-Ddef_localstatedir=localstatebar', + '-Ddef_mandir=manbar', + '-Ddef_sbindir=sbinbar', + '-Ddef_sharedstatedir=sharedstatebar', + '-Ddef_sysconfdir=sysconfbar']) + + def test_cross_file_dirs_chain(self): + # crossfile2 overrides crossfile overrides nativefile + testcase = os.path.join(self.unit_test_dir, '60 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '--cross-file', os.path.join(testcase, 'crossfile'), + '--cross-file', os.path.join(testcase, 'crossfile2'), + '-Ddef_bindir=binbar2', + '-Ddef_datadir=databar', + '-Ddef_includedir=includebar', + '-Ddef_infodir=infobar', + '-Ddef_libdir=libbar', + '-Ddef_libexecdir=libexecbar', + '-Ddef_localedir=localebar', + '-Ddef_localstatedir=localstatebar', + '-Ddef_mandir=manbar', + '-Ddef_sbindir=sbinbar', + '-Ddef_sharedstatedir=sharedstatebar', + '-Ddef_sysconfdir=sysconfbar']) + + def test_user_options(self): + # This is just a touch test for cross file, since the implementation + # shares code after loading from the files + testcase = os.path.join(self.common_test_dir, '40 options') + config = self.helper_create_cross_file({'project options': {'testoption': 'some other value'}}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--cross-file', config]) + self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + def test_builtin_options(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_cross_file({'built-in options': {'cpp_std': 'c++14'}}) + + self.init(testcase, extra_args=['--cross-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++14') + break + else: + self.fail('No c++ standard set?') + + def test_builtin_options_per_machine(self): + """Test options that are allowed to be set on a per-machine basis. + + Such options could be passed twice, once for the build machine, and + once for the host machine. I've picked pkg-config path, but any would + do that can be set for both. + """ + testcase = os.path.join(self.common_test_dir, '2 cpp') + cross = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/cross/path', 'cpp_std': 'c++17'}}) + native = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/native/path', 'cpp_std': 'c++14'}}) + + # Ensure that PKG_CONFIG_PATH is not set in the environment + with mock.patch.dict('os.environ'): + for k in ['PKG_CONFIG_PATH', 'PKG_CONFIG_PATH_FOR_BUILD']: + try: + del os.environ[k] + except KeyError: + pass + self.init(testcase, extra_args=['--cross-file', cross, '--native-file', native]) + + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/cross/path']) + found += 1 + elif each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++17') + found += 1 + elif each['name'] == 'build.pkg_config_path': + self.assertEqual(each['value'], ['/native/path']) + found += 1 + elif each['name'] == 'build.cpp_std': + self.assertEqual(each['value'], 'c++14') + found += 1 + + if found == 4: + break + self.assertEqual(found, 4, 'Did not find all sections.') + + def test_builtin_options_conf_overrides_env(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/native', 'cpp_args': '-DFILE'}}) + cross = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/cross', 'cpp_args': '-DFILE'}}) + + self.init(testcase, extra_args=['--native-file', config, '--cross-file', cross], + override_envvars={'PKG_CONFIG_PATH': '/bar', 'PKG_CONFIG_PATH_FOR_BUILD': '/dir', + 'CXXFLAGS': '-DENV', 'CXXFLAGS_FOR_BUILD': '-DENV'}) + configuration = self.introspect('--buildoptions') + found = 0 + expected = 4 + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/cross']) + found += 1 + elif each['name'] == 'build.pkg_config_path': + self.assertEqual(each['value'], ['/native']) + found += 1 + elif each['name'].endswith('cpp_args'): + self.assertEqual(each['value'], ['-DFILE']) + found += 1 + if found == expected: + break + self.assertEqual(found, expected, 'Did not find all sections.') + + def test_for_build_env_vars(self) -> None: + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_cross_file({'built-in options': {}}) + cross = self.helper_create_cross_file({'built-in options': {}}) + + self.init(testcase, extra_args=['--native-file', config, '--cross-file', cross], + override_envvars={'PKG_CONFIG_PATH': '/bar', 'PKG_CONFIG_PATH_FOR_BUILD': '/dir'}) + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/bar']) + found += 1 + elif each['name'] == 'build.pkg_config_path': + self.assertEqual(each['value'], ['/dir']) + found += 1 + if found == 2: + break + self.assertEqual(found, 2, 'Did not find all sections.') + + def test_project_options_native_only(self) -> None: + # Do not load project options from a native file when doing a cross + # build + testcase = os.path.join(self.unit_test_dir, '19 array option') + config = self.helper_create_cross_file({'project options': {'list': ['bar', 'foo']}}) + cross = self.helper_create_cross_file({'binaries': {}}) + + self.init(testcase, extra_args=['--native-file', config, '--cross-file', cross]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'list': + self.assertEqual(each['value'], ['foo', 'bar']) + break + else: + self.fail('Did not find expected option.') diff -Nru meson-0.53.2/unittests/platformagnostictests.py meson-0.61.2/unittests/platformagnostictests.py --- meson-0.53.2/unittests/platformagnostictests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/platformagnostictests.py 2022-01-02 20:12:32.000000000 +0000 @@ -0,0 +1,72 @@ +# Copyright 2021 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 tempfile +from unittest import skipIf + +from .baseplatformtests import BasePlatformTests +from .helpers import is_ci +from mesonbuild.mesonlib import is_linux +from mesonbuild.optinterpreter import OptionInterpreter, OptionException + +@skipIf(is_ci() and not is_linux(), "Run only on fast platforms") +class PlatformAgnosticTests(BasePlatformTests): + ''' + Tests that does not need to run on all platforms during CI + ''' + + def test_relative_find_program(self): + ''' + Tests that find_program() with a relative path does not find the program + in current workdir. + ''' + testdir = os.path.join(self.unit_test_dir, '101 relative find program') + self.init(testdir, workdir=testdir) + + def test_invalid_option_names(self): + interp = OptionInterpreter('') + + def write_file(code: str): + with tempfile.NamedTemporaryFile('w', dir=self.builddir, encoding='utf-8', delete=False) as f: + f.write(code) + return f.name + + fname = write_file("option('default_library', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option name default_library is reserved.', + interp.process, fname) + + fname = write_file("option('c_anything', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option name c_anything is reserved.', + interp.process, fname) + + fname = write_file("option('b_anything', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option name b_anything is reserved.', + interp.process, fname) + + fname = write_file("option('backend_anything', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option name backend_anything is reserved.', + interp.process, fname) + + fname = write_file("option('foo.bar', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option names can only contain letters, numbers or dashes.', + interp.process, fname) + + # platlib is allowed, only python.platlib is reserved. + fname = write_file("option('platlib', type: 'string')") + interp.process(fname) + + def test_python_dependency_without_pkgconfig(self): + testdir = os.path.join(self.unit_test_dir, '103 python without pkgconfig') + self.init(testdir, override_envvars={'PKG_CONFIG': 'notfound'}) diff -Nru meson-0.53.2/unittests/pythontests.py meson-0.61.2/unittests/pythontests.py --- meson-0.53.2/unittests/pythontests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/pythontests.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,82 @@ +# Copyright 2016-2021 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 unittest + +from run_tests import ( + Backend +) + +from .baseplatformtests import BasePlatformTests + +class PythonTests(BasePlatformTests): + ''' + Tests that verify compilation of python extension modules + ''' + + def test_versions(self): + if self.backend is not Backend.ninja: + raise unittest.SkipTest(f'Skipping python tests with {self.backend.name} backend') + + testdir = os.path.join(self.src_root, 'test cases', 'unit', '39 python extmodule') + + # No python version specified, this will use meson's python + self.init(testdir) + self.build() + self.run_tests() + self.wipe() + + # When specifying a known name, (python2 / python3) the module + # will also try 'python' as a fallback and use it if the major + # version matches + try: + self.init(testdir, extra_args=['-Dpython=python2']) + self.build() + self.run_tests() + except unittest.SkipTest: + # python2 is not necessarily installed on the test machine, + # if it is not, or the python headers can't be found, the test + # will raise MESON_SKIP_TEST, we could check beforehand what version + # of python is available, but it's a bit of a chicken and egg situation, + # as that is the job of the module, so we just ask for forgiveness rather + # than permission. + pass + + self.wipe() + + for py in ('pypy', 'pypy3'): + try: + self.init(testdir, extra_args=['-Dpython=%s' % py]) + except unittest.SkipTest: + # Same as above, pypy2 and pypy3 are not expected to be present + # on the test system, the test project only raises in these cases + continue + + # We have a pypy, this is expected to work + self.build() + self.run_tests() + self.wipe() + + # The test is configured to error out with MESON_SKIP_TEST + # in case it could not find python + with self.assertRaises(unittest.SkipTest): + self.init(testdir, extra_args=['-Dpython=not-python']) + self.wipe() + + # While dir is an external command on both Windows and Linux, + # it certainly isn't python + with self.assertRaises(unittest.SkipTest): + self.init(testdir, extra_args=['-Dpython=dir']) + self.wipe() diff -Nru meson-0.53.2/unittests/rewritetests.py meson-0.61.2/unittests/rewritetests.py --- meson-0.53.2/unittests/rewritetests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/rewritetests.py 2022-02-14 19:03:13.000000000 +0000 @@ -0,0 +1,399 @@ +# Copyright 2016-2021 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 subprocess +import json +import os +import shutil +import unittest + +from mesonbuild.mesonlib import windows_proof_rmtree +from .baseplatformtests import BasePlatformTests + +class RewriterTests(BasePlatformTests): + def setUp(self): + super().setUp() + self.maxDiff = None + + def prime(self, dirname): + if os.path.exists(self.builddir): + windows_proof_rmtree(self.builddir) + shutil.copytree(os.path.join(self.rewrite_test_dir, dirname), self.builddir) + + def rewrite_raw(self, directory, args): + 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) + print('STDOUT:') + print(p.stdout) + print('STDERR:') + print(p.stderr) + if p.returncode != 0: + if 'MESON_SKIP_TEST' in p.stdout: + raise unittest.SkipTest('Project requested skipping.') + raise subprocess.CalledProcessError(p.returncode, command, output=p.stdout) + if not p.stderr: + return {} + return json.loads(p.stderr) + + def rewrite(self, directory, args): + if isinstance(args, str): + args = [args] + return self.rewrite_raw(directory, ['command'] + args) + + def test_target_source_list(self): + self.prime('1 basic') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + def test_target_add_sources(self): + self.prime('1 basic') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['a5.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['a5.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['a3.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp', 'a4.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) + + def test_target_add_sources_abs(self): + self.prime('1 basic') + abs_src = [os.path.join(self.builddir, x) for x in ['a1.cpp', 'a2.cpp', 'a6.cpp']] + add = json.dumps([{"type": "target", "target": "trivialprog1", "operation": "src_add", "sources": abs_src}]) + inf = json.dumps([{"type": "target", "target": "trivialprog1", "operation": "info"}]) + self.rewrite(self.builddir, add) + out = self.rewrite(self.builddir, inf) + expected = {'target': {'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}}} + self.assertDictEqual(out, expected) + + def test_target_remove_sources(self): + self.prime('1 basic') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'rmSrc.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileC.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) + + def test_target_subdir(self): + self.prime('2 subdirs') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) + expected = {'name': 'something', 'sources': ['first.c', 'second.c', 'third.c'], 'extra_files': []} + self.assertDictEqual(list(out['target'].values())[0], expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(list(out['target'].values())[0], expected) + + def test_target_remove(self): + self.prime('1 basic') + self.rewrite(self.builddir, os.path.join(self.builddir, 'rmTgt.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + + expected = { + 'target': { + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + def test_tatrget_add(self): + self.prime('1 basic') + self.rewrite(self.builddir, os.path.join(self.builddir, 'addTgt.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog10@sha': {'name': 'trivialprog10', 'sources': ['new1.cpp', 'new2.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + def test_target_remove_subdir(self): + self.prime('2 subdirs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'rmTgt.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, {}) + + def test_target_add_subdir(self): + self.prime('2 subdirs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'addTgt.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = {'name': 'something', 'sources': ['first.c', 'second.c'], 'extra_files': []} + self.assertDictEqual(out['target']['94b671c@@something@exe'], expected) + + def test_target_source_sorting(self): + self.prime('5 sorting') + add_json = json.dumps([{'type': 'target', 'target': 'exe1', 'operation': 'src_add', 'sources': ['a666.c']}]) + inf_json = json.dumps([{'type': 'target', 'target': 'exe1', 'operation': 'info'}]) + out = self.rewrite(self.builddir, add_json) + out = self.rewrite(self.builddir, inf_json) + expected = { + 'target': { + 'exe1@exe': { + 'name': 'exe1', + 'sources': [ + 'aaa/a/a1.c', + 'aaa/b/b1.c', + 'aaa/b/b2.c', + 'aaa/f1.c', + 'aaa/f2.c', + 'aaa/f3.c', + 'bbb/a/b1.c', + 'bbb/b/b2.c', + 'bbb/c1/b5.c', + 'bbb/c2/b7.c', + 'bbb/c10/b6.c', + 'bbb/a4.c', + 'bbb/b3.c', + 'bbb/b4.c', + 'bbb/b5.c', + 'a1.c', + 'a2.c', + 'a3.c', + 'a10.c', + 'a20.c', + 'a30.c', + 'a100.c', + 'a101.c', + 'a110.c', + 'a210.c', + 'a666.c', + 'b1.c', + 'c2.c' + ], + 'extra_files': [] + } + } + } + self.assertDictEqual(out, expected) + + def test_target_same_name_skip(self): + self.prime('4 same name targets') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = {'name': 'myExe', 'sources': ['main.cpp'], 'extra_files': []} + self.assertEqual(len(out['target']), 2) + for val in out['target'].values(): + self.assertDictEqual(expected, val) + + def test_kwargs_info(self): + self.prime('3 kwargs') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1'}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_set(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'set.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.2', 'meson_version': '0.50.0', 'license': ['GPL', 'MIT']}, + 'target#tgt1': {'build_by_default': False, 'build_rpath': '/usr/local', 'dependencies': 'dep1'}, + 'dependency#dep1': {'required': True, 'method': 'cmake'} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_add(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'add.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'license': ['GPL', 'MIT', 'BSD', 'Boost']}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_remove(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'remove.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'license': 'GPL'}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_remove_regex(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'remove_regex.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'default_options': 'debug=true'}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_delete(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'delete.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {}, + 'target#tgt1': {}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_default_options_set(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'defopts_set.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'default_options': ['buildtype=release', 'debug=True', 'cpp_std=c++11']}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_default_options_delete(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'defopts_delete.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'default_options': ['cpp_std=c++14', 'debug=true']}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_target_add_extra_files(self): + self.prime('6 extra_files') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addExtraFiles.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp', 'a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['main.cpp'], 'extra_files': ['a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': ['a5.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': ['a5.hpp', 'main.hpp', 'fileA.hpp']}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp'], 'extra_files': ['a3.hpp', 'main.hpp', 'a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': ['a2.hpp', 'a7.hpp']}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': ['a8.hpp', 'a9.hpp']}, + 'trivialprog10@exe': {'name': 'trivialprog10', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a4.hpp']}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) + + def test_target_remove_extra_files(self): + self.prime('6 extra_files') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'rmExtraFiles.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp'], 'extra_files': ['main.hpp', 'fileC.hpp']}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['main.cpp'], 'extra_files': ['fileC.hpp']}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp'], 'extra_files': ['main.hpp', 'fileC.hpp']}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog10@exe': {'name': 'trivialprog10', 'sources': ['main.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) diff -Nru meson-0.53.2/unittests/subprojectscommandtests.py meson-0.61.2/unittests/subprojectscommandtests.py --- meson-0.53.2/unittests/subprojectscommandtests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/subprojectscommandtests.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,286 @@ +# Copyright 2016-2021 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 subprocess +import tempfile +import textwrap +import os +from pathlib import Path +import typing as T + +from mesonbuild.mesonlib import ( + version_compare, git, search_version +) + + + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +class SubprojectsCommandTests(BasePlatformTests): + def setUp(self): + super().setUp() + self.root_dir = Path(self.builddir) + + self.project_dir = self.root_dir / 'src' + self._create_project(self.project_dir) + + self.subprojects_dir = self.project_dir / 'subprojects' + os.makedirs(str(self.subprojects_dir)) + self.packagecache_dir = self.subprojects_dir / 'packagecache' + os.makedirs(str(self.packagecache_dir)) + + def _create_project(self, path, project_name='dummy'): + os.makedirs(str(path), exist_ok=True) + with open(str(path / 'meson.build'), 'w', encoding='utf-8') as f: + f.write(f"project('{project_name}')") + + def _git(self, cmd, workdir): + return git(cmd, str(workdir), check=True)[1].strip() + + def _git_config(self, workdir): + self._git(['config', 'user.name', 'Meson Test'], workdir) + self._git(['config', 'user.email', 'meson.test@example.com'], workdir) + + def _git_remote(self, cmd, name): + return self._git(cmd, self.root_dir / name) + + def _git_local(self, cmd, name): + return self._git(cmd, self.subprojects_dir / name) + + def _git_local_branch(self, name): + # Same as `git branch --show-current` but compatible with older git version + branch = self._git_local(['rev-parse', '--abbrev-ref', 'HEAD'], name) + return branch if branch != 'HEAD' else '' + + def _git_local_commit(self, name, ref='HEAD'): + return self._git_local(['rev-parse', ref], name) + + def _git_remote_commit(self, name, ref='HEAD'): + return self._git_remote(['rev-parse', ref], name) + + def _git_create_repo(self, path): + # If a user has git configuration init.defaultBranch set we want to override that + with tempfile.TemporaryDirectory() as d: + out = git(['--version'], str(d))[1] + if version_compare(search_version(out), '>= 2.28'): + extra_cmd = ['--initial-branch', 'master'] + else: + extra_cmd = [] + + self._create_project(path) + self._git(['init'] + extra_cmd, path) + self._git_config(path) + self._git(['add', '.'], path) + self._git(['commit', '--no-gpg-sign', '-m', 'Initial commit'], path) + + def _git_create_remote_repo(self, name): + self._git_create_repo(self.root_dir / name) + + def _git_create_local_repo(self, name): + self._git_create_repo(self.subprojects_dir / name) + + def _git_create_remote_commit(self, name, branch): + self._git_remote(['checkout', branch], name) + self._git_remote(['commit', '--no-gpg-sign', '--allow-empty', '-m', f'initial {branch} commit'], name) + + def _git_create_remote_branch(self, name, branch): + self._git_remote(['checkout', '-b', branch], name) + self._git_remote(['commit', '--no-gpg-sign', '--allow-empty', '-m', f'initial {branch} commit'], name) + + def _git_create_remote_tag(self, name, tag): + self._git_remote(['commit', '--no-gpg-sign', '--allow-empty', '-m', f'tag {tag} commit'], name) + self._git_remote(['tag', '--no-sign', tag], name) + + def _wrap_create_git(self, name, revision='master'): + path = self.root_dir / name + with open(str((self.subprojects_dir / name).with_suffix('.wrap')), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + ''' + [wrap-git] + url={} + revision={} + '''.format(os.path.abspath(str(path)), revision))) + + def _wrap_create_file(self, name, tarball='dummy.tar.gz'): + path = self.root_dir / tarball + with open(str((self.subprojects_dir / name).with_suffix('.wrap')), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + f''' + [wrap-file] + source_url={os.path.abspath(str(path))} + source_filename={tarball} + ''')) + Path(self.packagecache_dir / tarball).touch() + + def _subprojects_cmd(self, args): + return self._run(self.meson_command + ['subprojects'] + args, workdir=str(self.project_dir)) + + def test_git_update(self): + subp_name = 'sub1' + + # Create a fake remote git repository and a wrap file. Checks that + # "meson subprojects download" works. + self._git_create_remote_repo(subp_name) + self._wrap_create_git(subp_name) + self._subprojects_cmd(['download']) + self.assertPathExists(str(self.subprojects_dir / subp_name)) + self._git_config(self.subprojects_dir / subp_name) + + # Create a new remote branch and update the wrap file. Checks that + # "meson subprojects update --reset" checkout the new branch. + self._git_create_remote_branch(subp_name, 'newbranch') + self._wrap_create_git(subp_name, 'newbranch') + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), 'newbranch') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) + + # Update remote newbranch. Checks the new commit is pulled into existing + # local newbranch. Make sure it does not print spurious 'git stash' message. + self._git_create_remote_commit(subp_name, 'newbranch') + out = self._subprojects_cmd(['update', '--reset']) + self.assertNotIn('No local changes to save', out) + self.assertEqual(self._git_local_branch(subp_name), 'newbranch') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) + + # Update remote newbranch and switch to another branch. Checks that it + # switch current branch to newbranch and pull latest commit. + self._git_local(['checkout', 'master'], subp_name) + self._git_create_remote_commit(subp_name, 'newbranch') + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), 'newbranch') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) + + # Stage some local changes then update. Checks that local changes got + # stashed. + self._create_project(self.subprojects_dir / subp_name, 'new_project_name') + self._git_local(['add', '.'], subp_name) + self._git_create_remote_commit(subp_name, 'newbranch') + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), 'newbranch') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) + self.assertTrue(self._git_local(['stash', 'list'], subp_name)) + + # Create a new remote tag and update the wrap file. Checks that + # "meson subprojects update --reset" checkout the new tag in detached mode. + self._git_create_remote_tag(subp_name, 'newtag') + self._wrap_create_git(subp_name, 'newtag') + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), '') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newtag')) + + # Create a new remote commit and update the wrap file with the commit id. + # Checks that "meson subprojects update --reset" checkout the new commit + # in detached mode. + self._git_local(['checkout', 'master'], subp_name) + self._git_create_remote_commit(subp_name, 'newbranch') + new_commit = self._git_remote(['rev-parse', 'HEAD'], subp_name) + self._wrap_create_git(subp_name, new_commit) + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), '') + self.assertEqual(self._git_local_commit(subp_name), new_commit) + + # Create a local project not in a git repository, then update it with + # a git wrap. Without --reset it should print error message and return + # failure. With --reset it should delete existing project and clone the + # new project. + subp_name = 'sub2' + self._create_project(self.subprojects_dir / subp_name) + self._git_create_remote_repo(subp_name) + self._wrap_create_git(subp_name) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self._subprojects_cmd(['update']) + self.assertIn('Not a git repository', cm.exception.output) + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name)) + + @skipIfNoExecutable('true') + def test_foreach(self): + self._create_project(self.subprojects_dir / 'sub_file') + self._wrap_create_file('sub_file') + self._git_create_local_repo('sub_git') + self._wrap_create_git('sub_git') + self._git_create_local_repo('sub_git_no_wrap') + + def ran_in(s): + ret = [] + prefix = 'Executing command in ' + for l in s.splitlines(): + if l.startswith(prefix): + ret.append(l[len(prefix):]) + return sorted(ret) + + dummy_cmd = ['true'] + out = self._subprojects_cmd(['foreach'] + dummy_cmd) + self.assertEqual(ran_in(out), sorted(['subprojects/sub_file', 'subprojects/sub_git', 'subprojects/sub_git_no_wrap'])) + out = self._subprojects_cmd(['foreach', '--types', 'git,file'] + dummy_cmd) + self.assertEqual(ran_in(out), sorted(['subprojects/sub_file', 'subprojects/sub_git'])) + out = self._subprojects_cmd(['foreach', '--types', 'file'] + dummy_cmd) + self.assertEqual(ran_in(out), ['subprojects/sub_file']) + out = self._subprojects_cmd(['foreach', '--types', 'git'] + dummy_cmd) + self.assertEqual(ran_in(out), ['subprojects/sub_git']) + + def test_purge(self): + self._create_project(self.subprojects_dir / 'sub_file') + self._wrap_create_file('sub_file') + self._git_create_local_repo('sub_git') + self._wrap_create_git('sub_git') + + sub_file_subprojects_dir = self.subprojects_dir / 'sub_file' / 'subprojects' + sub_file_subprojects_dir.mkdir(exist_ok=True, parents=True) + real_dir = Path('sub_file') / 'subprojects' / 'real' + + self._wrap_create_file(real_dir, tarball='dummy2.tar.gz') + + with open(str((self.subprojects_dir / 'redirect').with_suffix('.wrap')), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + f''' + [wrap-redirect] + filename = {real_dir}.wrap + ''')) + + def deleting(s: str) -> T.List[str]: + ret = [] + prefix = 'Deleting ' + for l in s.splitlines(): + if l.startswith(prefix): + ret.append(l[len(prefix):]) + return sorted(ret) + + out = self._subprojects_cmd(['purge']) + self.assertEqual(deleting(out), sorted([ + str(self.subprojects_dir / 'redirect.wrap'), + str(self.subprojects_dir / 'sub_file'), + str(self.subprojects_dir / 'sub_git'), + ])) + out = self._subprojects_cmd(['purge', '--include-cache']) + self.assertEqual(deleting(out), sorted([ + str(self.subprojects_dir / 'sub_git'), + str(self.subprojects_dir / 'redirect.wrap'), + str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'), + str(self.subprojects_dir / 'packagecache' / 'dummy2.tar.gz'), + str(self.subprojects_dir / 'sub_file'), + ])) + out = self._subprojects_cmd(['purge', '--include-cache', '--confirm']) + self.assertEqual(deleting(out), sorted([ + str(self.subprojects_dir / 'sub_git'), + str(self.subprojects_dir / 'redirect.wrap'), + str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'), + str(self.subprojects_dir / 'packagecache' / 'dummy2.tar.gz'), + str(self.subprojects_dir / 'sub_file'), + ])) + self.assertFalse(Path(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz').exists()) + self.assertFalse(Path(self.subprojects_dir / 'sub_file').exists()) + self.assertFalse(Path(self.subprojects_dir / 'sub_git').exists()) + self.assertFalse(Path(self.subprojects_dir / 'redirect.wrap').exists()) diff -Nru meson-0.53.2/unittests/taptests.py meson-0.61.2/unittests/taptests.py --- meson-0.53.2/unittests/taptests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/taptests.py 2021-11-02 19:58:07.000000000 +0000 @@ -0,0 +1,291 @@ +# Copyright 2016-2021 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 unittest +import io + +from mesonbuild.mtest import TAPParser, TestResult + + +class TAPParserTests(unittest.TestCase): + def assert_test(self, events, **kwargs): + if 'explanation' not in kwargs: + kwargs['explanation'] = None + self.assertEqual(next(events), TAPParser.Test(**kwargs)) + + def assert_plan(self, events, **kwargs): + if 'skipped' not in kwargs: + kwargs['skipped'] = False + if 'explanation' not in kwargs: + kwargs['explanation'] = None + self.assertEqual(next(events), TAPParser.Plan(**kwargs)) + + def assert_version(self, events, **kwargs): + self.assertEqual(next(events), TAPParser.Version(**kwargs)) + + def assert_error(self, events): + self.assertEqual(type(next(events)), TAPParser.Error) + + def assert_bailout(self, events, **kwargs): + self.assertEqual(next(events), TAPParser.Bailout(**kwargs)) + + def assert_last(self, events): + with self.assertRaises(StopIteration): + next(events) + + def parse_tap(self, s): + parser = TAPParser() + return iter(parser.parse(io.StringIO(s))) + + def parse_tap_v13(self, s): + events = self.parse_tap('TAP version 13\n' + s) + self.assert_version(events, version=13) + return events + + def test_empty(self): + events = self.parse_tap('') + self.assert_last(events) + + def test_empty_plan(self): + events = self.parse_tap('1..0') + self.assert_plan(events, num_tests=0, late=False, skipped=True) + self.assert_last(events) + + def test_plan_directive(self): + events = self.parse_tap('1..0 # skipped for some reason') + self.assert_plan(events, num_tests=0, late=False, skipped=True, + explanation='for some reason') + self.assert_last(events) + + events = self.parse_tap('1..1 # skipped for some reason\nok 1') + self.assert_error(events) + self.assert_plan(events, num_tests=1, late=False, skipped=True, + explanation='for some reason') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + events = self.parse_tap('1..1 # todo not supported here\nok 1') + self.assert_error(events) + self.assert_plan(events, num_tests=1, late=False, skipped=False, + explanation='not supported here') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_ok(self): + events = self.parse_tap('ok') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_with_number(self): + events = self.parse_tap('ok 1') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_with_name(self): + events = self.parse_tap('ok 1 abc') + self.assert_test(events, number=1, name='abc', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_not_ok(self): + events = self.parse_tap('not ok') + self.assert_test(events, number=1, name='', result=TestResult.FAIL) + self.assert_last(events) + + def test_one_test_todo(self): + events = self.parse_tap('not ok 1 abc # TODO') + self.assert_test(events, number=1, name='abc', result=TestResult.EXPECTEDFAIL) + self.assert_last(events) + + events = self.parse_tap('ok 1 abc # TODO') + self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS) + self.assert_last(events) + + def test_one_test_skip(self): + events = self.parse_tap('ok 1 abc # SKIP') + self.assert_test(events, number=1, name='abc', result=TestResult.SKIP) + self.assert_last(events) + + def test_one_test_skip_failure(self): + events = self.parse_tap('not ok 1 abc # SKIP') + self.assert_test(events, number=1, name='abc', result=TestResult.FAIL) + self.assert_last(events) + + def test_many_early_plan(self): + events = self.parse_tap('1..4\nok 1\nnot ok 2\nok 3\nnot ok 4') + self.assert_plan(events, num_tests=4, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_test(events, number=3, name='', result=TestResult.OK) + self.assert_test(events, number=4, name='', result=TestResult.FAIL) + self.assert_last(events) + + def test_many_late_plan(self): + events = self.parse_tap('ok 1\nnot ok 2\nok 3\nnot ok 4\n1..4') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_test(events, number=3, name='', result=TestResult.OK) + self.assert_test(events, number=4, name='', result=TestResult.FAIL) + self.assert_plan(events, num_tests=4, late=True) + self.assert_last(events) + + def test_directive_case(self): + events = self.parse_tap('ok 1 abc # skip') + self.assert_test(events, number=1, name='abc', result=TestResult.SKIP) + self.assert_last(events) + + events = self.parse_tap('ok 1 abc # ToDo') + self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS) + self.assert_last(events) + + def test_directive_explanation(self): + events = self.parse_tap('ok 1 abc # skip why') + self.assert_test(events, number=1, name='abc', result=TestResult.SKIP, + explanation='why') + self.assert_last(events) + + events = self.parse_tap('ok 1 abc # ToDo Because') + self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS, + explanation='Because') + self.assert_last(events) + + def test_one_test_early_plan(self): + events = self.parse_tap('1..1\nok') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_late_plan(self): + events = self.parse_tap('ok\n1..1') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_plan(events, num_tests=1, late=True) + self.assert_last(events) + + def test_out_of_order(self): + events = self.parse_tap('ok 2') + self.assert_error(events) + self.assert_test(events, number=2, name='', result=TestResult.OK) + self.assert_last(events) + + def test_middle_plan(self): + events = self.parse_tap('ok 1\n1..2\nok 2') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_plan(events, num_tests=2, late=True) + self.assert_error(events) + self.assert_test(events, number=2, name='', result=TestResult.OK) + self.assert_last(events) + + def test_too_many_plans(self): + events = self.parse_tap('1..1\n1..2\nok 1') + self.assert_plan(events, num_tests=1, late=False) + self.assert_error(events) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_too_many(self): + events = self.parse_tap('ok 1\nnot ok 2\n1..1') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_plan(events, num_tests=1, late=True) + self.assert_error(events) + self.assert_last(events) + + events = self.parse_tap('1..1\nok 1\nnot ok 2') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_error(events) + self.assert_last(events) + + def test_too_few(self): + events = self.parse_tap('ok 1\nnot ok 2\n1..3') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_plan(events, num_tests=3, late=True) + self.assert_error(events) + self.assert_last(events) + + events = self.parse_tap('1..3\nok 1\nnot ok 2') + self.assert_plan(events, num_tests=3, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_error(events) + self.assert_last(events) + + def test_too_few_bailout(self): + events = self.parse_tap('1..3\nok 1\nnot ok 2\nBail out! no third test') + self.assert_plan(events, num_tests=3, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_bailout(events, message='no third test') + self.assert_last(events) + + def test_diagnostics(self): + events = self.parse_tap('1..1\n# ignored\nok 1') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + events = self.parse_tap('# ignored\n1..1\nok 1\n# ignored too') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + events = self.parse_tap('# ignored\nok 1\n1..1\n# ignored too') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_plan(events, num_tests=1, late=True) + self.assert_last(events) + + def test_empty_line(self): + events = self.parse_tap('1..1\n\nok 1') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_unexpected(self): + events = self.parse_tap('1..1\ninvalid\nok 1') + self.assert_plan(events, num_tests=1, late=False) + self.assert_error(events) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_version(self): + events = self.parse_tap('TAP version 13\n') + self.assert_version(events, version=13) + self.assert_last(events) + + events = self.parse_tap('TAP version 12\n') + self.assert_error(events) + self.assert_last(events) + + events = self.parse_tap('1..0\nTAP version 13\n') + self.assert_plan(events, num_tests=0, late=False, skipped=True) + self.assert_error(events) + self.assert_last(events) + + def test_yaml(self): + events = self.parse_tap_v13('ok\n ---\n foo: abc\n bar: def\n ...\nok 2') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.OK) + self.assert_last(events) + + events = self.parse_tap_v13('ok\n ---\n foo: abc\n bar: def') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_error(events) + self.assert_last(events) + + events = self.parse_tap_v13('ok 1\n ---\n foo: abc\n bar: def\nnot ok 2') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_error(events) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_last(events) diff -Nru meson-0.53.2/unittests/windowstests.py meson-0.61.2/unittests/windowstests.py --- meson-0.53.2/unittests/windowstests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-0.61.2/unittests/windowstests.py 2022-01-17 10:50:38.000000000 +0000 @@ -0,0 +1,401 @@ +# Copyright 2016-2021 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 subprocess +import re +import os +import shutil +from unittest import mock, SkipTest, skipUnless, skipIf +from glob import glob + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + MachineChoice, is_windows, is_cygwin, python_command, version_compare, + EnvironmentException, OptionKey +) +from mesonbuild.compilers import ( + detect_c_compiler, detect_d_compiler, compiler_from_language, + GnuLikeCompiler +) +from mesonbuild.programs import ExternalProgram +import mesonbuild.dependencies.base +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + Backend, get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@skipUnless(is_windows() or is_cygwin(), "requires Windows (or Windows via Cygwin)") +class WindowsTests(BasePlatformTests): + ''' + Tests that should run on Cygwin, MinGW, and MSVC + ''' + + def setUp(self): + super().setUp() + self.platform_test_dir = os.path.join(self.src_root, 'test cases/windows') + + @skipIf(is_cygwin(), 'Test only applicable to Windows') + @mock.patch.dict(os.environ) + def test_find_program(self): + ''' + Test that Windows-specific edge-cases in find_program are functioning + correctly. Cannot be an ordinary test because it involves manipulating + PATH to point to a directory with Python scripts. + ''' + testdir = os.path.join(self.platform_test_dir, '8 find program') + # Find `cmd` and `cmd.exe` + prog1 = ExternalProgram('cmd') + self.assertTrue(prog1.found(), msg='cmd not found') + prog2 = ExternalProgram('cmd.exe') + self.assertTrue(prog2.found(), msg='cmd.exe not found') + self.assertPathEqual(prog1.get_path(), prog2.get_path()) + # Find cmd.exe with args without searching + prog = ExternalProgram('cmd', command=['cmd', '/C']) + self.assertTrue(prog.found(), msg='cmd not found with args') + self.assertPathEqual(prog.get_command()[0], 'cmd') + # Find cmd with an absolute path that's missing the extension + cmd_path = prog2.get_path()[:-4] + prog = ExternalProgram(cmd_path) + self.assertTrue(prog.found(), msg=f'{cmd_path!r} not found') + # Finding a script with no extension inside a directory works + prog = ExternalProgram(os.path.join(testdir, 'test-script')) + self.assertTrue(prog.found(), msg='test-script not found') + # Finding a script with an extension inside a directory works + prog = ExternalProgram(os.path.join(testdir, 'test-script-ext.py')) + self.assertTrue(prog.found(), msg='test-script-ext.py not found') + # Finding a script in PATH + os.environ['PATH'] += os.pathsep + testdir + # If `.PY` is in PATHEXT, scripts can be found as programs + if '.PY' in [ext.upper() for ext in os.environ['PATHEXT'].split(';')]: + # Finding a script in PATH w/o extension works and adds the interpreter + prog = ExternalProgram('test-script-ext') + self.assertTrue(prog.found(), msg='test-script-ext not found in PATH') + self.assertPathEqual(prog.get_command()[0], python_command[0]) + self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py') + # Finding a script in PATH with extension works and adds the interpreter + prog = ExternalProgram('test-script-ext.py') + self.assertTrue(prog.found(), msg='test-script-ext.py not found in PATH') + self.assertPathEqual(prog.get_command()[0], python_command[0]) + self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py') + # Using a script with an extension directly via command= works and adds the interpreter + prog = ExternalProgram('test-script-ext.py', command=[os.path.join(testdir, 'test-script-ext.py'), '--help']) + self.assertTrue(prog.found(), msg='test-script-ext.py with full path not picked up via command=') + self.assertPathEqual(prog.get_command()[0], python_command[0]) + self.assertPathEqual(prog.get_command()[2], '--help') + self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py') + # Using a script without an extension directly via command= works and adds the interpreter + prog = ExternalProgram('test-script', command=[os.path.join(testdir, 'test-script'), '--help']) + self.assertTrue(prog.found(), msg='test-script with full path not picked up via command=') + self.assertPathEqual(prog.get_command()[0], python_command[0]) + self.assertPathEqual(prog.get_command()[2], '--help') + self.assertPathBasenameEqual(prog.get_path(), 'test-script') + # Ensure that WindowsApps gets removed from PATH + path = os.environ['PATH'] + if 'WindowsApps' not in path: + username = os.environ['USERNAME'] + appstore_dir = fr'C:\Users\{username}\AppData\Local\Microsoft\WindowsApps' + path = os.pathsep + appstore_dir + path = ExternalProgram._windows_sanitize_path(path) + self.assertNotIn('WindowsApps', path) + + def test_ignore_libs(self): + ''' + Test that find_library on libs that are to be ignored returns an empty + array of arguments. Must be a unit test because we cannot inspect + ExternalLibraryHolder from build files. + ''' + testdir = os.path.join(self.platform_test_dir, '1 basic') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise SkipTest('Not using MSVC') + # To force people to update this test, and also test + self.assertEqual(set(cc.ignore_libs), {'c', 'm', 'pthread', 'dl', 'rt', 'execinfo'}) + for l in cc.ignore_libs: + self.assertEqual(cc.find_library(l, env, []), []) + + def test_rc_depends_files(self): + testdir = os.path.join(self.platform_test_dir, '5 resources') + + # resource compiler depfile generation is not yet implemented for msvc + env = get_fake_env(testdir, self.builddir, self.prefix) + depfile_works = detect_c_compiler(env, MachineChoice.HOST).get_id() not in {'msvc', 'clang-cl', 'intel-cl'} + + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Test compile_resources(depend_file:) + # Changing mtime of sample.ico should rebuild prog + self.utime(os.path.join(testdir, 'res', 'sample.ico')) + self.assertRebuiltTarget('prog') + # Test depfile generation by compile_resources + # Changing mtime of resource.h should rebuild myres.rc and then prog + if depfile_works: + self.utime(os.path.join(testdir, 'inc', 'resource', 'resource.h')) + self.assertRebuiltTarget('prog') + self.wipe() + + if depfile_works: + testdir = os.path.join(self.platform_test_dir, '12 resources with custom targets') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of resource.h should rebuild myres_1.rc and then prog_1 + self.utime(os.path.join(testdir, 'res', 'resource.h')) + self.assertRebuiltTarget('prog_1') + + def test_msvc_cpp17(self): + testdir = os.path.join(self.unit_test_dir, '45 vscpp17') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise SkipTest('Test only applies to MSVC-like compilers') + + try: + self.init(testdir) + except subprocess.CalledProcessError: + # According to Python docs, output is only stored when + # using check_output. We don't use it, so we can't check + # that the output is correct (i.e. that it failed due + # to the right reason). + return + self.build() + + def test_install_pdb_introspection(self): + testdir = os.path.join(self.platform_test_dir, '1 basic') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise SkipTest('Test only applies to MSVC-like compilers') + + self.init(testdir) + installed = self.introspect('--installed') + files = [os.path.basename(path) for path in installed.values()] + + self.assertIn('prog.pdb', files) + + def _check_ld(self, name: str, lang: str, expected: str) -> None: + if not shutil.which(name): + raise SkipTest(f'Could not find {name}.') + envvars = [mesonbuild.envconfig.ENV_VAR_PROG_MAP[f'{lang}_ld']] + + # Also test a deprecated variable if there is one. + if f'{lang}_ld' in mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP: + envvars.append( + mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP[f'{lang}_ld']) + + for envvar in envvars: + with mock.patch.dict(os.environ, {envvar: name}): + env = get_fake_env() + try: + comp = compiler_from_language(env, lang, MachineChoice.HOST) + except EnvironmentException: + raise SkipTest(f'Could not find a compiler for {lang}') + self.assertEqual(comp.linker.id, expected) + + def test_link_environment_variable_lld_link(self): + env = get_fake_env() + comp = detect_c_compiler(env, MachineChoice.HOST) + if isinstance(comp, GnuLikeCompiler): + raise SkipTest('GCC cannot be used with link compatible linkers.') + self._check_ld('lld-link', 'c', 'lld-link') + + def test_link_environment_variable_link(self): + env = get_fake_env() + comp = detect_c_compiler(env, MachineChoice.HOST) + if isinstance(comp, GnuLikeCompiler): + raise SkipTest('GCC cannot be used with link compatible linkers.') + self._check_ld('link', 'c', 'link') + + def test_link_environment_variable_optlink(self): + env = get_fake_env() + comp = detect_c_compiler(env, MachineChoice.HOST) + if isinstance(comp, GnuLikeCompiler): + raise SkipTest('GCC cannot be used with link compatible linkers.') + self._check_ld('optlink', 'c', 'optlink') + + @skip_if_not_language('rust') + def test_link_environment_variable_rust(self): + self._check_ld('link', 'rust', 'link') + + @skip_if_not_language('d') + def test_link_environment_variable_d(self): + env = get_fake_env() + comp = detect_d_compiler(env, MachineChoice.HOST) + if comp.id == 'dmd': + raise SkipTest('meson cannot reliably make DMD use a different linker.') + self._check_ld('lld-link', 'd', 'lld-link') + + def test_pefile_checksum(self): + try: + import pefile + except ImportError: + if is_ci(): + raise + raise SkipTest('pefile module not found') + testdir = os.path.join(self.common_test_dir, '6 linkshared') + self.init(testdir, extra_args=['--buildtype=release']) + self.build() + # Test that binaries have a non-zero checksum + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + cc_id = cc.get_id() + ld_id = cc.get_linker_id() + dll = glob(os.path.join(self.builddir, '*mycpplib.dll'))[0] + exe = os.path.join(self.builddir, 'cppprog.exe') + for f in (dll, exe): + pe = pefile.PE(f) + msg = f'PE file: {f!r}, compiler: {cc_id!r}, linker: {ld_id!r}' + if cc_id == 'clang-cl': + # Latest clang-cl tested (7.0) does not write checksums out + self.assertFalse(pe.verify_checksum(), msg=msg) + else: + # Verify that a valid checksum was written by all other compilers + self.assertTrue(pe.verify_checksum(), msg=msg) + + def test_qt5dependency_vscrt(self): + ''' + Test that qt5 dependencies use the debug module suffix when b_vscrt is + set to 'mdd' + ''' + # Verify that the `b_vscrt` option is available + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if OptionKey('b_vscrt') not in cc.base_options: + raise SkipTest('Compiler does not support setting the VS CRT') + # Verify that qmake is for Qt5 + if not shutil.which('qmake-qt5'): + if not shutil.which('qmake') and not is_ci(): + raise SkipTest('QMake not found') + output = subprocess.getoutput('qmake --version') + if 'Qt version 5' not in output and not is_ci(): + raise SkipTest('Qmake found, but it is not for Qt 5.') + # Setup with /MDd + testdir = os.path.join(self.framework_test_dir, '4 qt') + self.init(testdir, extra_args=['-Db_vscrt=mdd']) + # Verify that we're linking to the debug versions of Qt DLLs + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + m = re.search('build qt5core.exe: cpp_LINKER.*Qt5Cored.lib', contents) + self.assertIsNotNone(m, msg=contents) + + def test_compiler_checks_vscrt(self): + ''' + Test that the correct VS CRT is used when running compiler checks + ''' + # Verify that the `b_vscrt` option is available + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if OptionKey('b_vscrt') not in cc.base_options: + raise SkipTest('Compiler does not support setting the VS CRT') + + def sanitycheck_vscrt(vscrt): + checks = self.get_meson_log_sanitychecks() + self.assertGreater(len(checks), 0) + for check in checks: + self.assertIn(vscrt, check) + + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + sanitycheck_vscrt('/MDd') + + self.new_builddir() + self.init(testdir, extra_args=['-Dbuildtype=debugoptimized']) + sanitycheck_vscrt('/MD') + + self.new_builddir() + self.init(testdir, extra_args=['-Dbuildtype=release']) + sanitycheck_vscrt('/MD') + + self.new_builddir() + self.init(testdir, extra_args=['-Db_vscrt=md']) + sanitycheck_vscrt('/MD') + + self.new_builddir() + self.init(testdir, extra_args=['-Db_vscrt=mdd']) + sanitycheck_vscrt('/MDd') + + self.new_builddir() + self.init(testdir, extra_args=['-Db_vscrt=mt']) + sanitycheck_vscrt('/MT') + + self.new_builddir() + self.init(testdir, extra_args=['-Db_vscrt=mtd']) + sanitycheck_vscrt('/MTd') + + def test_modules(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'C++ modules only work with the Ninja backend (not {self.backend.name}).') + if 'VSCMD_VER' not in os.environ: + raise SkipTest('C++ modules is only supported with Visual Studio.') + if version_compare(os.environ['VSCMD_VER'], '<16.10.0'): + raise SkipTest('C++ modules are only supported with VS 2019 Preview or newer.') + self.init(os.path.join(self.unit_test_dir, '86 cpp modules')) + self.build() + + def test_non_utf8_fails(self): + # FIXME: VS backend does not use flags from compiler.get_always_args() + # and thus it's missing /utf-8 argument. Was that intentional? This needs + # to be revisited. + if self.backend is not Backend.ninja: + raise SkipTest(f'This test only pass with ninja backend (not {self.backend.name}).') + testdir = os.path.join(self.platform_test_dir, '18 msvc charset') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + 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)